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