1 /*
2 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
3 */
4
5 /*
6 * BSD 3 Clause License
7 *
8 * Copyright (c) 2007, The Storage Networking Industry Association.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * - Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * - Neither the name of The Storage Networking Industry Association (SNIA)
22 * nor the names of its contributors may be used to endorse or promote
23 * products derived from this software without specific prior written
24 * permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38 /* Copyright (c) 2007, The Storage Networking Industry Association. */
39 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
40
41 #include <sys/types.h>
42 #include <stdlib.h>
43 #include <errno.h>
44 #include <stdarg.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include "ndmpd.h"
48
49
50 /*
51 * Message Id counter. This number is increased by MOD_LOGV3 macro.
52 * MOD_LOGCONTV3 macro uses the number generated by the last MOD_LOGV3.
53 *
54 */
55 int ndmp_log_msg_id = 0;
56
57
58 /*
59 * ************************************************************************
60 * NDMP V2 CALLBACKS
61 * ************************************************************************
62 */
63
64 /*
65 * ndmpd_api_done_v2
66 *
67 * Called when dump/restore has completed.
68 * Sends a notify_halt request to the NDMP client.
69 *
70 * Parameters:
71 * session (input) - session pointer.
72 * err (input) - UNIX error code.
73 *
74 * Returns:
75 * void
76 */
77 void
ndmpd_api_done_v2(void * cookie,int err)78 ndmpd_api_done_v2(void *cookie, int err)
79 {
80 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
81 ndmp_notify_data_halted_request req_v2;
82
83 if (session == NULL)
84 return;
85
86 if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE ||
87 session->ns_data.dd_state == NDMP_DATA_STATE_HALTED)
88 return;
89
90 NDMP_LOG(LOG_DEBUG, "data.operation: %d",
91 session->ns_data.dd_operation);
92
93 if (session->ns_data.dd_operation == NDMP_DATA_OP_BACKUP) {
94 /*
95 * Send/discard any buffered file history data.
96 */
97 ndmpd_file_history_cleanup(session, (err == 0 ? TRUE : FALSE));
98
99 /*
100 * If mover local and successfull backup, write any
101 * remaining buffered data to tape.
102 */
103 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_LOCAL &&
104 err == 0) {
105 if (ndmpd_local_write(session, 0, 0) < 0)
106 err = EIO;
107 }
108 }
109
110 session->ns_data.dd_state = NDMP_DATA_STATE_HALTED;
111
112 switch (err) {
113 case 0:
114 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_SUCCESSFUL;
115 break;
116 case EINTR:
117 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_ABORTED;
118 break;
119 case EIO:
120 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_CONNECT_ERROR;
121 break;
122 default:
123 session->ns_data.dd_halt_reason = NDMP_DATA_HALT_INTERNAL_ERROR;
124 }
125
126 req_v2.reason = session->ns_data.dd_halt_reason;
127 req_v2.text_reason = "";
128
129 NDMP_LOG(LOG_DEBUG, "ndmp_send_request(NDMP_NOTIFY_DATA_HALTED)");
130
131 if (ndmp_send_request_lock(session->ns_connection,
132 NDMP_NOTIFY_DATA_HALTED, NDMP_NO_ERR, (void *)&req_v2, 0) < 0)
133 NDMP_LOG(LOG_DEBUG, "Sending notify_data_halted request");
134
135 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
136
137 if (session->ns_mover.md_sock != session->ns_data.dd_sock) {
138 (void) close(session->ns_data.dd_sock);
139 } else {
140 NDMP_LOG(LOG_DEBUG, "Not closing as used by mover");
141 }
142
143 session->ns_data.dd_sock = -1;
144 } else {
145 ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED);
146 }
147 }
148
149
150 /*
151 * ndmpd_api_log_v2
152 *
153 * Sends a log request to the NDMP client.
154 *
155 * Parameters:
156 * cookie (input) - session pointer.
157 * str (input) - null terminated string
158 * format (input) - printf style format.
159 * ... (input) - format arguments.
160 *
161 * Returns:
162 * 0 - success.
163 * -1 - error.
164 */
165 /*ARGSUSED*/
166 int
ndmpd_api_log_v2(void * cookie,char * format,...)167 ndmpd_api_log_v2(void *cookie, char *format, ...)
168 {
169 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
170 ndmp_log_log_request request;
171 static char buf[1024];
172 va_list ap;
173
174 if (session == NULL)
175 return (-1);
176
177 va_start(ap, format);
178
179 /*LINTED variable format specifier */
180 (void) vsnprintf(buf, sizeof (buf), format, ap);
181 va_end(ap);
182
183 request.entry = buf;
184
185
186 if (ndmp_send_request(session->ns_connection, _NDMP_LOG_LOG,
187 NDMP_NO_ERR, (void *)&request, 0) < 0) {
188 NDMP_LOG(LOG_DEBUG, "Sending log request");
189 return (-1);
190 }
191 return (0);
192
193 }
194
195
196 /*
197 * ndmpd_api_read_v2
198 *
199 * Callback function called by the backup/recover module.
200 * Reads data from the mover.
201 * If the mover is remote, the data is read from the data connection.
202 * If the mover is local, the data is read from the tape device.
203 *
204 * Parameters:
205 * client_data (input) - session pointer.
206 * data (input) - data to be written.
207 * length (input) - data length.
208 *
209 * Returns:
210 * 0 - data successfully read.
211 * -1 - error.
212 * 1 - session terminated or operation aborted.
213 */
214 int
ndmpd_api_read_v2(void * client_data,char * data,ulong_t length)215 ndmpd_api_read_v2(void *client_data, char *data, ulong_t length)
216 {
217 ndmpd_session_t *session = (ndmpd_session_t *)client_data;
218
219 if (session == NULL)
220 return (-1);
221
222 /*
223 * Read the data from the data connection if the mover is remote.
224 */
225 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP)
226 return (ndmpd_remote_read(session, data, length));
227 else
228 return (ndmpd_local_read(session, data, length));
229 }
230
231
232 /*
233 * ndmpd_api_seek_v2
234 *
235 * Seek to the specified position in the data stream and start a
236 * read for the specified amount of data.
237 *
238 * Parameters:
239 * cookie (input) - session pointer.
240 * offset (input) - stream position to seek to.
241 * length (input) - amount of data that will be read using ndmpd_api_read
242 *
243 * Returns:
244 * 0 - seek successful.
245 * -1 - error.
246 */
247 int
ndmpd_api_seek_v2(void * cookie,u_longlong_t offset,u_longlong_t length)248 ndmpd_api_seek_v2(void *cookie, u_longlong_t offset, u_longlong_t length)
249 {
250 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
251 int err;
252
253 if (session == NULL)
254 return (-1);
255
256 session->ns_data.dd_read_offset = offset;
257 session->ns_data.dd_read_length = length;
258
259 /*
260 * Send a notify_data_read request if the mover is remote.
261 */
262 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
263 ndmp_notify_data_read_request request;
264
265 session->ns_mover.md_discard_length =
266 session->ns_mover.md_bytes_left_to_read;
267 session->ns_mover.md_bytes_left_to_read = length;
268 session->ns_mover.md_position = offset;
269
270 request.offset = long_long_to_quad(offset);
271 request.length = long_long_to_quad(length);
272
273 if (ndmp_send_request_lock(session->ns_connection,
274 NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
275 (void *)&request, 0) < 0) {
276
277 NDMP_LOG(LOG_DEBUG,
278 "Sending notify_data_read request");
279 return (-1);
280 }
281 return (0);
282 }
283 /* Mover is local. */
284
285 err = ndmpd_mover_seek(session, offset, length);
286 if (err < 0) {
287 ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR);
288 return (-1);
289 }
290 if (err == 0)
291 return (0);
292
293 /*
294 * NDMP client intervention is required to perform the seek.
295 * Wait for the client to either do the seek and send a continue
296 * request or send an abort request.
297 */
298 nlp_ref_nw(session);
299 for (; ; ) {
300 nlp_wait_nw(session);
301
302 if (nlp_event_rv_get(session) < 0) {
303 nlp_unref_nw(session);
304 return (-1);
305 }
306
307 if (session->ns_eof == TRUE) {
308 nlp_unref_nw(session);
309 return (-1);
310 }
311
312 switch (session->ns_mover.md_state) {
313 case NDMP_MOVER_STATE_ACTIVE:
314 /*
315 * There is a bug in the original SDK code which
316 * causes to fall in an infinite loop after the
317 * break.
318 */
319 nlp_unref_nw(session);
320 break;
321
322 case NDMP_MOVER_STATE_PAUSED:
323 continue;
324
325 default:
326 nlp_unref_nw(session);
327 return (-1);
328 }
329 }
330 }
331
332
333 /*
334 * ndmpd_api_file_recovered_v2
335 *
336 * Notify the NDMP client that the specified file was recovered.
337 *
338 * Parameters:
339 * cookie (input) - session pointer.
340 * name (input) - name of recovered file.
341 * error (input) - 0 if file successfully recovered.
342 * otherwise, error code indicating why recovery failed.
343 *
344 * Returns:
345 * void.
346 */
347 int
ndmpd_api_file_recovered_v2(void * cookie,char * name,int error)348 ndmpd_api_file_recovered_v2(void *cookie, char *name, int error)
349 {
350 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
351 ndmp_log_file_request_v2 request;
352
353 if (session == NULL)
354 return (-1);
355
356 request.name = name;
357 request.ssid = 0;
358
359 switch (error) {
360 case 0:
361 request.error = NDMP_NO_ERR;
362 break;
363 case ENOENT:
364 request.error = NDMP_FILE_NOT_FOUND_ERR;
365 break;
366 default:
367 request.error = NDMP_PERMISSION_ERR;
368 }
369
370 if (ndmp_send_request_lock(session->ns_connection, NDMP_LOG_FILE,
371 NDMP_NO_ERR, (void *)&request, 0) < 0) {
372 NDMP_LOG(LOG_DEBUG, "Sending log file request");
373 return (-1);
374 }
375 return (0);
376 }
377
378
379 /*
380 * ndmpd_api_write_v2
381 *
382 * Callback function called by the backup/restore module.
383 * Writes data to the mover.
384 * If the mover is remote, the data is written to the data connection.
385 * If the mover is local, the data is buffered and written to the
386 * tape device after a full record has been buffered.
387 *
388 * Parameters:
389 * client_data (input) - session pointer.
390 * data (input) - data to be written.
391 * length (input) - data length.
392 *
393 * Returns:
394 * 0 - data successfully written.
395 * -1 - error.
396 */
397 int
ndmpd_api_write_v2(void * client_data,char * data,ulong_t length)398 ndmpd_api_write_v2(void *client_data, char *data, ulong_t length)
399 {
400 ndmpd_session_t *session = (ndmpd_session_t *)client_data;
401
402 if (session == NULL)
403 return (-1);
404
405 /*
406 * Write the data to the data connection if the mover is remote.
407 */
408 if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP)
409 return (ndmpd_remote_write(session, data, length));
410 else
411 return (ndmpd_local_write(session, data, length));
412 }
413
414
415 /*
416 * ************************************************************************
417 * NDMP V3 CALLBACKS
418 * ************************************************************************
419 */
420
421 /*
422 * ndmpd_api_done_v3
423 *
424 * Called when the data module has completed.
425 * Sends a notify_halt request to the NDMP client.
426 *
427 * Parameters:
428 * session (input) - session pointer.
429 * err (input) - UNIX error code.
430 *
431 * Returns:
432 * void
433 */
434 void
ndmpd_api_done_v3(void * cookie,int err)435 ndmpd_api_done_v3(void *cookie, int err)
436 {
437 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
438 ndmp_data_halt_reason reason;
439
440 switch (err) {
441 case 0:
442 reason = NDMP_DATA_HALT_SUCCESSFUL;
443 break;
444
445 case EINTR:
446 reason = NDMP_DATA_HALT_ABORTED;
447 break;
448
449 case EIO:
450 reason = NDMP_DATA_HALT_CONNECT_ERROR;
451 break;
452
453 default:
454 reason = NDMP_DATA_HALT_INTERNAL_ERROR;
455 }
456
457 ndmpd_data_error(session, reason);
458 }
459
460 /*
461 * ndmpd_api_log_v3
462 *
463 * Sends a log request to the NDMP client.
464 *
465 * Parameters:
466 * cookie (input) - session pointer.
467 * format (input) - printf style format.
468 * ... (input) - format arguments.
469 *
470 * Returns:
471 * 0 - success.
472 * -1 - error.
473 */
474 /*ARGSUSED*/
475 int
ndmpd_api_log_v3(void * cookie,ndmp_log_type type,ulong_t msg_id,char * format,...)476 ndmpd_api_log_v3(void *cookie, ndmp_log_type type, ulong_t msg_id,
477 char *format, ...)
478 {
479 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
480 ndmp_log_message_request_v3 request;
481 static char buf[1024];
482 va_list ap;
483
484 if (session == NULL)
485 return (-1);
486
487 va_start(ap, format);
488
489 /*LINTED variable format specifier */
490 (void) vsnprintf(buf, sizeof (buf), format, ap);
491 va_end(ap);
492
493 request.entry = buf;
494 request.log_type = type;
495 request.message_id = msg_id;
496
497 if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE,
498 NDMP_NO_ERR, (void *)&request, 0) < 0) {
499 NDMP_LOG(LOG_DEBUG, "Error sending log message request.");
500 return (-1);
501 }
502 return (0);
503 }
504
505
506 /*
507 * ndmpd_api_write_v3
508 *
509 * Callback function called by the backup/restore module.
510 * Writes data to the mover.
511 * If the mover is remote, the data is written to the data connection.
512 * If the mover is local, the data is buffered and written to the
513 * tape device after a full record has been buffered.
514 *
515 * Parameters:
516 * client_data (input) - session pointer.
517 * data (input) - data to be written.
518 * length (input) - data length.
519 *
520 * Returns:
521 * 0 - data successfully written.
522 * -1 - error.
523 */
524 int
ndmpd_api_write_v3(void * client_data,char * data,ulong_t length)525 ndmpd_api_write_v3(void *client_data, char *data, ulong_t length)
526 {
527 ndmpd_session_t *session = (ndmpd_session_t *)client_data;
528
529 if (session == NULL)
530 return (-1);
531
532 /*
533 * Write the data to the tape if the mover is local, otherwise,
534 * write the data to the data connection.
535 *
536 * The same write function for of v2 can be used in V3
537 * for writing data to the data connection to the mover.
538 * So we don't need ndmpd_remote_write_v3().
539 */
540 if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL)
541 return (ndmpd_local_write_v3(session, data, length));
542 else
543 return (ndmpd_remote_write(session, data, length));
544 }
545
546
547 /*
548 * ndmpd_api_read_v3
549 *
550 * Callback function called by the backup/recover module.
551 * Reads data from the mover.
552 * If the mover is remote, the data is read from the data connection.
553 * If the mover is local, the data is read from the tape device.
554 *
555 * Parameters:
556 * client_data (input) - session pointer.
557 * data (input) - data to be written.
558 * length (input) - data length.
559 *
560 * Returns:
561 * 0 - data successfully read.
562 * -1 - error.
563 * 1 - session terminated or operation aborted.
564 */
565 int
ndmpd_api_read_v3(void * client_data,char * data,ulong_t length)566 ndmpd_api_read_v3(void *client_data, char *data, ulong_t length)
567 {
568 ndmpd_session_t *session = (ndmpd_session_t *)client_data;
569
570 if (session == NULL)
571 return (-1);
572
573 /*
574 * Read the data from the data connection if the mover is remote.
575 */
576 if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL)
577 return (ndmpd_local_read_v3(session, data, length));
578 else
579 return (ndmpd_remote_read_v3(session, data, length));
580 }
581
582
583 /*
584 * ndmpd_api_get_name_v3
585 *
586 * Return the name entry at the specified index from the
587 * recover file name list.
588 *
589 * Parameters:
590 * cookie (input) - NDMP session pointer.
591 * name_index (input) - index of entry to be returned.
592 *
593 * Returns:
594 * Pointer to name entry.
595 * 0 if requested entry does not exist.
596 */
597 void *
ndmpd_api_get_name_v3(void * cookie,ulong_t name_index)598 ndmpd_api_get_name_v3(void *cookie, ulong_t name_index)
599 {
600 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
601
602 if (session == NULL)
603 return (NULL);
604
605 if (name_index >= session->ns_data.dd_nlist_len)
606 return (NULL);
607
608 return (&session->ns_data.dd_nlist_v3[name_index]);
609 }
610
611
612 /*
613 * ndmpd_api_file_recovered_v3
614 *
615 * Notify the NDMP client that the specified file was recovered.
616 *
617 * Parameters:
618 * cookie (input) - session pointer.
619 * name (input) - name of recovered file.
620 * ssid (input) - selection set id.
621 * error (input) - 0 if file successfully recovered.
622 * otherwise, error code indicating why recovery failed.
623 *
624 * Returns:
625 * 0 - success.
626 * -1 - error.
627 */
628 int
ndmpd_api_file_recovered_v3(void * cookie,char * name,int error)629 ndmpd_api_file_recovered_v3(void *cookie, char *name, int error)
630 {
631 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
632 ndmp_log_file_request_v3 request;
633
634 if (session == NULL)
635 return (-1);
636
637 request.name = name;
638
639 switch (error) {
640 case 0:
641 request.error = NDMP_NO_ERR;
642 break;
643 case ENOENT:
644 request.error = NDMP_FILE_NOT_FOUND_ERR;
645 break;
646 default:
647 request.error = NDMP_PERMISSION_ERR;
648 }
649
650 if (ndmp_send_request_lock(session->ns_connection, NDMP_LOG_FILE,
651 NDMP_NO_ERR, (void *)&request, 0) < 0) {
652 NDMP_LOG(LOG_DEBUG, "Error sending log file request");
653 return (-1);
654 }
655
656 return (0);
657 }
658
659
660 /*
661 * ndmpd_api_seek_v3
662 *
663 * Seek to the specified position in the data stream and start a
664 * read for the specified amount of data.
665 *
666 * Parameters:
667 * cookie (input) - session pointer.
668 * offset (input) - stream position to seek to.
669 * length (input) - amount of data that will be read using ndmpd_api_read
670 *
671 * Returns:
672 * 0 - seek successful.
673 * 1 - seek needed DMA(client) intervention.
674 * -1 - error.
675 */
676 int
ndmpd_api_seek_v3(void * cookie,u_longlong_t offset,u_longlong_t length)677 ndmpd_api_seek_v3(void *cookie, u_longlong_t offset, u_longlong_t length)
678 {
679 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
680 int err;
681 ndmp_notify_data_read_request request;
682
683 if (session == NULL)
684 return (-1);
685
686 session->ns_data.dd_read_offset = offset;
687 session->ns_data.dd_read_length = length;
688
689 /*
690 * Send a notify_data_read request if the mover is remote.
691 */
692 if (session->ns_data.dd_data_addr.addr_type != NDMP_ADDR_LOCAL) {
693 session->ns_data.dd_discard_length =
694 session->ns_data.dd_bytes_left_to_read;
695 session->ns_data.dd_bytes_left_to_read = length;
696 session->ns_data.dd_position = offset;
697
698 request.offset = long_long_to_quad(offset);
699 request.length = long_long_to_quad(length);
700
701 if (ndmp_send_request_lock(session->ns_connection,
702 NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
703 (void *)&request, 0) < 0) {
704 NDMP_LOG(LOG_DEBUG,
705 "Sending notify_data_read request");
706 return (-1);
707 }
708
709 return (0);
710 }
711
712 /* Mover is local. */
713
714 err = ndmpd_mover_seek(session, offset, length);
715 if (err < 0) {
716 ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR);
717 return (-1);
718 }
719
720 if (err == 0)
721 return (0);
722
723 /*
724 * NDMP client intervention is required to perform the seek.
725 * Wait for the client to either do the seek and send a continue
726 * request or send an abort request.
727 */
728 err = ndmpd_mover_wait_v3(session);
729
730 /*
731 * If we needed a client intervention, then we should be able to
732 * detect this in DAR.
733 */
734 if (err == 0)
735 err = 1;
736 return (err);
737 }
738
739
740 /*
741 * ************************************************************************
742 * NDMP V4 CALLBACKS
743 * ************************************************************************
744 */
745
746 /*
747 * ndmpd_api_log_v4
748 *
749 * Sends a log request to the NDMP client.
750 * No message association is supported now, but can be added later on
751 * in this function.
752 *
753 * Parameters:
754 * cookie (input) - session pointer.
755 * format (input) - printf style format.
756 * ... (input) - format arguments.
757 *
758 * Returns:
759 * 0 - success.
760 * -1 - error.
761 */
762 /*ARGSUSED*/
763 int
ndmpd_api_log_v4(void * cookie,ndmp_log_type type,ulong_t msg_id,char * format,...)764 ndmpd_api_log_v4(void *cookie, ndmp_log_type type, ulong_t msg_id,
765 char *format, ...)
766 {
767 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
768 ndmp_log_message_request_v4 request;
769 static char buf[1024];
770 va_list ap;
771
772 if (session == NULL)
773 return (-1);
774
775 va_start(ap, format);
776
777 /*LINTED variable format specifier */
778 (void) vsnprintf(buf, sizeof (buf), format, ap);
779 va_end(ap);
780
781 request.entry = buf;
782 request.log_type = type;
783 request.message_id = msg_id;
784 request.associated_message_valid = NDMP_NO_ASSOCIATED_MESSAGE;
785 request.associated_message_sequence = 0;
786
787 if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE,
788 NDMP_NO_ERR, (void *)&request, 0) < 0) {
789 NDMP_LOG(LOG_DEBUG, "Error sending log message request.");
790 return (-1);
791 }
792 return (0);
793 }
794
795
796 /*
797 * ndmpd_api_file_recovered_v4
798 *
799 * Notify the NDMP client that the specified file was recovered.
800 *
801 * Parameters:
802 * cookie (input) - session pointer.
803 * name (input) - name of recovered file.
804 * ssid (input) - selection set id.
805 * error (input) - 0 if file successfully recovered.
806 * otherwise, error code indicating why recovery failed.
807 *
808 * Returns:
809 * void.
810 */
811 int
ndmpd_api_file_recovered_v4(void * cookie,char * name,int error)812 ndmpd_api_file_recovered_v4(void *cookie, char *name, int error)
813 {
814 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
815 ndmp_log_file_request_v4 request;
816
817 if (session == NULL)
818 return (-1);
819
820 request.name = name;
821
822 switch (error) {
823 case 0:
824 request.recovery_status = NDMP_RECOVERY_SUCCESSFUL;
825 break;
826 case EPERM:
827 request.recovery_status = NDMP_RECOVERY_FAILED_PERMISSION;
828 break;
829 case ENOENT:
830 request.recovery_status = NDMP_RECOVERY_FAILED_NOT_FOUND;
831 break;
832 case ENOTDIR:
833 request.recovery_status = NDMP_RECOVERY_FAILED_NO_DIRECTORY;
834 break;
835 case ENOMEM:
836 request.recovery_status = NDMP_RECOVERY_FAILED_OUT_OF_MEMORY;
837 break;
838 case EIO:
839 request.recovery_status = NDMP_RECOVERY_FAILED_IO_ERROR;
840 break;
841 case EEXIST:
842 request.recovery_status = NDMP_RECOVERY_FAILED_FILE_PATH_EXISTS;
843 break;
844 default:
845 request.recovery_status = NDMP_RECOVERY_FAILED_UNDEFINED_ERROR;
846 break;
847 }
848
849 if (ndmp_send_request_lock(session->ns_connection, NDMP_LOG_FILE,
850 NDMP_NO_ERR, (void *)&request, 0) < 0) {
851 NDMP_LOG(LOG_DEBUG, "Error sending log file request");
852 return (-1);
853 }
854
855 return (0);
856 }
857
858
859 /*
860 * ************************************************************************
861 * LOCALS
862 * ************************************************************************
863 */
864
865 /*
866 * ndmpd_api_find_env
867 *
868 * Return the pointer of the environment variable from the variable
869 * array for the spcified environment variable.
870 *
871 * Parameters:
872 * cookie (input) - NDMP session pointer.
873 * name (input) - name of variable.
874 *
875 * Returns:
876 * Pointer to variable.
877 * NULL if variable not found.
878 *
879 */
880 ndmp_pval *
ndmpd_api_find_env(void * cookie,char * name)881 ndmpd_api_find_env(void *cookie, char *name)
882 {
883 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
884 ulong_t i;
885 ndmp_pval *envp;
886
887 if (session == NULL)
888 return (NULL);
889
890 envp = session->ns_data.dd_env;
891 for (i = 0; envp && i < session->ns_data.dd_env_len; envp++, i++)
892 if (strcmp(name, envp->name) == NULL)
893 return (envp);
894
895 return (NULL);
896 }
897
898
899 /*
900 * ndmpd_api_get_env
901 *
902 * Return the value of an environment variable from the variable array.
903 *
904 * Parameters:
905 * cookie (input) - NDMP session pointer.
906 * name (input) - name of variable.
907 *
908 * Returns:
909 * Pointer to variable value.
910 * 0 if variable not found.
911 *
912 */
913 char *
ndmpd_api_get_env(void * cookie,char * name)914 ndmpd_api_get_env(void *cookie, char *name)
915 {
916 ndmp_pval *envp;
917
918 envp = ndmpd_api_find_env(cookie, name);
919 if (envp)
920 return (envp->value);
921
922 return (NULL);
923 }
924
925
926 /*
927 * ndmpd_api_add_env
928 *
929 * Adds an environment variable name/value pair to the environment
930 * variable list.
931 *
932 * Parameters:
933 * session (input) - session pointer.
934 * name (input) - variable name.
935 * val (input) - value.
936 *
937 * Returns:
938 * 0 - success.
939 * -1 - error.
940 */
941 int
ndmpd_api_add_env(void * cookie,char * name,char * value)942 ndmpd_api_add_env(void *cookie, char *name, char *value)
943 {
944 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
945 char *namebuf;
946 char *valbuf;
947
948 if (session == NULL)
949 return (-1);
950
951 session->ns_data.dd_env = realloc((void *)session->ns_data.dd_env,
952 sizeof (ndmp_pval) * (session->ns_data.dd_env_len + 1));
953
954 if (session->ns_data.dd_env == NULL) {
955 NDMP_LOG(LOG_ERR, "Out of memory.");
956 return (-1);
957 }
958 namebuf = strdup(name);
959 if (namebuf == NULL)
960 return (-1);
961
962 valbuf = strdup(value);
963 if (valbuf == NULL) {
964 free(namebuf);
965 return (-1);
966 }
967
968 (void) mutex_lock(&session->ns_lock);
969 session->ns_data.dd_env[session->ns_data.dd_env_len].name = namebuf;
970 session->ns_data.dd_env[session->ns_data.dd_env_len].value = valbuf;
971 session->ns_data.dd_env_len++;
972 (void) mutex_unlock(&session->ns_lock);
973
974 return (0);
975 }
976
977
978 /*
979 * ndmpd_api_set_env
980 *
981 * Sets an environment variable name/value pair in the environment
982 * variable list. If the variable exists, it gets the new value,
983 * otherwise it's added as a new variable.
984 *
985 * Parameters:
986 * session (input) - session pointer.
987 * name (input) - variable name.
988 * val (input) - value.
989 *
990 * Returns:
991 * 0 - success.
992 * -1 - error.
993 */
994 int
ndmpd_api_set_env(void * cookie,char * name,char * value)995 ndmpd_api_set_env(void *cookie, char *name, char *value)
996 {
997 char *valbuf;
998 int rv;
999 ndmp_pval *envp;
1000
1001 envp = ndmpd_api_find_env(cookie, name);
1002 if (!envp) {
1003 rv = ndmpd_api_add_env(cookie, name, value);
1004 } else if (!(valbuf = strdup(value))) {
1005 rv = -1;
1006 } else {
1007 rv = 0;
1008 free(envp->value);
1009 envp->value = valbuf;
1010 }
1011
1012 return (rv);
1013 }
1014
1015
1016 /*
1017 * ndmpd_api_get_name
1018 *
1019 * Return the name entry at the specified index from the
1020 * recover file name list.
1021 *
1022 * Parameters:
1023 * cookie (input) - NDMP session pointer.
1024 * name_index (input) - index of entry to be returned.
1025 *
1026 * Returns:
1027 * Pointer to name entry.
1028 * 0 if requested entry does not exist.
1029 */
1030 void *
ndmpd_api_get_name(void * cookie,ulong_t name_index)1031 ndmpd_api_get_name(void *cookie, ulong_t name_index)
1032 {
1033 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
1034
1035 if (session == NULL)
1036 return (NULL);
1037
1038 if (name_index >= session->ns_data.dd_nlist_len)
1039 return (NULL);
1040
1041 return (&session->ns_data.dd_nlist[name_index]);
1042 }
1043
1044
1045 /*
1046 * ndmpd_api_dispatch
1047 *
1048 * Process pending NDMP client requests and check registered files for
1049 * data availability.
1050 *
1051 * Parameters:
1052 * cookie (input) - session pointer.
1053 * block (input) -
1054 * TRUE block until a request has been processed or
1055 * until a file handler has been called.
1056 * FALSE don't block.
1057 *
1058 * Returns:
1059 * -1 - abort request received or connection closed.
1060 * 0 - success.
1061 */
1062 int
ndmpd_api_dispatch(void * cookie,boolean_t block)1063 ndmpd_api_dispatch(void *cookie, boolean_t block)
1064 {
1065 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
1066 int err;
1067
1068 if (session == NULL)
1069 return (-1);
1070
1071 for (; ; ) {
1072 err = ndmpd_select(session, block, HC_ALL);
1073 if (err < 0 || session->ns_data.dd_abort == TRUE ||
1074 session->ns_eof)
1075 return (-1);
1076
1077 if (err == 0)
1078 return (0);
1079
1080 /*
1081 * Something was processed.
1082 * Set the block flag to false so that we will return as
1083 * soon as everything available to be processed has been
1084 * processed.
1085 */
1086 block = FALSE;
1087 }
1088 }
1089
1090
1091 /*
1092 * ndmpd_api_add_file_handler
1093 *
1094 * Adds a file handler to the file handler list.
1095 * The file handler list is used by ndmpd_api_dispatch.
1096 *
1097 * Parameters:
1098 * daemon_cookie (input) - session pointer.
1099 * cookie (input) - opaque data to be passed to file hander when called.
1100 * fd (input) - file descriptor.
1101 * mode (input) - bitmask of the following:
1102 * NDMP_SELECT_MODE_READ = watch file for ready for reading
1103 * NDMP_SELECT_MODE_WRITE = watch file for ready for writing
1104 * NDMP_SELECT_MODE_EXCEPTION = watch file for exception
1105 * func (input) - function to call when the file meets one of the
1106 * conditions specified by mode.
1107 *
1108 * Returns:
1109 * 0 - success.
1110 * -1 - error.
1111 */
1112 int
ndmpd_api_add_file_handler(void * daemon_cookie,void * cookie,int fd,ulong_t mode,ndmpd_file_handler_func_t * func)1113 ndmpd_api_add_file_handler(void *daemon_cookie, void *cookie, int fd,
1114 ulong_t mode, ndmpd_file_handler_func_t *func)
1115 {
1116 ndmpd_session_t *session = (ndmpd_session_t *)daemon_cookie;
1117
1118 return (ndmpd_add_file_handler(session, cookie, fd, mode, HC_MODULE,
1119 func));
1120 }
1121
1122
1123 /*
1124 * ndmpd_api_remove_file_handler
1125 *
1126 * Removes a file handler from the file handler list.
1127 *
1128 * Parameters:
1129 * cookie (input) - session pointer.
1130 * fd (input) - file descriptor.
1131 *
1132 * Returns:
1133 * 0 - success.
1134 * -1 - error.
1135 */
1136 int
ndmpd_api_remove_file_handler(void * cookie,int fd)1137 ndmpd_api_remove_file_handler(void *cookie, int fd)
1138 {
1139 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
1140
1141 return (ndmpd_remove_file_handler(session, fd));
1142 }
1143