1 /* 2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 3 * Copyright 2014 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 42 #include <sys/types.h> 43 #include <sys/socket.h> 44 #include <sys/time.h> 45 #include <sys/uio.h> 46 #include <unistd.h> 47 #include <string.h> 48 #include <stdlib.h> 49 #include <errno.h> 50 #include <netdb.h> 51 #include <netinet/in.h> 52 #include <arpa/inet.h> 53 #include <libinetutil.h> 54 #include "ndmpd.h" 55 #include "ndmpd_common.h" 56 57 #define NDMP_PROC_ERR -1 58 #define NDMP_PROC_MSG 1 59 #define NDMP_PROC_REP 0 60 #define NDMP_PROC_REP_ERR 2 61 62 /* 63 * The ndmp connection version can be set through command line. If command line 64 * is not specified it will be set from the ndmp SMF version property. 65 */ 66 int ndmp_ver = 0; 67 68 /* 69 * The NDMP listening port number 70 */ 71 int ndmp_port = 0; 72 73 /* 74 * Restore path mechanism definition 75 * 0 means partial path restore and 76 * 1 means full path restore. 77 * Refer to NDMP_FULL_RESTORE_PATH for partial path and full path definition. 78 */ 79 int ndmp_full_restore_path = 1; 80 81 /* 82 * Do we support Direct Access Restore? 83 */ 84 int ndmp_dar_support = 0; 85 86 /* 87 * ndmp_connection_t handler function 88 */ 89 static ndmpd_file_handler_func_t connection_file_handler; 90 91 extern ndmp_handler_t ndmp_msghdl_tab[]; 92 93 static int ndmp_readit(void *connection_handle, 94 caddr_t buf, 95 int len); 96 static int ndmp_writeit(void *connection_handle, 97 caddr_t buf, 98 int len); 99 static int ndmp_recv_msg(ndmp_connection_t *connection); 100 static int ndmp_process_messages(ndmp_connection_t *connection, 101 boolean_t reply_expected); 102 static ndmp_msg_handler_t *ndmp_get_handler(ndmp_connection_t *connection, 103 ndmp_message message); 104 static boolean_t ndmp_check_auth_required(ndmp_message message); 105 static ndmp_handler_t *ndmp_get_interface(ndmp_message message); 106 void *ndmpd_worker(void *ptarg); 107 108 #ifdef lint 109 bool_t 110 xdr_ndmp_header(XDR *xdrs, ndmp_header *objp) 111 { 112 xdrs = xdrs; 113 objp = objp; 114 return (0); 115 } 116 #endif /* lint */ 117 118 /* 119 * ndmp_create_connection 120 * 121 * Allocate and initialize a connection structure. 122 * 123 * Parameters: 124 * handler_tbl (input) - message handlers. 125 * 126 * Returns: 127 * NULL - error 128 * connection pointer 129 * 130 * Notes: 131 * The returned connection should be destroyed using 132 * ndmp_destroy_connection(). 133 */ 134 ndmp_connection_t * 135 ndmp_create_connection(void) 136 { 137 ndmp_connection_t *connection; 138 139 connection = ndmp_malloc(sizeof (ndmp_connection_t)); 140 if (connection == NULL) 141 return (NULL); 142 143 connection->conn_sock = -1; 144 connection->conn_my_sequence = 0; 145 connection->conn_authorized = FALSE; 146 connection->conn_eof = FALSE; 147 connection->conn_msginfo.mi_body = 0; 148 connection->conn_version = ndmp_ver; 149 connection->conn_client_data = 0; 150 (void) mutex_init(&connection->conn_lock, 0, NULL); 151 connection->conn_xdrs.x_ops = 0; 152 153 xdrrec_create(&connection->conn_xdrs, 0, 0, (caddr_t)connection, 154 ndmp_readit, ndmp_writeit); 155 156 if (connection->conn_xdrs.x_ops == 0) { 157 NDMP_LOG(LOG_DEBUG, "xdrrec_create failed"); 158 (void) mutex_destroy(&connection->conn_lock); 159 (void) close(connection->conn_sock); 160 free(connection); 161 return (0); 162 } 163 return ((ndmp_connection_t *)connection); 164 } 165 166 /* 167 * ndmp_destroy_connection 168 * 169 * Shutdown a connection and release allocated resources. 170 * 171 * Parameters: 172 * connection_handle (Input) - connection handle. 173 * 174 * Returns: 175 * void 176 */ 177 void 178 ndmp_destroy_connection(ndmp_connection_t *connection_handle) 179 { 180 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 181 182 if (connection->conn_sock >= 0) { 183 (void) mutex_destroy(&connection->conn_lock); 184 (void) close(connection->conn_sock); 185 connection->conn_sock = -1; 186 } 187 xdr_destroy(&connection->conn_xdrs); 188 free(connection); 189 } 190 191 192 /* 193 * ndmp_close 194 * 195 * Close a connection. 196 * 197 * Parameters: 198 * connection_handle (Input) - connection handle. 199 * 200 * Returns: 201 * void 202 */ 203 void 204 ndmp_close(ndmp_connection_t *connection_handle) 205 { 206 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 207 208 ndmpd_audit_disconnect(connection); 209 if (connection->conn_sock >= 0) { 210 (void) mutex_destroy(&connection->conn_lock); 211 (void) close(connection->conn_sock); 212 connection->conn_sock = -1; 213 } 214 connection->conn_eof = TRUE; 215 216 /* 217 * We should close all the tapes that are used by this connection. 218 * In some cases the ndmp client opens a tape, but does not close the 219 * tape and closes the connection. 220 */ 221 ndmp_open_list_release(connection_handle); 222 } 223 224 /* 225 * ndmp_start_worker 226 * 227 * Initializes and starts a ndmp_worker thread 228 */ 229 int 230 ndmp_start_worker(ndmpd_worker_arg_t *argp) 231 { 232 pthread_attr_t tattr; 233 int rc; 234 235 (void) pthread_attr_init(&tattr); 236 (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 237 rc = pthread_create(NULL, &tattr, ndmpd_worker, (void *)argp); 238 (void) pthread_attr_destroy(&tattr); 239 return (rc); 240 } 241 242 /* 243 * ndmp_run 244 * 245 * Creates a socket for listening and accepting connections 246 * from NDMP clients. 247 * Accepts connections and passes each connection to the connection 248 * handler. 249 * 250 * Parameters: 251 * port (input) - NDMP server port. 252 * If 0, the port number will be retrieved from 253 * the network service database. If not found there, 254 * the default NDMP port number (from ndmp.x) 255 * will be used. 256 * handler (input) - connection handler function. 257 * 258 * Returns: 259 * This function normally never returns unless there's error. 260 * -1 : error 261 * 262 * Notes: 263 * This function does not return unless encountering an error 264 * related to the listen socket. 265 */ 266 int 267 ndmp_run(ulong_t port, ndmp_con_handler_func_t con_handler_func) 268 { 269 int ns; 270 int on; 271 int server_socket; 272 unsigned int ipaddr; 273 struct sockaddr_in sin; 274 ndmpd_worker_arg_t *argp; 275 276 sin.sin_family = AF_INET; 277 sin.sin_addr.s_addr = INADDR_ANY; 278 sin.sin_port = htons(port); 279 280 if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 281 NDMP_LOG(LOG_DEBUG, "Socket error: %m"); 282 return (-1); 283 } 284 285 on = 1; 286 (void) setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, 287 (char *)&on, sizeof (on)); 288 289 290 if (bind(server_socket, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 291 NDMP_LOG(LOG_DEBUG, "bind error: %m"); 292 (void) close(server_socket); 293 return (-1); 294 } 295 if (listen(server_socket, 5) < 0) { 296 NDMP_LOG(LOG_DEBUG, "listen error: %m"); 297 (void) close(server_socket); 298 return (-1); 299 } 300 301 for (; ; ) { 302 if ((ns = tcp_accept(server_socket, &ipaddr)) < 0) { 303 NDMP_LOG(LOG_DEBUG, "tcp_accept error: %m"); 304 continue; 305 } 306 NDMP_LOG(LOG_DEBUG, "connection fd: %d", ns); 307 set_socket_options(ns); 308 309 if ((argp = ndmp_malloc(sizeof (ndmpd_worker_arg_t))) != NULL) { 310 argp->nw_sock = ns; 311 argp->nw_ipaddr = ipaddr; 312 argp->nw_con_handler_func = con_handler_func; 313 (void) ndmp_start_worker(argp); 314 } 315 } 316 } 317 318 /* 319 * ndmpd_worker thread 320 * 321 * Parameters: 322 * argp (input) - structure containing socket and handler function 323 * 324 * Returns: 325 * 0 - successful connection. 326 * -1 - error. 327 */ 328 void * 329 ndmpd_worker(void *ptarg) 330 { 331 int sock; 332 ndmp_connection_t *connection; 333 ndmpd_worker_arg_t *argp = (ndmpd_worker_arg_t *)ptarg; 334 335 if (!argp) 336 return ((void *)-1); 337 338 NS_INC(trun); 339 sock = argp->nw_sock; 340 341 if ((connection = ndmp_create_connection()) == NULL) { 342 (void) close(sock); 343 free(argp); 344 exit(1); 345 } 346 347 /* initialize auditing session */ 348 if (adt_start_session(&connection->conn_ah, NULL, 0) != 0) { 349 free(argp); 350 return ((void *)-1); 351 } 352 353 ((ndmp_connection_t *)connection)->conn_sock = sock; 354 (*argp->nw_con_handler_func)(connection); 355 (void) adt_end_session(connection->conn_ah); 356 ndmp_destroy_connection(connection); 357 NS_DEC(trun); 358 359 free(argp); 360 return (NULL); 361 } 362 363 /* 364 * ndmp_process_requests 365 * 366 * Reads the next request message into the stream buffer. 367 * Processes messages until the stream buffer is empty. 368 * 369 * Parameters: 370 * connection_handle (input) - connection handle. 371 * 372 * Returns: 373 * 0 - 1 or more messages successfully processed. 374 * -1 - error; connection no longer established. 375 */ 376 int 377 ndmp_process_requests(ndmp_connection_t *connection_handle) 378 { 379 int rv; 380 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 381 382 (void) mutex_lock(&connection->conn_lock); 383 rv = 0; 384 if (ndmp_process_messages(connection, FALSE) < 0) 385 rv = -1; 386 387 (void) mutex_unlock(&connection->conn_lock); 388 return (rv); 389 } 390 391 392 /* 393 * ndmp_send_request 394 * 395 * Send an NDMP request message. 396 * 397 * Parameters: 398 * connection_handle (input) - connection pointer. 399 * message (input) - message number. 400 * err (input) - error code to place in header. 401 * request_data (input) - message body. 402 * reply (output) - reply message. If 0, reply will be 403 * discarded. 404 * 405 * Returns: 406 * 0 - successful send. 407 * -1 - error. 408 * otherwise - error from reply header. 409 * 410 * Notes: 411 * - The reply body is only returned if the error code is NDMP_NO_ERR. 412 */ 413 int 414 ndmp_send_request(ndmp_connection_t *connection_handle, ndmp_message message, 415 ndmp_error err, void *request_data, void **reply) 416 { 417 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 418 ndmp_header header; 419 ndmp_msg_handler_t *handler; 420 int r; 421 struct timeval time; 422 423 /* Lookup info necessary for processing this request. */ 424 if (!(handler = ndmp_get_handler(connection, message))) { 425 NDMP_LOG(LOG_DEBUG, "Sending message 0x%x: not supported", 426 message); 427 return (-1); 428 } 429 (void) gettimeofday(&time, 0); 430 431 header.sequence = ++(connection->conn_my_sequence); 432 header.time_stamp = time.tv_sec; 433 header.message_type = NDMP_MESSAGE_REQUEST; 434 header.message = message; 435 header.reply_sequence = 0; 436 header.error = err; 437 438 connection->conn_xdrs.x_op = XDR_ENCODE; 439 if (!xdr_ndmp_header(&connection->conn_xdrs, &header)) { 440 NDMP_LOG(LOG_DEBUG, 441 "Sending message 0x%x: encoding request header", message); 442 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 443 return (-1); 444 } 445 if (err == NDMP_NO_ERR && handler->mh_xdr_request && request_data) { 446 if (!(*handler->mh_xdr_request)(&connection->conn_xdrs, 447 request_data)) { 448 NDMP_LOG(LOG_DEBUG, 449 "Sending message 0x%x: encoding request body", 450 message); 451 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 452 return (-1); 453 } 454 } 455 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 456 457 if (handler->mh_xdr_reply == 0) { 458 NDMP_LOG(LOG_DEBUG, "handler->mh_xdr_reply == 0"); 459 return (0); 460 } 461 462 /* 463 * Process messages until the reply to this request has been 464 * processed. 465 */ 466 for (; ; ) { 467 r = ndmp_process_messages(connection, TRUE); 468 469 /* connection error? */ 470 if (r < 0) 471 return (-1); 472 473 /* no reply received? */ 474 if (r == 0) 475 continue; 476 477 /* reply received? */ 478 if (r == 1) { 479 if (message != 480 connection->conn_msginfo.mi_hdr.message) { 481 NDMP_LOG(LOG_DEBUG, 482 "Received unexpected reply 0x%x", 483 connection->conn_msginfo.mi_hdr.message); 484 ndmp_free_message(connection_handle); 485 return (-1); 486 } 487 if (reply != NULL) 488 *reply = connection->conn_msginfo.mi_body; 489 else 490 ndmp_free_message(connection_handle); 491 492 return (connection->conn_msginfo.mi_hdr.error); 493 } 494 /* error handling reply */ 495 496 return (-1); 497 } 498 } 499 500 501 /* 502 * ndmp_send_request_lock 503 * 504 * A wrapper for ndmp_send_request with locks. 505 * 506 * Parameters: 507 * connection_handle (input) - connection pointer. 508 * message (input) - message number. 509 * err (input) - error code to place in header. 510 * request_data (input) - message body. 511 * reply (output) - reply message. If 0, reply will be 512 * discarded. 513 * 514 * Returns: 515 * 0 - successful send. 516 * -1 - error. 517 * otherwise - error from reply header. 518 * 519 * Notes: 520 * - The reply body is only returned if the error code is NDMP_NO_ERR. 521 */ 522 int 523 ndmp_send_request_lock(ndmp_connection_t *connection_handle, 524 ndmp_message message, ndmp_error err, void *request_data, void **reply) 525 { 526 int rv; 527 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 528 529 (void) mutex_lock(&connection->conn_lock); 530 531 rv = ndmp_send_request(connection_handle, message, err, request_data, 532 reply); 533 (void) mutex_unlock(&connection->conn_lock); 534 return (rv); 535 } 536 537 538 /* 539 * ndmp_send_response 540 * 541 * Send an NDMP reply message. 542 * 543 * Parameters: 544 * connection_handle (input) - connection pointer. 545 * err (input) - error code to place in header. 546 * reply (input) - reply message body. 547 * 548 * Returns: 549 * 0 - successful send. 550 * -1 - error. 551 * 552 * Notes: 553 * - The body is only sent if the error code is NDMP_NO_ERR. 554 */ 555 int 556 ndmp_send_response(ndmp_connection_t *connection_handle, ndmp_error err, 557 void *reply) 558 { 559 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 560 ndmp_header header; 561 struct timeval time; 562 563 (void) gettimeofday(&time, 0); 564 565 header.sequence = ++(connection->conn_my_sequence); 566 header.time_stamp = time.tv_sec; 567 header.message_type = NDMP_MESSAGE_REPLY; 568 header.message = connection->conn_msginfo.mi_hdr.message; 569 header.reply_sequence = connection->conn_msginfo.mi_hdr.sequence; 570 header.error = err; 571 572 connection->conn_xdrs.x_op = XDR_ENCODE; 573 if (!xdr_ndmp_header(&connection->conn_xdrs, &header)) { 574 NDMP_LOG(LOG_DEBUG, "Sending message 0x%x: " 575 "encoding reply header", 576 header.message); 577 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 578 return (-1); 579 } 580 if (err == NDMP_NO_ERR && 581 connection->conn_msginfo.mi_handler->mh_xdr_reply && 582 reply) { 583 if (!(*connection->conn_msginfo.mi_handler->mh_xdr_reply)( 584 &connection->conn_xdrs, reply)) { 585 NDMP_LOG(LOG_DEBUG, 586 "Sending message 0x%x: encoding reply body", 587 header.message); 588 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 589 return (-1); 590 } 591 } 592 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 593 return (0); 594 } 595 596 /* 597 * ndmp_free_message 598 * 599 * Free the memory of NDMP message body. 600 * 601 * Parameters: 602 * connection_handle (input) - connection pointer. 603 * 604 * Returns: 605 * void 606 * 607 */ 608 void 609 ndmp_free_message(ndmp_connection_t *connection_handle) 610 { 611 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 612 613 if (connection->conn_msginfo.mi_handler == NULL || 614 connection->conn_msginfo.mi_body == NULL) 615 return; 616 617 connection->conn_xdrs.x_op = XDR_FREE; 618 if (connection->conn_msginfo.mi_hdr.message_type == 619 NDMP_MESSAGE_REQUEST) { 620 if (connection->conn_msginfo.mi_handler->mh_xdr_request) 621 (*connection->conn_msginfo.mi_handler->mh_xdr_request)( 622 &connection->conn_xdrs, 623 connection->conn_msginfo.mi_body); 624 } else { 625 if (connection->conn_msginfo.mi_handler->mh_xdr_reply) 626 (*connection->conn_msginfo.mi_handler->mh_xdr_reply)( 627 &connection->conn_xdrs, 628 connection->conn_msginfo.mi_body); 629 } 630 631 (void) free(connection->conn_msginfo.mi_body); 632 connection->conn_msginfo.mi_body = 0; 633 } 634 635 /* 636 * ndmp_get_fd 637 * 638 * Returns the connection file descriptor. 639 * 640 * Parameters: 641 * connection_handle (input) - connection handle 642 * 643 * Returns: 644 * >=0 - file descriptor. 645 * -1 - connection not open. 646 */ 647 int 648 ndmp_get_fd(ndmp_connection_t *connection_handle) 649 { 650 return (((ndmp_connection_t *)connection_handle)->conn_sock); 651 } 652 653 654 /* 655 * ndmp_set_client_data 656 * 657 * This function provides a means for the library client to provide 658 * a pointer to some user data structure that is retrievable by 659 * each message handler via ndmp_get_client_data. 660 * 661 * Parameters: 662 * connection_handle (input) - connection handle. 663 * client_data (input) - user data pointer. 664 * 665 * Returns: 666 * void 667 */ 668 void 669 ndmp_set_client_data(ndmp_connection_t *connection_handle, void *client_data) 670 { 671 ((ndmp_connection_t *)connection_handle)->conn_client_data = 672 client_data; 673 } 674 675 676 /* 677 * ndmp_get_client_data 678 * 679 * This function provides a means for the library client to provide 680 * a pointer to some user data structure that is retrievable by 681 * each message handler via ndmp_get_client_data. 682 * 683 * Parameters: 684 * connection_handle (input) - connection handle. 685 * 686 * Returns: 687 * client data pointer. 688 */ 689 void * 690 ndmp_get_client_data(ndmp_connection_t *connection_handle) 691 { 692 return (((ndmp_connection_t *)connection_handle)->conn_client_data); 693 } 694 695 696 /* 697 * ndmp_set_version 698 * 699 * Sets the NDMP protocol version to be used on the connection. 700 * 701 * Parameters: 702 * connection_handle (input) - connection handle. 703 * version (input) - protocol version. 704 * 705 * Returns: 706 * void 707 */ 708 void 709 ndmp_set_version(ndmp_connection_t *connection_handle, ushort_t version) 710 { 711 ((ndmp_connection_t *)connection_handle)->conn_version = version; 712 } 713 714 715 /* 716 * ndmp_get_version 717 * 718 * Gets the NDMP protocol version in use on the connection. 719 * 720 * Parameters: 721 * connection_handle (input) - connection handle. 722 * version (input) - protocol version. 723 * 724 * Returns: 725 * void 726 */ 727 ushort_t 728 ndmp_get_version(ndmp_connection_t *connection_handle) 729 { 730 return (((ndmp_connection_t *)connection_handle)->conn_version); 731 } 732 733 734 /* 735 * ndmp_set_authorized 736 * 737 * Mark the connection as either having been authorized or not. 738 * 739 * Parameters: 740 * connection_handle (input) - connection handle. 741 * authorized (input) - TRUE or FALSE. 742 * 743 * Returns: 744 * void 745 */ 746 void 747 ndmp_set_authorized(ndmp_connection_t *connection_handle, boolean_t authorized) 748 { 749 ((ndmp_connection_t *)connection_handle)->conn_authorized = authorized; 750 } 751 752 753 /* 754 * ndmpd_main 755 * 756 * NDMP main function called from main(). 757 * 758 * Parameters: 759 * void 760 * 761 * Returns: 762 * void 763 */ 764 void 765 ndmpd_main(void) 766 { 767 char *propval; 768 769 ndmp_load_params(); 770 771 /* 772 * Find ndmp port number to be used. If ndmpd is run as command line 773 * and port number is supplied, use that port number. If port number is 774 * is not supplied, find out if ndmp port property is set. If ndmp 775 * port property is set, use that port number otherwise use the defaule 776 * port number. 777 */ 778 if (ndmp_port == 0) { 779 if ((propval = ndmpd_get_prop(NDMP_TCP_PORT)) == NULL || 780 *propval == 0) 781 ndmp_port = NDMPPORT; 782 else 783 ndmp_port = strtol(propval, 0, 0); 784 } 785 786 if (ndmp_run(ndmp_port, connection_handler) == -1) 787 perror("ndmp_run ERROR"); 788 } 789 790 /* 791 * connection_handler 792 * 793 * NDMP connection handler. 794 * Waits for, reads, and processes NDMP requests on a connection. 795 * 796 * Parameters: 797 * connection (input) - connection handle. 798 * 799 * Return: 800 * void 801 */ 802 void 803 connection_handler(ndmp_connection_t *connection) 804 { 805 static int conn_id = 1; 806 ndmpd_session_t session; 807 ndmp_notify_connected_request req; 808 int connection_fd; 809 810 (void) memset(&session, 0, sizeof (session)); 811 session.ns_connection = connection; 812 session.ns_eof = FALSE; 813 /* 814 * The 'protocol_version' must be 1 at first, since the client talks 815 * to the server in version 1 then they can move to a higher 816 * protocol version. 817 */ 818 session.ns_protocol_version = ndmp_ver; 819 820 session.ns_scsi.sd_is_open = -1; 821 session.ns_scsi.sd_devid = -1; 822 823 session.ns_scsi.sd_sid = 0; 824 session.ns_scsi.sd_lun = 0; 825 session.ns_scsi.sd_valid_target_set = 0; 826 (void) memset(session.ns_scsi.sd_adapter_name, 0, 827 sizeof (session.ns_scsi.sd_adapter_name)); 828 829 session.ns_tape.td_fd = -1; 830 session.ns_tape.td_sid = 0; 831 session.ns_tape.td_lun = 0; 832 (void) memset(session.ns_tape.td_adapter_name, 0, 833 sizeof (session.ns_tape.td_adapter_name)); 834 session.ns_tape.td_pos = 0; 835 session.ns_tape.td_record_count = 0; 836 session.ns_file_handler_list = 0; 837 838 (void) ndmpd_data_init(&session); 839 ndmpd_file_history_init(&session); 840 if (ndmpd_mover_init(&session) < 0) 841 return; 842 843 if (ndmp_lbr_init(&session) < 0) 844 return; 845 846 /* 847 * Setup defaults here. The init functions can not set defaults 848 * since the init functions are called by the stop request handlers 849 * and client set variables need to persist across data operations. 850 */ 851 session.ns_mover.md_record_size = MAX_RECORD_SIZE; 852 853 ndmp_set_client_data(connection, (void *)&session); 854 855 req.reason = NDMP_CONNECTED; 856 req.protocol_version = ndmp_ver; 857 req.text_reason = ""; 858 859 if (ndmp_send_request_lock(connection, NDMP_NOTIFY_CONNECTION_STATUS, 860 NDMP_NO_ERR, (void *)&req, 0) < 0) { 861 NDMP_LOG(LOG_DEBUG, "Connection terminated"); 862 return; 863 } 864 connection_fd = ndmp_get_fd(connection); 865 866 NDMP_LOG(LOG_DEBUG, "connection_fd: %d", connection_fd); 867 868 /* 869 * Add the handler function for the connection to the DMA. 870 */ 871 if (ndmpd_add_file_handler(&session, (void *)&session, connection_fd, 872 NDMPD_SELECT_MODE_READ, HC_CLIENT, connection_file_handler) != 0) { 873 NDMP_LOG(LOG_DEBUG, "Could not register session handler."); 874 return; 875 } 876 877 /* 878 * Register the connection in the list of active connections. 879 */ 880 if (ndmp_connect_list_add(connection, &conn_id) != 0) { 881 NDMP_LOG(LOG_ERR, 882 "Could not register the session to the server."); 883 (void) ndmpd_remove_file_handler(&session, connection_fd); 884 return; 885 } 886 887 session.hardlink_q = hardlink_q_init(); 888 889 while (session.ns_eof == FALSE) 890 (void) ndmpd_select(&session, TRUE, HC_ALL); 891 892 hardlink_q_cleanup(session.hardlink_q); 893 894 NDMP_LOG(LOG_DEBUG, "Connection terminated"); 895 896 (void) ndmpd_remove_file_handler(&session, connection_fd); 897 898 if (session.ns_scsi.sd_is_open != -1) { 899 NDMP_LOG(LOG_DEBUG, "scsi.is_open: %d", 900 session.ns_scsi.sd_is_open); 901 (void) ndmp_open_list_del(session.ns_scsi.sd_adapter_name, 902 session.ns_scsi.sd_sid, session.ns_scsi.sd_lun); 903 } 904 if (session.ns_tape.td_fd != -1) { 905 NDMP_LOG(LOG_DEBUG, "tape.fd: %d", session.ns_tape.td_fd); 906 (void) close(session.ns_tape.td_fd); 907 (void) ndmp_open_list_del(session.ns_tape.td_adapter_name, 908 session.ns_tape.td_sid, session.ns_tape.td_lun); 909 } 910 ndmpd_mover_shut_down(&session); 911 ndmp_lbr_cleanup(&session); 912 ndmpd_data_cleanup(&session); 913 ndmpd_file_history_cleanup(&session, FALSE); 914 ndmpd_mover_cleanup(&session); 915 916 (void) ndmp_connect_list_del(connection); 917 } 918 919 920 /* 921 * connection_file_handler 922 * 923 * ndmp_connection_t file handler function. 924 * Called by ndmpd_select when data is available to be read on the 925 * NDMP connection. 926 * 927 * Parameters: 928 * cookie (input) - session pointer. 929 * fd (input) - connection file descriptor. 930 * mode (input) - select mode. 931 * 932 * Returns: 933 * void. 934 */ 935 /*ARGSUSED*/ 936 static void 937 connection_file_handler(void *cookie, int fd, ulong_t mode) 938 { 939 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 940 941 if (ndmp_process_requests(session->ns_connection) < 0) 942 session->ns_eof = TRUE; 943 } 944 945 946 /* ************* private functions *************************************** */ 947 948 /* 949 * ndmp_readit 950 * 951 * Low level read routine called by the xdrrec library. 952 * 953 * Parameters: 954 * connection (input) - connection pointer. 955 * buf (input) - location to store received data. 956 * len (input) - max number of bytes to read. 957 * 958 * Returns: 959 * >0 - number of bytes received. 960 * -1 - error. 961 */ 962 static int 963 ndmp_readit(void *connection_handle, caddr_t buf, int len) 964 { 965 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 966 967 len = read(connection->conn_sock, buf, len); 968 if (len <= 0) { 969 /* ndmp_connection_t has been closed. */ 970 connection->conn_eof = TRUE; 971 return (-1); 972 } 973 return (len); 974 } 975 976 /* 977 * ndmp_writeit 978 * 979 * Low level write routine called by the xdrrec library. 980 * 981 * Parameters: 982 * connection (input) - connection pointer. 983 * buf (input) - location to store received data. 984 * len (input) - max number of bytes to read. 985 * 986 * Returns: 987 * >0 - number of bytes sent. 988 * -1 - error. 989 */ 990 static int 991 ndmp_writeit(void *connection_handle, caddr_t buf, int len) 992 { 993 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 994 register int n; 995 register int cnt; 996 997 for (cnt = len; cnt > 0; cnt -= n, buf += n) { 998 if ((n = write(connection->conn_sock, buf, cnt)) < 0) { 999 connection->conn_eof = TRUE; 1000 return (-1); 1001 } 1002 } 1003 1004 return (len); 1005 } 1006 1007 1008 /* 1009 * ndmp_recv_msg 1010 * 1011 * Read the next message. 1012 * 1013 * Parameters: 1014 * connection (input) - connection pointer. 1015 * msg (output) - received message. 1016 * 1017 * Returns: 1018 * 0 - Message successfully received. 1019 * error number - Message related error. 1020 * -1 - Error decoding the message header. 1021 */ 1022 static int 1023 ndmp_recv_msg(ndmp_connection_t *connection) 1024 { 1025 bool_t(*xdr_func) (XDR *, ...) = NULL; 1026 1027 /* Decode the header. */ 1028 connection->conn_xdrs.x_op = XDR_DECODE; 1029 (void) xdrrec_skiprecord(&connection->conn_xdrs); 1030 if (!xdr_ndmp_header(&connection->conn_xdrs, 1031 &connection->conn_msginfo.mi_hdr)) 1032 return (-1); 1033 1034 /* Lookup info necessary for processing this message. */ 1035 if ((connection->conn_msginfo.mi_handler = ndmp_get_handler(connection, 1036 connection->conn_msginfo.mi_hdr.message)) == 0) { 1037 NDMP_LOG(LOG_DEBUG, "Message 0x%x not supported", 1038 connection->conn_msginfo.mi_hdr.message); 1039 return (NDMP_NOT_SUPPORTED_ERR); 1040 } 1041 connection->conn_msginfo.mi_body = 0; 1042 1043 if (connection->conn_msginfo.mi_hdr.error != NDMP_NO_ERR) 1044 return (0); 1045 1046 /* Determine body type */ 1047 if (connection->conn_msginfo.mi_hdr.message_type == 1048 NDMP_MESSAGE_REQUEST) { 1049 if (ndmp_check_auth_required( 1050 connection->conn_msginfo.mi_hdr.message) && 1051 !connection->conn_authorized) { 1052 NDMP_LOG(LOG_DEBUG, 1053 "Processing request 0x%x:connection not authorized", 1054 connection->conn_msginfo.mi_hdr.message); 1055 return (NDMP_NOT_AUTHORIZED_ERR); 1056 } 1057 if (connection->conn_msginfo.mi_handler->mh_sizeof_request > 1058 0) { 1059 xdr_func = 1060 connection->conn_msginfo.mi_handler->mh_xdr_request; 1061 if (xdr_func == NULL) { 1062 NDMP_LOG(LOG_DEBUG, 1063 "Processing request 0x%x: no xdr function " 1064 "in handler table", 1065 connection->conn_msginfo.mi_hdr.message); 1066 return (NDMP_NOT_SUPPORTED_ERR); 1067 } 1068 connection->conn_msginfo.mi_body = ndmp_malloc( 1069 connection->conn_msginfo.mi_handler-> 1070 mh_sizeof_request); 1071 if (connection->conn_msginfo.mi_body == NULL) 1072 return (NDMP_NO_MEM_ERR); 1073 1074 (void) memset(connection->conn_msginfo.mi_body, 0, 1075 connection->conn_msginfo.mi_handler-> 1076 mh_sizeof_request); 1077 } 1078 } else { 1079 if (connection->conn_msginfo.mi_handler->mh_sizeof_reply > 0) { 1080 xdr_func = 1081 connection->conn_msginfo.mi_handler->mh_xdr_reply; 1082 if (xdr_func == NULL) { 1083 NDMP_LOG(LOG_DEBUG, 1084 "Processing reply 0x%x: no xdr function " 1085 "in handler table", 1086 connection->conn_msginfo.mi_hdr.message); 1087 return (NDMP_NOT_SUPPORTED_ERR); 1088 } 1089 connection->conn_msginfo.mi_body = ndmp_malloc( 1090 connection->conn_msginfo.mi_handler-> 1091 mh_sizeof_reply); 1092 if (connection->conn_msginfo.mi_body == NULL) 1093 return (NDMP_NO_MEM_ERR); 1094 1095 (void) memset(connection->conn_msginfo.mi_body, 0, 1096 connection->conn_msginfo.mi_handler-> 1097 mh_sizeof_reply); 1098 } 1099 } 1100 1101 /* Decode message arguments if needed */ 1102 if (xdr_func) { 1103 if (!(*xdr_func)(&connection->conn_xdrs, 1104 connection->conn_msginfo.mi_body)) { 1105 NDMP_LOG(LOG_DEBUG, 1106 "Processing message 0x%x: error decoding arguments", 1107 connection->conn_msginfo.mi_hdr.message); 1108 free(connection->conn_msginfo.mi_body); 1109 connection->conn_msginfo.mi_body = 0; 1110 return (NDMP_XDR_DECODE_ERR); 1111 } 1112 } 1113 return (0); 1114 } 1115 1116 /* 1117 * ndmp_process_messages 1118 * 1119 * Reads the next message into the stream buffer. 1120 * Processes messages until the stream buffer is empty. 1121 * 1122 * This function processes all data in the stream buffer before returning. 1123 * This allows functions like poll() to be used to determine when new 1124 * messages have arrived. If only some of the messages in the stream buffer 1125 * were processed and then poll was called, poll() could block waiting for 1126 * a message that had already been received and read into the stream buffer. 1127 * 1128 * This function processes both request and reply messages. 1129 * Request messages are dispatched using the appropriate function from the 1130 * message handling table. 1131 * Only one reply messages may be pending receipt at a time. 1132 * A reply message, if received, is placed in connection->conn_msginfo 1133 * before returning to the caller. 1134 * Errors are reported if a reply is received but not expected or if 1135 * more than one reply message is received 1136 * 1137 * Parameters: 1138 * connection (input) - connection pointer. 1139 * reply_expected (output) - TRUE - a reply message is expected. 1140 * FALSE - no reply message is expected and 1141 * an error will be reported if a reply 1142 * is received. 1143 * 1144 * Returns: 1145 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 1146 * error processing reply message. 1147 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 1148 * reply seen. 1149 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 1150 * no reply seen. 1151 * NDMP_PROC_REP_ERR - error; connection no longer established. 1152 * 1153 * Notes: 1154 * If the peer is generating a large number of requests, a caller 1155 * looking for a reply will be blocked while the requests are handled. 1156 * This is because this function does not return until the stream 1157 * buffer is empty. 1158 * Code needs to be added to allow a return if the stream buffer 1159 * is not empty but there is data available on the socket. This will 1160 * prevent poll() from blocking and prevent a caller looking for a reply 1161 * from getting blocked by a bunch of requests. 1162 */ 1163 static int 1164 ndmp_process_messages(ndmp_connection_t *connection, boolean_t reply_expected) 1165 { 1166 msg_info_t reply_msginfo; 1167 boolean_t reply_read = FALSE; 1168 boolean_t reply_error = FALSE; 1169 int err; 1170 1171 NDMP_LOG(LOG_DEBUG, "reply_expected: %s", 1172 reply_expected == TRUE ? "TRUE" : "FALSE"); 1173 1174 (void) memset((void *)&reply_msginfo, 0, sizeof (msg_info_t)); 1175 1176 do { 1177 (void) memset((void *)&connection->conn_msginfo, 0, 1178 sizeof (msg_info_t)); 1179 1180 if ((err = ndmp_recv_msg(connection)) != NDMP_NO_ERR) { 1181 if (connection->conn_eof) { 1182 NDMP_LOG(LOG_DEBUG, "detected eof"); 1183 return (NDMP_PROC_ERR); 1184 } 1185 if (err < 1) { 1186 NDMP_LOG(LOG_DEBUG, "error decoding header"); 1187 1188 /* 1189 * Error occurred decoding the header. 1190 * Don't send a reply since we don't know 1191 * the message or if the message was even 1192 * a request message. To be safe, assume 1193 * that the message was a reply if a reply 1194 * was expected. Need to do this to prevent 1195 * hanging ndmp_send_request() waiting for a 1196 * reply. Don't set reply_read so that the 1197 * reply will be processed if it is received 1198 * later. 1199 */ 1200 if (reply_read == FALSE) 1201 reply_error = TRUE; 1202 1203 continue; 1204 } 1205 if (connection->conn_msginfo.mi_hdr.message_type 1206 != NDMP_MESSAGE_REQUEST) { 1207 NDMP_LOG(LOG_DEBUG, "received reply: 0x%x", 1208 connection->conn_msginfo.mi_hdr.message); 1209 1210 if (reply_expected == FALSE || 1211 reply_read == TRUE) 1212 NDMP_LOG(LOG_DEBUG, 1213 "Unexpected reply message: 0x%x", 1214 connection->conn_msginfo.mi_hdr. 1215 message); 1216 1217 ndmp_free_message((ndmp_connection_t *) 1218 connection); 1219 1220 if (reply_read == FALSE) { 1221 reply_read = TRUE; 1222 reply_error = TRUE; 1223 } 1224 continue; 1225 } 1226 NDMP_LOG(LOG_DEBUG, "received request: 0x%x", 1227 connection->conn_msginfo.mi_hdr.message); 1228 1229 (void) ndmp_send_response((ndmp_connection_t *) 1230 connection, err, NULL); 1231 ndmp_free_message((ndmp_connection_t *)connection); 1232 continue; 1233 } 1234 if (connection->conn_msginfo.mi_hdr.message_type 1235 != NDMP_MESSAGE_REQUEST) { 1236 NDMP_LOG(LOG_DEBUG, "received reply: 0x%x", 1237 connection->conn_msginfo.mi_hdr.message); 1238 1239 if (reply_expected == FALSE || reply_read == TRUE) { 1240 NDMP_LOG(LOG_DEBUG, 1241 "Unexpected reply message: 0x%x", 1242 connection->conn_msginfo.mi_hdr.message); 1243 ndmp_free_message((ndmp_connection_t *) 1244 connection); 1245 continue; 1246 } 1247 reply_read = TRUE; 1248 reply_msginfo = connection->conn_msginfo; 1249 continue; 1250 } 1251 NDMP_LOG(LOG_DEBUG, "received request: 0x%x", 1252 connection->conn_msginfo.mi_hdr.message); 1253 1254 /* 1255 * The following is needed to catch an improperly constructed 1256 * handler table or to deal with an NDMP client that is not 1257 * conforming to the negotiated protocol version. 1258 */ 1259 if (connection->conn_msginfo.mi_handler->mh_func == NULL) { 1260 NDMP_LOG(LOG_DEBUG, "No handler for message 0x%x", 1261 connection->conn_msginfo.mi_hdr.message); 1262 1263 (void) ndmp_send_response((ndmp_connection_t *) 1264 connection, NDMP_NOT_SUPPORTED_ERR, NULL); 1265 ndmp_free_message((ndmp_connection_t *)connection); 1266 continue; 1267 } 1268 /* 1269 * Call the handler function. 1270 * The handler will send any necessary reply. 1271 */ 1272 (*connection->conn_msginfo.mi_handler->mh_func) (connection, 1273 connection->conn_msginfo.mi_body); 1274 1275 ndmp_free_message((ndmp_connection_t *)connection); 1276 1277 } while (xdrrec_eof(&connection->conn_xdrs) == FALSE && 1278 connection->conn_eof == FALSE); 1279 1280 NDMP_LOG(LOG_DEBUG, "no more messages in stream buffer"); 1281 1282 if (connection->conn_eof == TRUE) { 1283 if (reply_msginfo.mi_body) 1284 free(reply_msginfo.mi_body); 1285 return (NDMP_PROC_ERR); 1286 } 1287 if (reply_error) { 1288 if (reply_msginfo.mi_body) 1289 free(reply_msginfo.mi_body); 1290 return (NDMP_PROC_REP_ERR); 1291 } 1292 if (reply_read) { 1293 connection->conn_msginfo = reply_msginfo; 1294 return (NDMP_PROC_MSG); 1295 } 1296 return (NDMP_PROC_REP); 1297 } 1298 1299 1300 /* 1301 * ndmp_get_interface 1302 * 1303 * Return the NDMP interface (e.g. config, scsi, tape) for the 1304 * specific message. 1305 * 1306 * Parameters: 1307 * message (input) - message number. 1308 * 1309 * Returns: 1310 * NULL - message not found. 1311 * pointer to handler info. 1312 */ 1313 static ndmp_handler_t * 1314 ndmp_get_interface(ndmp_message message) 1315 { 1316 ndmp_handler_t *ni = &ndmp_msghdl_tab[(message >> 8) % INT_MAXCMD]; 1317 1318 if ((message & 0xff) >= ni->hd_cnt) 1319 return (NULL); 1320 1321 /* Sanity check */ 1322 if (ni->hd_msgs[message & 0xff].hm_message != message) 1323 return (NULL); 1324 1325 return (ni); 1326 } 1327 1328 /* 1329 * ndmp_get_handler 1330 * 1331 * Return the handler info for the specified NDMP message. 1332 * 1333 * Parameters: 1334 * connection (input) - connection pointer. 1335 * message (input) - message number. 1336 * 1337 * Returns: 1338 * NULL - message not found. 1339 * pointer to handler info. 1340 */ 1341 static ndmp_msg_handler_t * 1342 ndmp_get_handler(ndmp_connection_t *connection, ndmp_message message) 1343 { 1344 ndmp_msg_handler_t *handler = NULL; 1345 1346 ndmp_handler_t *ni = ndmp_get_interface(message); 1347 int ver = connection->conn_version; 1348 1349 if (ni) 1350 handler = &ni->hd_msgs[message & 0xff].hm_msg_v[ver - 2]; 1351 1352 return (handler); 1353 } 1354 1355 /* 1356 * ndmp_check_auth_required 1357 * 1358 * Check if the connection needs to be authenticated before 1359 * this message is being processed. 1360 * 1361 * Parameters: 1362 * message (input) - message number. 1363 * 1364 * Returns: 1365 * TRUE - required 1366 * FALSE - not required 1367 */ 1368 static boolean_t 1369 ndmp_check_auth_required(ndmp_message message) 1370 { 1371 boolean_t auth_req = FALSE; 1372 ndmp_handler_t *ni = ndmp_get_interface(message); 1373 1374 if (ni) 1375 auth_req = ni->hd_msgs[message & 0xff].hm_auth_required; 1376 1377 return (auth_req); 1378 } 1379 1380 /* 1381 * tcp_accept 1382 * 1383 * A wrapper around accept for retrying and getting the IP address 1384 * 1385 * Parameters: 1386 * listen_sock (input) - the socket for listening 1387 * inaddr_p (output) - the IP address of peer connection 1388 * 1389 * Returns: 1390 * socket for the accepted connection 1391 * -1: error 1392 */ 1393 int 1394 tcp_accept(int listen_sock, unsigned int *inaddr_p) 1395 { 1396 struct sockaddr_in sin; 1397 int sock, i; 1398 int try; 1399 1400 for (try = 0; try < 3; try++) { 1401 i = sizeof (sin); 1402 sock = accept(listen_sock, (struct sockaddr *)&sin, &i); 1403 if (sock < 0) { 1404 continue; 1405 } 1406 *inaddr_p = sin.sin_addr.s_addr; 1407 return (sock); 1408 } 1409 return (-1); 1410 } 1411 1412 1413 /* 1414 * tcp_get_peer 1415 * 1416 * Get the peer IP address for a connection 1417 * 1418 * Parameters: 1419 * sock (input) - the active socket 1420 * inaddr_p (output) - the IP address of peer connection 1421 * port_p (output) - the port number of peer connection 1422 * 1423 * Returns: 1424 * socket for the accepted connection 1425 * -1: error 1426 */ 1427 int 1428 tcp_get_peer(int sock, unsigned int *inaddr_p, int *port_p) 1429 { 1430 struct sockaddr_in sin; 1431 int i, rc; 1432 1433 i = sizeof (sin); 1434 rc = getpeername(sock, (struct sockaddr *)&sin, &i); 1435 if (rc != 0) 1436 return (-1); 1437 1438 if (inaddr_p) 1439 *inaddr_p = sin.sin_addr.s_addr; 1440 1441 if (port_p) 1442 *port_p = ntohs(sin.sin_port); 1443 1444 return (sock); 1445 1446 } 1447 1448 /* 1449 * gethostaddr 1450 * 1451 * Get the IP address string of the current host 1452 * 1453 * Parameters: 1454 * void 1455 * 1456 * Returns: 1457 * IP address 1458 * NULL: error 1459 */ 1460 char * 1461 gethostaddr(void) 1462 { 1463 static char s[MAXHOSTNAMELEN]; 1464 struct hostent *h; 1465 struct in_addr in; 1466 char *p; 1467 1468 if (gethostname(s, sizeof (s)) == -1) 1469 return (NULL); 1470 1471 if ((h = gethostbyname(s)) == NULL) 1472 return (NULL); 1473 1474 p = h->h_addr_list[0]; 1475 (void) memcpy(&in.s_addr, p, sizeof (in.s_addr)); 1476 return (inet_ntoa(in)); 1477 } 1478 1479 1480 /* 1481 * get_default_nic_addr 1482 * 1483 * Get the IP address of the default NIC 1484 */ 1485 char * 1486 get_default_nic_addr(void) 1487 { 1488 struct ifaddrlist *al = NULL; 1489 char errmsg[ERRBUFSIZE]; 1490 struct in_addr addr; 1491 int nifs; 1492 1493 nifs = ifaddrlist(&al, AF_INET, LIFC_EXTERNAL_SOURCE, errmsg); 1494 if (nifs <= 0) 1495 return (NULL); 1496 1497 /* pick the first interface's address */ 1498 addr = al[0].addr.addr; 1499 free(al); 1500 1501 return (inet_ntoa(IN_ADDR(addr.s_addr))); 1502 } 1503 1504 1505 /* 1506 * ndmpd_audit_backup 1507 * 1508 * Generate AUE_ndmp_backup audit record 1509 */ 1510 /*ARGSUSED*/ 1511 void 1512 ndmpd_audit_backup(ndmp_connection_t *conn, 1513 char *path, int dest, char *local_path, int result) 1514 { 1515 adt_event_data_t *event; 1516 1517 if ((event = adt_alloc_event(conn->conn_ah, ADT_ndmp_backup)) == NULL) { 1518 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1519 return; 1520 } 1521 event->adt_ndmp_backup.source = path; 1522 1523 if (dest == NDMP_ADDR_LOCAL) { 1524 event->adt_ndmp_backup.local_dest = local_path; 1525 } else { 1526 event->adt_ndmp_backup.remote_dest = conn->conn_sock; 1527 } 1528 1529 if (result == 0) { 1530 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 1531 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1532 } else { 1533 if (adt_put_event(event, ADT_FAILURE, result) != 0) 1534 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1535 } 1536 1537 adt_free_event(event); 1538 } 1539 1540 1541 /* 1542 * ndmpd_audit_restore 1543 * 1544 * Generate AUE_ndmp_restore audit record 1545 */ 1546 /*ARGSUSED*/ 1547 void 1548 ndmpd_audit_restore(ndmp_connection_t *conn, 1549 char *path, int dest, char *local_path, int result) 1550 { 1551 adt_event_data_t *event; 1552 1553 if ((event = adt_alloc_event(conn->conn_ah, 1554 ADT_ndmp_restore)) == NULL) { 1555 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1556 return; 1557 } 1558 event->adt_ndmp_restore.destination = path; 1559 1560 if (dest == NDMP_ADDR_LOCAL) { 1561 event->adt_ndmp_restore.local_source = local_path; 1562 } else { 1563 event->adt_ndmp_restore.remote_source = conn->conn_sock; 1564 } 1565 1566 if (result == 0) { 1567 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 1568 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1569 } else { 1570 if (adt_put_event(event, ADT_FAILURE, result) != 0) 1571 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1572 } 1573 1574 adt_free_event(event); 1575 } 1576 1577 1578 /* 1579 * ndmpd_audit_connect 1580 * 1581 * Generate AUE_ndmp_connect audit record 1582 */ 1583 /*ARGSUSED*/ 1584 void 1585 ndmpd_audit_connect(ndmp_connection_t *conn, int result) 1586 { 1587 adt_event_data_t *event; 1588 adt_termid_t *termid; 1589 1590 if (adt_load_termid(conn->conn_sock, &termid) != 0) { 1591 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1592 return; 1593 } 1594 1595 if (adt_set_user(conn->conn_ah, ADT_NO_ATTRIB, ADT_NO_ATTRIB, 1596 ADT_NO_ATTRIB, ADT_NO_ATTRIB, termid, ADT_NEW) != 0) { 1597 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1598 free(termid); 1599 return; 1600 } 1601 free(termid); 1602 1603 if ((event = adt_alloc_event(conn->conn_ah, 1604 ADT_ndmp_connect)) == NULL) { 1605 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1606 return; 1607 } 1608 1609 if (result == 0) { 1610 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 1611 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1612 } else { 1613 if (adt_put_event(event, ADT_FAILURE, result) != 0) 1614 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1615 } 1616 1617 adt_free_event(event); 1618 } 1619 1620 1621 /* 1622 * ndmpd_audit_disconnect 1623 * 1624 * Generate AUE_ndmp_disconnect audit record 1625 */ 1626 /*ARGSUSED*/ 1627 void 1628 ndmpd_audit_disconnect(ndmp_connection_t *conn) 1629 { 1630 adt_event_data_t *event; 1631 1632 if ((event = adt_alloc_event(conn->conn_ah, 1633 ADT_ndmp_disconnect)) == NULL) { 1634 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1635 return; 1636 } 1637 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 1638 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1639 1640 adt_free_event(event); 1641 } 1642 1643 void * 1644 ndmp_malloc(size_t size) 1645 { 1646 void *data; 1647 1648 if ((data = calloc(1, size)) == NULL) { 1649 NDMP_LOG(LOG_ERR, "Out of memory."); 1650 } 1651 1652 return (data); 1653 } 1654 1655 /* 1656 * get_backup_path_v3 1657 * 1658 * Get the backup path from the NDMP environment variables. 1659 * 1660 * Parameters: 1661 * params (input) - pointer to the parameters structure. 1662 * 1663 * Returns: 1664 * The backup path: if anything is specified 1665 * NULL: Otherwise 1666 */ 1667 char * 1668 get_backup_path_v3(ndmpd_module_params_t *params) 1669 { 1670 char *bkpath; 1671 1672 bkpath = MOD_GETENV(params, "PREFIX"); 1673 if (!bkpath) 1674 bkpath = MOD_GETENV(params, "FILESYSTEM"); 1675 1676 1677 if (!bkpath) { 1678 MOD_LOGV3(params, NDMP_LOG_ERROR, 1679 "Backup path not defined.\n"); 1680 } else { 1681 NDMP_LOG(LOG_DEBUG, "bkpath: \"%s\"", bkpath); 1682 } 1683 1684 return (bkpath); 1685 } 1686 1687 /* 1688 * get_backup_path 1689 * 1690 * Find the backup path from the environment variables (v2) 1691 */ 1692 char * 1693 get_backup_path_v2(ndmpd_module_params_t *params) 1694 { 1695 char *bkpath; 1696 1697 bkpath = MOD_GETENV(params, "PREFIX"); 1698 if (bkpath == NULL) 1699 bkpath = MOD_GETENV(params, "FILESYSTEM"); 1700 1701 if (bkpath == NULL) { 1702 MOD_LOG(params, "Error: restore path not specified.\n"); 1703 return (NULL); 1704 } 1705 1706 if (*bkpath != '/') { 1707 MOD_LOG(params, "Error: relative backup path not allowed.\n"); 1708 return (NULL); 1709 } 1710 1711 return (bkpath); 1712 } 1713