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