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