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 if (ndmp_log_open_file() != 0) { 771 NDMP_LOG(LOG_ERR, 772 "Could not open log file properly."); 773 } 774 775 /* 776 * Find ndmp port number to be used. If ndmpd is run as command line 777 * and port number is supplied, use that port number. If port number is 778 * is not supplied, find out if ndmp port property is set. If ndmp 779 * port property is set, use that port number otherwise use the defaule 780 * port number. 781 */ 782 if (ndmp_port == 0) { 783 if ((propval = ndmpd_get_prop(NDMP_TCP_PORT)) == NULL || 784 *propval == 0) 785 ndmp_port = NDMPPORT; 786 else 787 ndmp_port = strtol(propval, 0, 0); 788 } 789 790 if (ndmp_run(ndmp_port, connection_handler) == -1) 791 perror("ndmp_run ERROR"); 792 793 ndmp_log_close_file(); 794 } 795 796 /* 797 * connection_handler 798 * 799 * NDMP connection handler. 800 * Waits for, reads, and processes NDMP requests on a connection. 801 * 802 * Parameters: 803 * connection (input) - connection handle. 804 * 805 * Return: 806 * void 807 */ 808 void 809 connection_handler(ndmp_connection_t *connection) 810 { 811 static int conn_id = 1; 812 ndmpd_session_t session; 813 ndmp_notify_connected_request req; 814 int connection_fd; 815 816 (void) memset(&session, 0, sizeof (session)); 817 session.ns_connection = connection; 818 session.ns_eof = FALSE; 819 /* 820 * The 'protocol_version' must be 1 at first, since the client talks 821 * to the server in version 1 then they can move to a higher 822 * protocol version. 823 */ 824 session.ns_protocol_version = ndmp_ver; 825 826 session.ns_scsi.sd_is_open = -1; 827 session.ns_scsi.sd_devid = -1; 828 829 session.ns_scsi.sd_sid = 0; 830 session.ns_scsi.sd_lun = 0; 831 session.ns_scsi.sd_valid_target_set = 0; 832 (void) memset(session.ns_scsi.sd_adapter_name, 0, 833 sizeof (session.ns_scsi.sd_adapter_name)); 834 835 session.ns_tape.td_fd = -1; 836 session.ns_tape.td_sid = 0; 837 session.ns_tape.td_lun = 0; 838 (void) memset(session.ns_tape.td_adapter_name, 0, 839 sizeof (session.ns_tape.td_adapter_name)); 840 session.ns_tape.td_pos = 0; 841 session.ns_tape.td_record_count = 0; 842 session.ns_file_handler_list = 0; 843 844 (void) ndmpd_data_init(&session); 845 ndmpd_file_history_init(&session); 846 if (ndmpd_mover_init(&session) < 0) 847 return; 848 849 if (ndmp_lbr_init(&session) < 0) 850 return; 851 852 /* 853 * Setup defaults here. The init functions can not set defaults 854 * since the init functions are called by the stop request handlers 855 * and client set variables need to persist across data operations. 856 */ 857 session.ns_mover.md_record_size = MAX_RECORD_SIZE; 858 859 ndmp_set_client_data(connection, (void *)&session); 860 861 req.reason = NDMP_CONNECTED; 862 req.protocol_version = ndmp_ver; 863 req.text_reason = ""; 864 865 if (ndmp_send_request_lock(connection, NDMP_NOTIFY_CONNECTION_STATUS, 866 NDMP_NO_ERR, (void *)&req, 0) < 0) { 867 NDMP_LOG(LOG_DEBUG, "Connection terminated"); 868 return; 869 } 870 connection_fd = ndmp_get_fd(connection); 871 872 NDMP_LOG(LOG_DEBUG, "connection_fd: %d", connection_fd); 873 874 /* 875 * Add the handler function for the connection to the DMA. 876 */ 877 if (ndmpd_add_file_handler(&session, (void *)&session, connection_fd, 878 NDMPD_SELECT_MODE_READ, HC_CLIENT, connection_file_handler) != 0) { 879 NDMP_LOG(LOG_DEBUG, "Could not register session handler."); 880 return; 881 } 882 883 /* 884 * Register the connection in the list of active connections. 885 */ 886 if (ndmp_connect_list_add(connection, &conn_id) != 0) { 887 NDMP_LOG(LOG_ERR, 888 "Could not register the session to the server."); 889 (void) ndmpd_remove_file_handler(&session, connection_fd); 890 return; 891 } 892 893 session.hardlink_q = hardlink_q_init(); 894 895 while (session.ns_eof == FALSE) 896 (void) ndmpd_select(&session, TRUE, HC_ALL); 897 898 hardlink_q_cleanup(session.hardlink_q); 899 900 NDMP_LOG(LOG_DEBUG, "Connection terminated"); 901 902 (void) ndmpd_remove_file_handler(&session, connection_fd); 903 904 if (session.ns_scsi.sd_is_open != -1) { 905 NDMP_LOG(LOG_DEBUG, "scsi.is_open: %d", 906 session.ns_scsi.sd_is_open); 907 (void) ndmp_open_list_del(session.ns_scsi.sd_adapter_name, 908 session.ns_scsi.sd_sid, session.ns_scsi.sd_lun); 909 } 910 if (session.ns_tape.td_fd != -1) { 911 NDMP_LOG(LOG_DEBUG, "tape.fd: %d", session.ns_tape.td_fd); 912 (void) close(session.ns_tape.td_fd); 913 (void) ndmp_open_list_del(session.ns_tape.td_adapter_name, 914 session.ns_tape.td_sid, session.ns_tape.td_lun); 915 } 916 ndmpd_mover_shut_down(&session); 917 ndmp_lbr_cleanup(&session); 918 ndmpd_data_cleanup(&session); 919 ndmpd_file_history_cleanup(&session, FALSE); 920 ndmpd_mover_cleanup(&session); 921 922 (void) ndmp_connect_list_del(connection); 923 } 924 925 926 /* 927 * connection_file_handler 928 * 929 * ndmp_connection_t file handler function. 930 * Called by ndmpd_select when data is available to be read on the 931 * NDMP connection. 932 * 933 * Parameters: 934 * cookie (input) - session pointer. 935 * fd (input) - connection file descriptor. 936 * mode (input) - select mode. 937 * 938 * Returns: 939 * void. 940 */ 941 /*ARGSUSED*/ 942 static void 943 connection_file_handler(void *cookie, int fd, ulong_t mode) 944 { 945 ndmpd_session_t *session = (ndmpd_session_t *)cookie; 946 947 if (ndmp_process_requests(session->ns_connection) < 0) 948 session->ns_eof = TRUE; 949 } 950 951 952 /* ************* private functions *************************************** */ 953 954 /* 955 * ndmp_readit 956 * 957 * Low level read routine called by the xdrrec library. 958 * 959 * Parameters: 960 * connection (input) - connection pointer. 961 * buf (input) - location to store received data. 962 * len (input) - max number of bytes to read. 963 * 964 * Returns: 965 * >0 - number of bytes received. 966 * -1 - error. 967 */ 968 static int 969 ndmp_readit(void *connection_handle, caddr_t buf, int len) 970 { 971 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 972 973 len = read(connection->conn_sock, buf, len); 974 if (len <= 0) { 975 /* ndmp_connection_t has been closed. */ 976 connection->conn_eof = TRUE; 977 return (-1); 978 } 979 return (len); 980 } 981 982 /* 983 * ndmp_writeit 984 * 985 * Low level write routine called by the xdrrec library. 986 * 987 * Parameters: 988 * connection (input) - connection pointer. 989 * buf (input) - location to store received data. 990 * len (input) - max number of bytes to read. 991 * 992 * Returns: 993 * >0 - number of bytes sent. 994 * -1 - error. 995 */ 996 static int 997 ndmp_writeit(void *connection_handle, caddr_t buf, int len) 998 { 999 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 1000 register int n; 1001 register int cnt; 1002 1003 for (cnt = len; cnt > 0; cnt -= n, buf += n) { 1004 if ((n = write(connection->conn_sock, buf, cnt)) < 0) { 1005 connection->conn_eof = TRUE; 1006 return (-1); 1007 } 1008 } 1009 1010 return (len); 1011 } 1012 1013 1014 /* 1015 * ndmp_recv_msg 1016 * 1017 * Read the next message. 1018 * 1019 * Parameters: 1020 * connection (input) - connection pointer. 1021 * msg (output) - received message. 1022 * 1023 * Returns: 1024 * 0 - Message successfully received. 1025 * error number - Message related error. 1026 * -1 - Error decoding the message header. 1027 */ 1028 static int 1029 ndmp_recv_msg(ndmp_connection_t *connection) 1030 { 1031 bool_t(*xdr_func) (XDR *, ...) = NULL; 1032 1033 /* Decode the header. */ 1034 connection->conn_xdrs.x_op = XDR_DECODE; 1035 (void) xdrrec_skiprecord(&connection->conn_xdrs); 1036 if (!xdr_ndmp_header(&connection->conn_xdrs, 1037 &connection->conn_msginfo.mi_hdr)) 1038 return (-1); 1039 1040 /* Lookup info necessary for processing this message. */ 1041 if ((connection->conn_msginfo.mi_handler = ndmp_get_handler(connection, 1042 connection->conn_msginfo.mi_hdr.message)) == 0) { 1043 NDMP_LOG(LOG_DEBUG, "Message 0x%x not supported", 1044 connection->conn_msginfo.mi_hdr.message); 1045 return (NDMP_NOT_SUPPORTED_ERR); 1046 } 1047 connection->conn_msginfo.mi_body = 0; 1048 1049 if (connection->conn_msginfo.mi_hdr.error != NDMP_NO_ERR) 1050 return (0); 1051 1052 /* Determine body type */ 1053 if (connection->conn_msginfo.mi_hdr.message_type == 1054 NDMP_MESSAGE_REQUEST) { 1055 if (ndmp_check_auth_required( 1056 connection->conn_msginfo.mi_hdr.message) && 1057 !connection->conn_authorized) { 1058 NDMP_LOG(LOG_DEBUG, 1059 "Processing request 0x%x:connection not authorized", 1060 connection->conn_msginfo.mi_hdr.message); 1061 return (NDMP_NOT_AUTHORIZED_ERR); 1062 } 1063 if (connection->conn_msginfo.mi_handler->mh_sizeof_request > 1064 0) { 1065 xdr_func = 1066 connection->conn_msginfo.mi_handler->mh_xdr_request; 1067 if (xdr_func == NULL) { 1068 NDMP_LOG(LOG_DEBUG, 1069 "Processing request 0x%x: no xdr function " 1070 "in handler table", 1071 connection->conn_msginfo.mi_hdr.message); 1072 return (NDMP_NOT_SUPPORTED_ERR); 1073 } 1074 connection->conn_msginfo.mi_body = ndmp_malloc( 1075 connection->conn_msginfo.mi_handler-> 1076 mh_sizeof_request); 1077 if (connection->conn_msginfo.mi_body == NULL) 1078 return (NDMP_NO_MEM_ERR); 1079 1080 (void) memset(connection->conn_msginfo.mi_body, 0, 1081 connection->conn_msginfo.mi_handler-> 1082 mh_sizeof_request); 1083 } 1084 } else { 1085 if (connection->conn_msginfo.mi_handler->mh_sizeof_reply > 0) { 1086 xdr_func = 1087 connection->conn_msginfo.mi_handler->mh_xdr_reply; 1088 if (xdr_func == NULL) { 1089 NDMP_LOG(LOG_DEBUG, 1090 "Processing reply 0x%x: no xdr function " 1091 "in handler table", 1092 connection->conn_msginfo.mi_hdr.message); 1093 return (NDMP_NOT_SUPPORTED_ERR); 1094 } 1095 connection->conn_msginfo.mi_body = ndmp_malloc( 1096 connection->conn_msginfo.mi_handler-> 1097 mh_sizeof_reply); 1098 if (connection->conn_msginfo.mi_body == NULL) 1099 return (NDMP_NO_MEM_ERR); 1100 1101 (void) memset(connection->conn_msginfo.mi_body, 0, 1102 connection->conn_msginfo.mi_handler-> 1103 mh_sizeof_reply); 1104 } 1105 } 1106 1107 /* Decode message arguments if needed */ 1108 if (xdr_func) { 1109 if (!(*xdr_func)(&connection->conn_xdrs, 1110 connection->conn_msginfo.mi_body)) { 1111 NDMP_LOG(LOG_DEBUG, 1112 "Processing message 0x%x: error decoding arguments", 1113 connection->conn_msginfo.mi_hdr.message); 1114 free(connection->conn_msginfo.mi_body); 1115 connection->conn_msginfo.mi_body = 0; 1116 return (NDMP_XDR_DECODE_ERR); 1117 } 1118 } 1119 return (0); 1120 } 1121 1122 /* 1123 * ndmp_process_messages 1124 * 1125 * Reads the next message into the stream buffer. 1126 * Processes messages until the stream buffer is empty. 1127 * 1128 * This function processes all data in the stream buffer before returning. 1129 * This allows functions like poll() to be used to determine when new 1130 * messages have arrived. If only some of the messages in the stream buffer 1131 * were processed and then poll was called, poll() could block waiting for 1132 * a message that had already been received and read into the stream buffer. 1133 * 1134 * This function processes both request and reply messages. 1135 * Request messages are dispatched using the appropriate function from the 1136 * message handling table. 1137 * Only one reply messages may be pending receipt at a time. 1138 * A reply message, if received, is placed in connection->conn_msginfo 1139 * before returning to the caller. 1140 * Errors are reported if a reply is received but not expected or if 1141 * more than one reply message is received 1142 * 1143 * Parameters: 1144 * connection (input) - connection pointer. 1145 * reply_expected (output) - TRUE - a reply message is expected. 1146 * FALSE - no reply message is expected and 1147 * an error will be reported if a reply 1148 * is received. 1149 * 1150 * Returns: 1151 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 1152 * error processing reply message. 1153 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 1154 * reply seen. 1155 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 1156 * no reply seen. 1157 * NDMP_PROC_REP_ERR - error; connection no longer established. 1158 * 1159 * Notes: 1160 * If the peer is generating a large number of requests, a caller 1161 * looking for a reply will be blocked while the requests are handled. 1162 * This is because this function does not return until the stream 1163 * buffer is empty. 1164 * Code needs to be added to allow a return if the stream buffer 1165 * is not empty but there is data available on the socket. This will 1166 * prevent poll() from blocking and prevent a caller looking for a reply 1167 * from getting blocked by a bunch of requests. 1168 */ 1169 static int 1170 ndmp_process_messages(ndmp_connection_t *connection, boolean_t reply_expected) 1171 { 1172 msg_info_t reply_msginfo; 1173 boolean_t reply_read = FALSE; 1174 boolean_t reply_error = FALSE; 1175 int err; 1176 1177 NDMP_LOG(LOG_DEBUG, "reply_expected: %s", 1178 reply_expected == TRUE ? "TRUE" : "FALSE"); 1179 1180 (void) memset((void *)&reply_msginfo, 0, sizeof (msg_info_t)); 1181 1182 do { 1183 (void) memset((void *)&connection->conn_msginfo, 0, 1184 sizeof (msg_info_t)); 1185 1186 if ((err = ndmp_recv_msg(connection)) != NDMP_NO_ERR) { 1187 if (connection->conn_eof) { 1188 NDMP_LOG(LOG_DEBUG, "detected eof"); 1189 return (NDMP_PROC_ERR); 1190 } 1191 if (err < 1) { 1192 NDMP_LOG(LOG_DEBUG, "error decoding header"); 1193 1194 /* 1195 * Error occurred decoding the header. 1196 * Don't send a reply since we don't know 1197 * the message or if the message was even 1198 * a request message. To be safe, assume 1199 * that the message was a reply if a reply 1200 * was expected. Need to do this to prevent 1201 * hanging ndmp_send_request() waiting for a 1202 * reply. Don't set reply_read so that the 1203 * reply will be processed if it is received 1204 * later. 1205 */ 1206 if (reply_read == FALSE) 1207 reply_error = TRUE; 1208 1209 continue; 1210 } 1211 if (connection->conn_msginfo.mi_hdr.message_type 1212 != NDMP_MESSAGE_REQUEST) { 1213 NDMP_LOG(LOG_DEBUG, "received reply: 0x%x", 1214 connection->conn_msginfo.mi_hdr.message); 1215 1216 if (reply_expected == FALSE || 1217 reply_read == TRUE) 1218 NDMP_LOG(LOG_DEBUG, 1219 "Unexpected reply message: 0x%x", 1220 connection->conn_msginfo.mi_hdr. 1221 message); 1222 1223 ndmp_free_message((ndmp_connection_t *) 1224 connection); 1225 1226 if (reply_read == FALSE) { 1227 reply_read = TRUE; 1228 reply_error = TRUE; 1229 } 1230 continue; 1231 } 1232 NDMP_LOG(LOG_DEBUG, "received request: 0x%x", 1233 connection->conn_msginfo.mi_hdr.message); 1234 1235 (void) ndmp_send_response((ndmp_connection_t *) 1236 connection, err, NULL); 1237 ndmp_free_message((ndmp_connection_t *)connection); 1238 continue; 1239 } 1240 if (connection->conn_msginfo.mi_hdr.message_type 1241 != NDMP_MESSAGE_REQUEST) { 1242 NDMP_LOG(LOG_DEBUG, "received reply: 0x%x", 1243 connection->conn_msginfo.mi_hdr.message); 1244 1245 if (reply_expected == FALSE || reply_read == TRUE) { 1246 NDMP_LOG(LOG_DEBUG, 1247 "Unexpected reply message: 0x%x", 1248 connection->conn_msginfo.mi_hdr.message); 1249 ndmp_free_message((ndmp_connection_t *) 1250 connection); 1251 continue; 1252 } 1253 reply_read = TRUE; 1254 reply_msginfo = connection->conn_msginfo; 1255 continue; 1256 } 1257 NDMP_LOG(LOG_DEBUG, "received request: 0x%x", 1258 connection->conn_msginfo.mi_hdr.message); 1259 1260 /* 1261 * The following is needed to catch an improperly constructed 1262 * handler table or to deal with an NDMP client that is not 1263 * conforming to the negotiated protocol version. 1264 */ 1265 if (connection->conn_msginfo.mi_handler->mh_func == NULL) { 1266 NDMP_LOG(LOG_DEBUG, "No handler for message 0x%x", 1267 connection->conn_msginfo.mi_hdr.message); 1268 1269 (void) ndmp_send_response((ndmp_connection_t *) 1270 connection, NDMP_NOT_SUPPORTED_ERR, NULL); 1271 ndmp_free_message((ndmp_connection_t *)connection); 1272 continue; 1273 } 1274 /* 1275 * Call the handler function. 1276 * The handler will send any necessary reply. 1277 */ 1278 (*connection->conn_msginfo.mi_handler->mh_func) (connection, 1279 connection->conn_msginfo.mi_body); 1280 1281 ndmp_free_message((ndmp_connection_t *)connection); 1282 1283 } while (xdrrec_eof(&connection->conn_xdrs) == FALSE && 1284 connection->conn_eof == FALSE); 1285 1286 NDMP_LOG(LOG_DEBUG, "no more messages in stream buffer"); 1287 1288 if (connection->conn_eof == TRUE) { 1289 if (reply_msginfo.mi_body) 1290 free(reply_msginfo.mi_body); 1291 return (NDMP_PROC_ERR); 1292 } 1293 if (reply_error) { 1294 if (reply_msginfo.mi_body) 1295 free(reply_msginfo.mi_body); 1296 return (NDMP_PROC_REP_ERR); 1297 } 1298 if (reply_read) { 1299 connection->conn_msginfo = reply_msginfo; 1300 return (NDMP_PROC_MSG); 1301 } 1302 return (NDMP_PROC_REP); 1303 } 1304 1305 1306 /* 1307 * ndmp_get_interface 1308 * 1309 * Return the NDMP interface (e.g. config, scsi, tape) for the 1310 * specific message. 1311 * 1312 * Parameters: 1313 * message (input) - message number. 1314 * 1315 * Returns: 1316 * NULL - message not found. 1317 * pointer to handler info. 1318 */ 1319 static ndmp_handler_t * 1320 ndmp_get_interface(ndmp_message message) 1321 { 1322 ndmp_handler_t *ni = &ndmp_msghdl_tab[(message >> 8) % INT_MAXCMD]; 1323 1324 if ((message & 0xff) >= ni->hd_cnt) 1325 return (NULL); 1326 1327 /* Sanity check */ 1328 if (ni->hd_msgs[message & 0xff].hm_message != message) 1329 return (NULL); 1330 1331 return (ni); 1332 } 1333 1334 /* 1335 * ndmp_get_handler 1336 * 1337 * Return the handler info for the specified NDMP message. 1338 * 1339 * Parameters: 1340 * connection (input) - connection pointer. 1341 * message (input) - message number. 1342 * 1343 * Returns: 1344 * NULL - message not found. 1345 * pointer to handler info. 1346 */ 1347 static ndmp_msg_handler_t * 1348 ndmp_get_handler(ndmp_connection_t *connection, ndmp_message message) 1349 { 1350 ndmp_msg_handler_t *handler = NULL; 1351 1352 ndmp_handler_t *ni = ndmp_get_interface(message); 1353 int ver = connection->conn_version; 1354 1355 if (ni) 1356 handler = &ni->hd_msgs[message & 0xff].hm_msg_v[ver - 2]; 1357 1358 return (handler); 1359 } 1360 1361 /* 1362 * ndmp_check_auth_required 1363 * 1364 * Check if the connection needs to be authenticated before 1365 * this message is being processed. 1366 * 1367 * Parameters: 1368 * message (input) - message number. 1369 * 1370 * Returns: 1371 * TRUE - required 1372 * FALSE - not required 1373 */ 1374 static boolean_t 1375 ndmp_check_auth_required(ndmp_message message) 1376 { 1377 boolean_t auth_req = FALSE; 1378 ndmp_handler_t *ni = ndmp_get_interface(message); 1379 1380 if (ni) 1381 auth_req = ni->hd_msgs[message & 0xff].hm_auth_required; 1382 1383 return (auth_req); 1384 } 1385 1386 /* 1387 * tcp_accept 1388 * 1389 * A wrapper around accept for retrying and getting the IP address 1390 * 1391 * Parameters: 1392 * listen_sock (input) - the socket for listening 1393 * inaddr_p (output) - the IP address of peer connection 1394 * 1395 * Returns: 1396 * socket for the accepted connection 1397 * -1: error 1398 */ 1399 int 1400 tcp_accept(int listen_sock, unsigned int *inaddr_p) 1401 { 1402 struct sockaddr_in sin; 1403 int sock, i; 1404 int try; 1405 1406 for (try = 0; try < 3; try++) { 1407 i = sizeof (sin); 1408 sock = accept(listen_sock, (struct sockaddr *)&sin, &i); 1409 if (sock < 0) { 1410 continue; 1411 } 1412 *inaddr_p = sin.sin_addr.s_addr; 1413 return (sock); 1414 } 1415 return (-1); 1416 } 1417 1418 1419 /* 1420 * tcp_get_peer 1421 * 1422 * Get the peer IP address for a connection 1423 * 1424 * Parameters: 1425 * sock (input) - the active socket 1426 * inaddr_p (output) - the IP address of peer connection 1427 * port_p (output) - the port number of peer connection 1428 * 1429 * Returns: 1430 * socket for the accepted connection 1431 * -1: error 1432 */ 1433 int 1434 tcp_get_peer(int sock, unsigned int *inaddr_p, int *port_p) 1435 { 1436 struct sockaddr_in sin; 1437 int i, rc; 1438 1439 i = sizeof (sin); 1440 rc = getpeername(sock, (struct sockaddr *)&sin, &i); 1441 if (rc != 0) 1442 return (-1); 1443 1444 if (inaddr_p) 1445 *inaddr_p = sin.sin_addr.s_addr; 1446 1447 if (port_p) 1448 *port_p = ntohs(sin.sin_port); 1449 1450 return (sock); 1451 1452 } 1453 1454 /* 1455 * gethostaddr 1456 * 1457 * Get the IP address string of the current host 1458 * 1459 * Parameters: 1460 * void 1461 * 1462 * Returns: 1463 * IP address 1464 * NULL: error 1465 */ 1466 char * 1467 gethostaddr(void) 1468 { 1469 static char s[MAXHOSTNAMELEN]; 1470 struct hostent *h; 1471 struct in_addr in; 1472 char *p; 1473 1474 if (gethostname(s, sizeof (s)) == -1) 1475 return (NULL); 1476 1477 if ((h = gethostbyname(s)) == NULL) 1478 return (NULL); 1479 1480 p = h->h_addr_list[0]; 1481 (void) memcpy(&in.s_addr, p, sizeof (in.s_addr)); 1482 return (inet_ntoa(in)); 1483 } 1484 1485 1486 /* 1487 * get_default_nic_addr 1488 * 1489 * Get the IP address of the default NIC 1490 */ 1491 char * 1492 get_default_nic_addr(void) 1493 { 1494 struct ifaddrlist *al = NULL; 1495 char errmsg[ERRBUFSIZE]; 1496 struct in_addr addr; 1497 int nifs; 1498 1499 nifs = ifaddrlist(&al, AF_INET, LIFC_EXTERNAL_SOURCE, errmsg); 1500 if (nifs <= 0) 1501 return (NULL); 1502 1503 /* pick the first interface's address */ 1504 addr = al[0].addr.addr; 1505 free(al); 1506 1507 return (inet_ntoa(IN_ADDR(addr.s_addr))); 1508 } 1509 1510 1511 /* 1512 * ndmpd_audit_backup 1513 * 1514 * Generate AUE_ndmp_backup audit record 1515 */ 1516 /*ARGSUSED*/ 1517 void 1518 ndmpd_audit_backup(ndmp_connection_t *conn, 1519 char *path, int dest, char *local_path, int result) 1520 { 1521 adt_event_data_t *event; 1522 1523 if ((event = adt_alloc_event(conn->conn_ah, ADT_ndmp_backup)) == NULL) { 1524 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1525 return; 1526 } 1527 event->adt_ndmp_backup.source = path; 1528 1529 if (dest == NDMP_ADDR_LOCAL) { 1530 event->adt_ndmp_backup.local_dest = local_path; 1531 } else { 1532 event->adt_ndmp_backup.remote_dest = conn->conn_sock; 1533 } 1534 1535 if (result == 0) { 1536 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 1537 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1538 } else { 1539 if (adt_put_event(event, ADT_FAILURE, result) != 0) 1540 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1541 } 1542 1543 adt_free_event(event); 1544 } 1545 1546 1547 /* 1548 * ndmpd_audit_restore 1549 * 1550 * Generate AUE_ndmp_restore audit record 1551 */ 1552 /*ARGSUSED*/ 1553 void 1554 ndmpd_audit_restore(ndmp_connection_t *conn, 1555 char *path, int dest, char *local_path, int result) 1556 { 1557 adt_event_data_t *event; 1558 1559 if ((event = adt_alloc_event(conn->conn_ah, 1560 ADT_ndmp_restore)) == NULL) { 1561 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1562 return; 1563 } 1564 event->adt_ndmp_restore.destination = path; 1565 1566 if (dest == NDMP_ADDR_LOCAL) { 1567 event->adt_ndmp_restore.local_source = local_path; 1568 } else { 1569 event->adt_ndmp_restore.remote_source = conn->conn_sock; 1570 } 1571 1572 if (result == 0) { 1573 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 1574 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1575 } else { 1576 if (adt_put_event(event, ADT_FAILURE, result) != 0) 1577 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1578 } 1579 1580 adt_free_event(event); 1581 } 1582 1583 1584 /* 1585 * ndmpd_audit_connect 1586 * 1587 * Generate AUE_ndmp_connect audit record 1588 */ 1589 /*ARGSUSED*/ 1590 void 1591 ndmpd_audit_connect(ndmp_connection_t *conn, int result) 1592 { 1593 adt_event_data_t *event; 1594 adt_termid_t *termid; 1595 1596 if (adt_load_termid(conn->conn_sock, &termid) != 0) { 1597 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1598 return; 1599 } 1600 1601 if (adt_set_user(conn->conn_ah, ADT_NO_ATTRIB, ADT_NO_ATTRIB, 1602 ADT_NO_ATTRIB, ADT_NO_ATTRIB, termid, ADT_NEW) != 0) { 1603 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1604 free(termid); 1605 return; 1606 } 1607 free(termid); 1608 1609 if ((event = adt_alloc_event(conn->conn_ah, 1610 ADT_ndmp_connect)) == NULL) { 1611 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1612 return; 1613 } 1614 1615 if (result == 0) { 1616 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 1617 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1618 } else { 1619 if (adt_put_event(event, ADT_FAILURE, result) != 0) 1620 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1621 } 1622 1623 adt_free_event(event); 1624 } 1625 1626 1627 /* 1628 * ndmpd_audit_disconnect 1629 * 1630 * Generate AUE_ndmp_disconnect audit record 1631 */ 1632 /*ARGSUSED*/ 1633 void 1634 ndmpd_audit_disconnect(ndmp_connection_t *conn) 1635 { 1636 adt_event_data_t *event; 1637 1638 if ((event = adt_alloc_event(conn->conn_ah, 1639 ADT_ndmp_disconnect)) == NULL) { 1640 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1641 return; 1642 } 1643 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 1644 NDMP_LOG(LOG_ERR, "Audit failure: %m."); 1645 1646 adt_free_event(event); 1647 } 1648 1649 void * 1650 ndmp_malloc(size_t size) 1651 { 1652 void *data; 1653 1654 if ((data = calloc(1, size)) == NULL) { 1655 NDMP_LOG(LOG_ERR, "Out of memory."); 1656 } 1657 1658 return (data); 1659 } 1660 1661 /* 1662 * get_backup_path_v3 1663 * 1664 * Get the backup path from the NDMP environment variables. 1665 * 1666 * Parameters: 1667 * params (input) - pointer to the parameters structure. 1668 * 1669 * Returns: 1670 * The backup path: if anything is specified 1671 * NULL: Otherwise 1672 */ 1673 char * 1674 get_backup_path_v3(ndmpd_module_params_t *params) 1675 { 1676 char *bkpath; 1677 1678 bkpath = MOD_GETENV(params, "PREFIX"); 1679 if (!bkpath) 1680 bkpath = MOD_GETENV(params, "FILESYSTEM"); 1681 1682 1683 if (!bkpath) { 1684 MOD_LOGV3(params, NDMP_LOG_ERROR, 1685 "Backup path not defined.\n"); 1686 } else { 1687 NDMP_LOG(LOG_DEBUG, "bkpath: \"%s\"", bkpath); 1688 } 1689 1690 return (bkpath); 1691 } 1692 1693 /* 1694 * get_backup_path 1695 * 1696 * Find the backup path from the environment variables (v2) 1697 */ 1698 char * 1699 get_backup_path_v2(ndmpd_module_params_t *params) 1700 { 1701 char *bkpath; 1702 1703 bkpath = MOD_GETENV(params, "PREFIX"); 1704 if (bkpath == NULL) 1705 bkpath = MOD_GETENV(params, "FILESYSTEM"); 1706 1707 if (bkpath == NULL) { 1708 MOD_LOG(params, "Error: restore path not specified.\n"); 1709 return (NULL); 1710 } 1711 1712 if (*bkpath != '/') { 1713 MOD_LOG(params, "Error: relative backup path not allowed.\n"); 1714 return (NULL); 1715 } 1716 1717 return (bkpath); 1718 } 1719