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