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