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