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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 * 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 * 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 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 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 * 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 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 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 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