8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / ndmpd / ndmp / ndmpd_comm.c
blob08e525516f2a2720e9d715484877d8cf356c10a5
1 /*
2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
4 */
6 /*
7 * BSD 3 Clause License
9 * Copyright (c) 2007, The Storage Networking Industry Association.
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.
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.
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.
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.
39 /* Copyright (c) 2007, The Storage Networking Industry Association. */
40 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <sys/time.h>
45 #include <sys/uio.h>
46 #include <unistd.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include <errno.h>
50 #include <netdb.h>
51 #include <netinet/in.h>
52 #include <arpa/inet.h>
53 #include <libinetutil.h>
54 #include "ndmpd.h"
55 #include "ndmpd_common.h"
57 #define NDMP_PROC_ERR -1
58 #define NDMP_PROC_MSG 1
59 #define NDMP_PROC_REP 0
60 #define NDMP_PROC_REP_ERR 2
63 * The ndmp connection version can be set through command line. If command line
64 * is not specified it will be set from the ndmp SMF version property.
66 int ndmp_ver = 0;
69 * The NDMP listening port number
71 int ndmp_port = 0;
74 * Restore path mechanism definition
75 * 0 means partial path restore and
76 * 1 means full path restore.
77 * Refer to NDMP_FULL_RESTORE_PATH for partial path and full path definition.
79 int ndmp_full_restore_path = 1;
82 * Do we support Direct Access Restore?
84 int ndmp_dar_support = 0;
87 * ndmp_connection_t handler function
89 static ndmpd_file_handler_func_t connection_file_handler;
91 extern ndmp_handler_t ndmp_msghdl_tab[];
93 static int ndmp_readit(void *connection_handle,
94 caddr_t buf,
95 int len);
96 static int ndmp_writeit(void *connection_handle,
97 caddr_t buf,
98 int len);
99 static int ndmp_recv_msg(ndmp_connection_t *connection);
100 static int ndmp_process_messages(ndmp_connection_t *connection,
101 boolean_t reply_expected);
102 static ndmp_msg_handler_t *ndmp_get_handler(ndmp_connection_t *connection,
103 ndmp_message message);
104 static boolean_t ndmp_check_auth_required(ndmp_message message);
105 static ndmp_handler_t *ndmp_get_interface(ndmp_message message);
106 void *ndmpd_worker(void *ptarg);
108 #ifdef lint
109 bool_t
110 xdr_ndmp_header(XDR *xdrs, ndmp_header *objp)
112 xdrs = xdrs;
113 objp = objp;
114 return (0);
116 #endif /* lint */
119 * ndmp_create_connection
121 * Allocate and initialize a connection structure.
123 * Parameters:
124 * handler_tbl (input) - message handlers.
126 * Returns:
127 * NULL - error
128 * connection pointer
130 * Notes:
131 * The returned connection should be destroyed using
132 * ndmp_destroy_connection().
134 ndmp_connection_t *
135 ndmp_create_connection(void)
137 ndmp_connection_t *connection;
139 connection = ndmp_malloc(sizeof (ndmp_connection_t));
140 if (connection == NULL)
141 return (NULL);
143 connection->conn_sock = -1;
144 connection->conn_my_sequence = 0;
145 connection->conn_authorized = FALSE;
146 connection->conn_eof = FALSE;
147 connection->conn_msginfo.mi_body = 0;
148 connection->conn_version = ndmp_ver;
149 connection->conn_client_data = 0;
150 (void) mutex_init(&connection->conn_lock, 0, NULL);
151 connection->conn_xdrs.x_ops = 0;
153 xdrrec_create(&connection->conn_xdrs, 0, 0, (caddr_t)connection,
154 ndmp_readit, ndmp_writeit);
156 if (connection->conn_xdrs.x_ops == 0) {
157 NDMP_LOG(LOG_DEBUG, "xdrrec_create failed");
158 (void) mutex_destroy(&connection->conn_lock);
159 (void) close(connection->conn_sock);
160 free(connection);
161 return (0);
163 return ((ndmp_connection_t *)connection);
167 * ndmp_destroy_connection
169 * Shutdown a connection and release allocated resources.
171 * Parameters:
172 * connection_handle (Input) - connection handle.
174 * Returns:
175 * void
177 void
178 ndmp_destroy_connection(ndmp_connection_t *connection_handle)
180 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
182 if (connection->conn_sock >= 0) {
183 (void) mutex_destroy(&connection->conn_lock);
184 (void) close(connection->conn_sock);
185 connection->conn_sock = -1;
187 xdr_destroy(&connection->conn_xdrs);
188 free(connection);
193 * ndmp_close
195 * Close a connection.
197 * Parameters:
198 * connection_handle (Input) - connection handle.
200 * Returns:
201 * void
203 void
204 ndmp_close(ndmp_connection_t *connection_handle)
206 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
208 ndmpd_audit_disconnect(connection);
209 if (connection->conn_sock >= 0) {
210 (void) mutex_destroy(&connection->conn_lock);
211 (void) close(connection->conn_sock);
212 connection->conn_sock = -1;
214 connection->conn_eof = TRUE;
217 * We should close all the tapes that are used by this connection.
218 * In some cases the ndmp client opens a tape, but does not close the
219 * tape and closes the connection.
221 ndmp_open_list_release(connection_handle);
225 * ndmp_start_worker
227 * Initializes and starts a ndmp_worker thread
230 ndmp_start_worker(ndmpd_worker_arg_t *argp)
232 pthread_attr_t tattr;
233 int rc;
235 (void) pthread_attr_init(&tattr);
236 (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
237 rc = pthread_create(NULL, &tattr, ndmpd_worker, (void *)argp);
238 (void) pthread_attr_destroy(&tattr);
239 return (rc);
243 * ndmp_run
245 * Creates a socket for listening and accepting connections
246 * from NDMP clients.
247 * Accepts connections and passes each connection to the connection
248 * handler.
250 * Parameters:
251 * port (input) - NDMP server port.
252 * If 0, the port number will be retrieved from
253 * the network service database. If not found there,
254 * the default NDMP port number (from ndmp.x)
255 * will be used.
256 * handler (input) - connection handler function.
258 * Returns:
259 * This function normally never returns unless there's error.
260 * -1 : error
262 * Notes:
263 * This function does not return unless encountering an error
264 * related to the listen socket.
267 ndmp_run(ulong_t port, ndmp_con_handler_func_t con_handler_func)
269 int ns;
270 int on;
271 int server_socket;
272 unsigned int ipaddr;
273 struct sockaddr_in sin;
274 ndmpd_worker_arg_t *argp;
276 sin.sin_family = AF_INET;
277 sin.sin_addr.s_addr = INADDR_ANY;
278 sin.sin_port = htons(port);
280 if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
281 NDMP_LOG(LOG_DEBUG, "Socket error: %m");
282 return (-1);
285 on = 1;
286 (void) setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR,
287 (char *)&on, sizeof (on));
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);
295 if (listen(server_socket, 5) < 0) {
296 NDMP_LOG(LOG_DEBUG, "listen error: %m");
297 (void) close(server_socket);
298 return (-1);
301 for (; ; ) {
302 if ((ns = tcp_accept(server_socket, &ipaddr)) < 0) {
303 NDMP_LOG(LOG_DEBUG, "tcp_accept error: %m");
304 continue;
306 NDMP_LOG(LOG_DEBUG, "connection fd: %d", ns);
307 set_socket_options(ns);
309 if ((argp = ndmp_malloc(sizeof (ndmpd_worker_arg_t))) != NULL) {
310 argp->nw_sock = ns;
311 argp->nw_ipaddr = ipaddr;
312 argp->nw_con_handler_func = con_handler_func;
313 (void) ndmp_start_worker(argp);
319 * ndmpd_worker thread
321 * Parameters:
322 * argp (input) - structure containing socket and handler function
324 * Returns:
325 * 0 - successful connection.
326 * -1 - error.
328 void *
329 ndmpd_worker(void *ptarg)
331 int sock;
332 ndmp_connection_t *connection;
333 ndmpd_worker_arg_t *argp = (ndmpd_worker_arg_t *)ptarg;
335 if (!argp)
336 return ((void *)-1);
338 NS_INC(trun);
339 sock = argp->nw_sock;
341 if ((connection = ndmp_create_connection()) == NULL) {
342 (void) close(sock);
343 free(argp);
344 exit(1);
347 /* initialize auditing session */
348 if (adt_start_session(&connection->conn_ah, NULL, 0) != 0) {
349 free(argp);
350 return ((void *)-1);
353 ((ndmp_connection_t *)connection)->conn_sock = sock;
354 (*argp->nw_con_handler_func)(connection);
355 (void) adt_end_session(connection->conn_ah);
356 ndmp_destroy_connection(connection);
357 NS_DEC(trun);
359 free(argp);
360 return (NULL);
364 * ndmp_process_requests
366 * Reads the next request message into the stream buffer.
367 * Processes messages until the stream buffer is empty.
369 * Parameters:
370 * connection_handle (input) - connection handle.
372 * Returns:
373 * 0 - 1 or more messages successfully processed.
374 * -1 - error; connection no longer established.
377 ndmp_process_requests(ndmp_connection_t *connection_handle)
379 int rv;
380 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
382 (void) mutex_lock(&connection->conn_lock);
383 rv = 0;
384 if (ndmp_process_messages(connection, FALSE) < 0)
385 rv = -1;
387 (void) mutex_unlock(&connection->conn_lock);
388 return (rv);
393 * ndmp_send_request
395 * Send an NDMP request message.
397 * Parameters:
398 * connection_handle (input) - connection pointer.
399 * message (input) - message number.
400 * err (input) - error code to place in header.
401 * request_data (input) - message body.
402 * reply (output) - reply message. If 0, reply will be
403 * discarded.
405 * Returns:
406 * 0 - successful send.
407 * -1 - error.
408 * otherwise - error from reply header.
410 * Notes:
411 * - The reply body is only returned if the error code is NDMP_NO_ERR.
414 ndmp_send_request(ndmp_connection_t *connection_handle, ndmp_message message,
415 ndmp_error err, void *request_data, void **reply)
417 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
418 ndmp_header header;
419 ndmp_msg_handler_t *handler;
420 int r;
421 struct timeval time;
423 /* Lookup info necessary for processing this request. */
424 if (!(handler = ndmp_get_handler(connection, message))) {
425 NDMP_LOG(LOG_DEBUG, "Sending message 0x%x: not supported",
426 message);
427 return (-1);
429 (void) gettimeofday(&time, 0);
431 header.sequence = ++(connection->conn_my_sequence);
432 header.time_stamp = time.tv_sec;
433 header.message_type = NDMP_MESSAGE_REQUEST;
434 header.message = message;
435 header.reply_sequence = 0;
436 header.error = err;
438 connection->conn_xdrs.x_op = XDR_ENCODE;
439 if (!xdr_ndmp_header(&connection->conn_xdrs, &header)) {
440 NDMP_LOG(LOG_DEBUG,
441 "Sending message 0x%x: encoding request header", message);
442 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
443 return (-1);
445 if (err == NDMP_NO_ERR && handler->mh_xdr_request && request_data) {
446 if (!(*handler->mh_xdr_request)(&connection->conn_xdrs,
447 request_data)) {
448 NDMP_LOG(LOG_DEBUG,
449 "Sending message 0x%x: encoding request body",
450 message);
451 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
452 return (-1);
455 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
457 if (handler->mh_xdr_reply == 0) {
458 NDMP_LOG(LOG_DEBUG, "handler->mh_xdr_reply == 0");
459 return (0);
463 * Process messages until the reply to this request has been
464 * processed.
466 for (; ; ) {
467 r = ndmp_process_messages(connection, TRUE);
469 /* connection error? */
470 if (r < 0)
471 return (-1);
473 /* no reply received? */
474 if (r == 0)
475 continue;
477 /* reply received? */
478 if (r == 1) {
479 if (message !=
480 connection->conn_msginfo.mi_hdr.message) {
481 NDMP_LOG(LOG_DEBUG,
482 "Received unexpected reply 0x%x",
483 connection->conn_msginfo.mi_hdr.message);
484 ndmp_free_message(connection_handle);
485 return (-1);
487 if (reply != NULL)
488 *reply = connection->conn_msginfo.mi_body;
489 else
490 ndmp_free_message(connection_handle);
492 return (connection->conn_msginfo.mi_hdr.error);
494 /* error handling reply */
496 return (-1);
502 * ndmp_send_request_lock
504 * A wrapper for ndmp_send_request with locks.
506 * Parameters:
507 * connection_handle (input) - connection pointer.
508 * message (input) - message number.
509 * err (input) - error code to place in header.
510 * request_data (input) - message body.
511 * reply (output) - reply message. If 0, reply will be
512 * discarded.
514 * Returns:
515 * 0 - successful send.
516 * -1 - error.
517 * otherwise - error from reply header.
519 * Notes:
520 * - The reply body is only returned if the error code is NDMP_NO_ERR.
523 ndmp_send_request_lock(ndmp_connection_t *connection_handle,
524 ndmp_message message, ndmp_error err, void *request_data, void **reply)
526 int rv;
527 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
529 (void) mutex_lock(&connection->conn_lock);
531 rv = ndmp_send_request(connection_handle, message, err, request_data,
532 reply);
533 (void) mutex_unlock(&connection->conn_lock);
534 return (rv);
539 * ndmp_send_response
541 * Send an NDMP reply message.
543 * Parameters:
544 * connection_handle (input) - connection pointer.
545 * err (input) - error code to place in header.
546 * reply (input) - reply message body.
548 * Returns:
549 * 0 - successful send.
550 * -1 - error.
552 * Notes:
553 * - The body is only sent if the error code is NDMP_NO_ERR.
556 ndmp_send_response(ndmp_connection_t *connection_handle, ndmp_error err,
557 void *reply)
559 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
560 ndmp_header header;
561 struct timeval time;
563 (void) gettimeofday(&time, 0);
565 header.sequence = ++(connection->conn_my_sequence);
566 header.time_stamp = time.tv_sec;
567 header.message_type = NDMP_MESSAGE_REPLY;
568 header.message = connection->conn_msginfo.mi_hdr.message;
569 header.reply_sequence = connection->conn_msginfo.mi_hdr.sequence;
570 header.error = err;
572 connection->conn_xdrs.x_op = XDR_ENCODE;
573 if (!xdr_ndmp_header(&connection->conn_xdrs, &header)) {
574 NDMP_LOG(LOG_DEBUG, "Sending message 0x%x: "
575 "encoding reply header",
576 header.message);
577 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
578 return (-1);
580 if (err == NDMP_NO_ERR &&
581 connection->conn_msginfo.mi_handler->mh_xdr_reply &&
582 reply) {
583 if (!(*connection->conn_msginfo.mi_handler->mh_xdr_reply)(
584 &connection->conn_xdrs, reply)) {
585 NDMP_LOG(LOG_DEBUG,
586 "Sending message 0x%x: encoding reply body",
587 header.message);
588 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
589 return (-1);
592 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
593 return (0);
597 * ndmp_free_message
599 * Free the memory of NDMP message body.
601 * Parameters:
602 * connection_handle (input) - connection pointer.
604 * Returns:
605 * void
608 void
609 ndmp_free_message(ndmp_connection_t *connection_handle)
611 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
613 if (connection->conn_msginfo.mi_handler == NULL ||
614 connection->conn_msginfo.mi_body == NULL)
615 return;
617 connection->conn_xdrs.x_op = XDR_FREE;
618 if (connection->conn_msginfo.mi_hdr.message_type ==
619 NDMP_MESSAGE_REQUEST) {
620 if (connection->conn_msginfo.mi_handler->mh_xdr_request)
621 (*connection->conn_msginfo.mi_handler->mh_xdr_request)(
622 &connection->conn_xdrs,
623 connection->conn_msginfo.mi_body);
624 } else {
625 if (connection->conn_msginfo.mi_handler->mh_xdr_reply)
626 (*connection->conn_msginfo.mi_handler->mh_xdr_reply)(
627 &connection->conn_xdrs,
628 connection->conn_msginfo.mi_body);
631 (void) free(connection->conn_msginfo.mi_body);
632 connection->conn_msginfo.mi_body = 0;
636 * ndmp_get_fd
638 * Returns the connection file descriptor.
640 * Parameters:
641 * connection_handle (input) - connection handle
643 * Returns:
644 * >=0 - file descriptor.
645 * -1 - connection not open.
648 ndmp_get_fd(ndmp_connection_t *connection_handle)
650 return (((ndmp_connection_t *)connection_handle)->conn_sock);
655 * ndmp_set_client_data
657 * This function provides a means for the library client to provide
658 * a pointer to some user data structure that is retrievable by
659 * each message handler via ndmp_get_client_data.
661 * Parameters:
662 * connection_handle (input) - connection handle.
663 * client_data (input) - user data pointer.
665 * Returns:
666 * void
668 void
669 ndmp_set_client_data(ndmp_connection_t *connection_handle, void *client_data)
671 ((ndmp_connection_t *)connection_handle)->conn_client_data =
672 client_data;
677 * ndmp_get_client_data
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.
683 * Parameters:
684 * connection_handle (input) - connection handle.
686 * Returns:
687 * client data pointer.
689 void *
690 ndmp_get_client_data(ndmp_connection_t *connection_handle)
692 return (((ndmp_connection_t *)connection_handle)->conn_client_data);
697 * ndmp_set_version
699 * Sets the NDMP protocol version to be used on the connection.
701 * Parameters:
702 * connection_handle (input) - connection handle.
703 * version (input) - protocol version.
705 * Returns:
706 * void
708 void
709 ndmp_set_version(ndmp_connection_t *connection_handle, ushort_t version)
711 ((ndmp_connection_t *)connection_handle)->conn_version = version;
716 * ndmp_get_version
718 * Gets the NDMP protocol version in use on the connection.
720 * Parameters:
721 * connection_handle (input) - connection handle.
722 * version (input) - protocol version.
724 * Returns:
725 * void
727 ushort_t
728 ndmp_get_version(ndmp_connection_t *connection_handle)
730 return (((ndmp_connection_t *)connection_handle)->conn_version);
735 * ndmp_set_authorized
737 * Mark the connection as either having been authorized or not.
739 * Parameters:
740 * connection_handle (input) - connection handle.
741 * authorized (input) - TRUE or FALSE.
743 * Returns:
744 * void
746 void
747 ndmp_set_authorized(ndmp_connection_t *connection_handle, boolean_t authorized)
749 ((ndmp_connection_t *)connection_handle)->conn_authorized = authorized;
754 * ndmpd_main
756 * NDMP main function called from main().
758 * Parameters:
759 * void
761 * Returns:
762 * void
764 void
765 ndmpd_main(void)
767 char *propval;
769 ndmp_load_params();
772 * Find ndmp port number to be used. If ndmpd is run as command line
773 * and port number is supplied, use that port number. If port number is
774 * is not supplied, find out if ndmp port property is set. If ndmp
775 * port property is set, use that port number otherwise use the defaule
776 * port number.
778 if (ndmp_port == 0) {
779 if ((propval = ndmpd_get_prop(NDMP_TCP_PORT)) == NULL ||
780 *propval == 0)
781 ndmp_port = NDMPPORT;
782 else
783 ndmp_port = strtol(propval, 0, 0);
786 if (ndmp_run(ndmp_port, connection_handler) == -1)
787 perror("ndmp_run ERROR");
791 * connection_handler
793 * NDMP connection handler.
794 * Waits for, reads, and processes NDMP requests on a connection.
796 * Parameters:
797 * connection (input) - connection handle.
799 * Return:
800 * void
802 void
803 connection_handler(ndmp_connection_t *connection)
805 static int conn_id = 1;
806 ndmpd_session_t session;
807 ndmp_notify_connected_request req;
808 int connection_fd;
810 (void) memset(&session, 0, sizeof (session));
811 session.ns_connection = connection;
812 session.ns_eof = FALSE;
814 * The 'protocol_version' must be 1 at first, since the client talks
815 * to the server in version 1 then they can move to a higher
816 * protocol version.
818 session.ns_protocol_version = ndmp_ver;
820 session.ns_scsi.sd_is_open = -1;
821 session.ns_scsi.sd_devid = -1;
823 session.ns_scsi.sd_sid = 0;
824 session.ns_scsi.sd_lun = 0;
825 session.ns_scsi.sd_valid_target_set = 0;
826 (void) memset(session.ns_scsi.sd_adapter_name, 0,
827 sizeof (session.ns_scsi.sd_adapter_name));
829 session.ns_tape.td_fd = -1;
830 session.ns_tape.td_sid = 0;
831 session.ns_tape.td_lun = 0;
832 (void) memset(session.ns_tape.td_adapter_name, 0,
833 sizeof (session.ns_tape.td_adapter_name));
834 session.ns_tape.td_pos = 0;
835 session.ns_tape.td_record_count = 0;
836 session.ns_file_handler_list = 0;
838 (void) ndmpd_data_init(&session);
839 ndmpd_file_history_init(&session);
840 if (ndmpd_mover_init(&session) < 0)
841 return;
843 if (ndmp_lbr_init(&session) < 0)
844 return;
847 * Setup defaults here. The init functions can not set defaults
848 * since the init functions are called by the stop request handlers
849 * and client set variables need to persist across data operations.
851 session.ns_mover.md_record_size = MAX_RECORD_SIZE;
853 ndmp_set_client_data(connection, (void *)&session);
855 req.reason = NDMP_CONNECTED;
856 req.protocol_version = ndmp_ver;
857 req.text_reason = "";
859 if (ndmp_send_request_lock(connection, NDMP_NOTIFY_CONNECTION_STATUS,
860 NDMP_NO_ERR, (void *)&req, 0) < 0) {
861 NDMP_LOG(LOG_DEBUG, "Connection terminated");
862 return;
864 connection_fd = ndmp_get_fd(connection);
866 NDMP_LOG(LOG_DEBUG, "connection_fd: %d", connection_fd);
869 * Add the handler function for the connection to the DMA.
871 if (ndmpd_add_file_handler(&session, (void *)&session, connection_fd,
872 NDMPD_SELECT_MODE_READ, HC_CLIENT, connection_file_handler) != 0) {
873 NDMP_LOG(LOG_DEBUG, "Could not register session handler.");
874 return;
878 * Register the connection in the list of active connections.
880 if (ndmp_connect_list_add(connection, &conn_id) != 0) {
881 NDMP_LOG(LOG_ERR,
882 "Could not register the session to the server.");
883 (void) ndmpd_remove_file_handler(&session, connection_fd);
884 return;
887 session.hardlink_q = hardlink_q_init();
889 while (session.ns_eof == FALSE)
890 (void) ndmpd_select(&session, TRUE, HC_ALL);
892 hardlink_q_cleanup(session.hardlink_q);
894 NDMP_LOG(LOG_DEBUG, "Connection terminated");
896 (void) ndmpd_remove_file_handler(&session, connection_fd);
898 if (session.ns_scsi.sd_is_open != -1) {
899 NDMP_LOG(LOG_DEBUG, "scsi.is_open: %d",
900 session.ns_scsi.sd_is_open);
901 (void) ndmp_open_list_del(session.ns_scsi.sd_adapter_name,
902 session.ns_scsi.sd_sid, session.ns_scsi.sd_lun);
904 if (session.ns_tape.td_fd != -1) {
905 NDMP_LOG(LOG_DEBUG, "tape.fd: %d", session.ns_tape.td_fd);
906 (void) close(session.ns_tape.td_fd);
907 (void) ndmp_open_list_del(session.ns_tape.td_adapter_name,
908 session.ns_tape.td_sid, session.ns_tape.td_lun);
910 ndmpd_mover_shut_down(&session);
911 ndmp_lbr_cleanup(&session);
912 ndmpd_data_cleanup(&session);
913 ndmpd_file_history_cleanup(&session, FALSE);
914 ndmpd_mover_cleanup(&session);
916 (void) ndmp_connect_list_del(connection);
921 * connection_file_handler
923 * ndmp_connection_t file handler function.
924 * Called by ndmpd_select when data is available to be read on the
925 * NDMP connection.
927 * Parameters:
928 * cookie (input) - session pointer.
929 * fd (input) - connection file descriptor.
930 * mode (input) - select mode.
932 * Returns:
933 * void.
935 /*ARGSUSED*/
936 static void
937 connection_file_handler(void *cookie, int fd, ulong_t mode)
939 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
941 if (ndmp_process_requests(session->ns_connection) < 0)
942 session->ns_eof = TRUE;
946 /* ************* private functions *************************************** */
949 * ndmp_readit
951 * Low level read routine called by the xdrrec library.
953 * Parameters:
954 * connection (input) - connection pointer.
955 * buf (input) - location to store received data.
956 * len (input) - max number of bytes to read.
958 * Returns:
959 * >0 - number of bytes received.
960 * -1 - error.
962 static int
963 ndmp_readit(void *connection_handle, caddr_t buf, int len)
965 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
967 len = read(connection->conn_sock, buf, len);
968 if (len <= 0) {
969 /* ndmp_connection_t has been closed. */
970 connection->conn_eof = TRUE;
971 return (-1);
973 return (len);
977 * ndmp_writeit
979 * Low level write routine called by the xdrrec library.
981 * Parameters:
982 * connection (input) - connection pointer.
983 * buf (input) - location to store received data.
984 * len (input) - max number of bytes to read.
986 * Returns:
987 * >0 - number of bytes sent.
988 * -1 - error.
990 static int
991 ndmp_writeit(void *connection_handle, caddr_t buf, int len)
993 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
994 register int n;
995 register int cnt;
997 for (cnt = len; cnt > 0; cnt -= n, buf += n) {
998 if ((n = write(connection->conn_sock, buf, cnt)) < 0) {
999 connection->conn_eof = TRUE;
1000 return (-1);
1004 return (len);
1009 * ndmp_recv_msg
1011 * Read the next message.
1013 * Parameters:
1014 * connection (input) - connection pointer.
1015 * msg (output) - received message.
1017 * Returns:
1018 * 0 - Message successfully received.
1019 * error number - Message related error.
1020 * -1 - Error decoding the message header.
1022 static int
1023 ndmp_recv_msg(ndmp_connection_t *connection)
1025 bool_t(*xdr_func) (XDR *, ...) = NULL;
1027 /* Decode the header. */
1028 connection->conn_xdrs.x_op = XDR_DECODE;
1029 (void) xdrrec_skiprecord(&connection->conn_xdrs);
1030 if (!xdr_ndmp_header(&connection->conn_xdrs,
1031 &connection->conn_msginfo.mi_hdr))
1032 return (-1);
1034 /* Lookup info necessary for processing this message. */
1035 if ((connection->conn_msginfo.mi_handler = ndmp_get_handler(connection,
1036 connection->conn_msginfo.mi_hdr.message)) == 0) {
1037 NDMP_LOG(LOG_DEBUG, "Message 0x%x not supported",
1038 connection->conn_msginfo.mi_hdr.message);
1039 return (NDMP_NOT_SUPPORTED_ERR);
1041 connection->conn_msginfo.mi_body = 0;
1043 if (connection->conn_msginfo.mi_hdr.error != NDMP_NO_ERR)
1044 return (0);
1046 /* Determine body type */
1047 if (connection->conn_msginfo.mi_hdr.message_type ==
1048 NDMP_MESSAGE_REQUEST) {
1049 if (ndmp_check_auth_required(
1050 connection->conn_msginfo.mi_hdr.message) &&
1051 !connection->conn_authorized) {
1052 NDMP_LOG(LOG_DEBUG,
1053 "Processing request 0x%x:connection not authorized",
1054 connection->conn_msginfo.mi_hdr.message);
1055 return (NDMP_NOT_AUTHORIZED_ERR);
1057 if (connection->conn_msginfo.mi_handler->mh_sizeof_request >
1058 0) {
1059 xdr_func =
1060 connection->conn_msginfo.mi_handler->mh_xdr_request;
1061 if (xdr_func == NULL) {
1062 NDMP_LOG(LOG_DEBUG,
1063 "Processing request 0x%x: no xdr function "
1064 "in handler table",
1065 connection->conn_msginfo.mi_hdr.message);
1066 return (NDMP_NOT_SUPPORTED_ERR);
1068 connection->conn_msginfo.mi_body = ndmp_malloc(
1069 connection->conn_msginfo.mi_handler->
1070 mh_sizeof_request);
1071 if (connection->conn_msginfo.mi_body == NULL)
1072 return (NDMP_NO_MEM_ERR);
1074 (void) memset(connection->conn_msginfo.mi_body, 0,
1075 connection->conn_msginfo.mi_handler->
1076 mh_sizeof_request);
1078 } else {
1079 if (connection->conn_msginfo.mi_handler->mh_sizeof_reply > 0) {
1080 xdr_func =
1081 connection->conn_msginfo.mi_handler->mh_xdr_reply;
1082 if (xdr_func == NULL) {
1083 NDMP_LOG(LOG_DEBUG,
1084 "Processing reply 0x%x: no xdr function "
1085 "in handler table",
1086 connection->conn_msginfo.mi_hdr.message);
1087 return (NDMP_NOT_SUPPORTED_ERR);
1089 connection->conn_msginfo.mi_body = ndmp_malloc(
1090 connection->conn_msginfo.mi_handler->
1091 mh_sizeof_reply);
1092 if (connection->conn_msginfo.mi_body == NULL)
1093 return (NDMP_NO_MEM_ERR);
1095 (void) memset(connection->conn_msginfo.mi_body, 0,
1096 connection->conn_msginfo.mi_handler->
1097 mh_sizeof_reply);
1101 /* Decode message arguments if needed */
1102 if (xdr_func) {
1103 if (!(*xdr_func)(&connection->conn_xdrs,
1104 connection->conn_msginfo.mi_body)) {
1105 NDMP_LOG(LOG_DEBUG,
1106 "Processing message 0x%x: error decoding arguments",
1107 connection->conn_msginfo.mi_hdr.message);
1108 free(connection->conn_msginfo.mi_body);
1109 connection->conn_msginfo.mi_body = 0;
1110 return (NDMP_XDR_DECODE_ERR);
1113 return (0);
1117 * ndmp_process_messages
1119 * Reads the next message into the stream buffer.
1120 * Processes messages until the stream buffer is empty.
1122 * This function processes all data in the stream buffer before returning.
1123 * This allows functions like poll() to be used to determine when new
1124 * messages have arrived. If only some of the messages in the stream buffer
1125 * were processed and then poll was called, poll() could block waiting for
1126 * a message that had already been received and read into the stream buffer.
1128 * This function processes both request and reply messages.
1129 * Request messages are dispatched using the appropriate function from the
1130 * message handling table.
1131 * Only one reply messages may be pending receipt at a time.
1132 * A reply message, if received, is placed in connection->conn_msginfo
1133 * before returning to the caller.
1134 * Errors are reported if a reply is received but not expected or if
1135 * more than one reply message is received
1137 * Parameters:
1138 * connection (input) - connection pointer.
1139 * reply_expected (output) - TRUE - a reply message is expected.
1140 * FALSE - no reply message is expected and
1141 * an error will be reported if a reply
1142 * is received.
1144 * Returns:
1145 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed,
1146 * error processing reply message.
1147 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed,
1148 * reply seen.
1149 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed,
1150 * no reply seen.
1151 * NDMP_PROC_REP_ERR - error; connection no longer established.
1153 * Notes:
1154 * If the peer is generating a large number of requests, a caller
1155 * looking for a reply will be blocked while the requests are handled.
1156 * This is because this function does not return until the stream
1157 * buffer is empty.
1158 * Code needs to be added to allow a return if the stream buffer
1159 * is not empty but there is data available on the socket. This will
1160 * prevent poll() from blocking and prevent a caller looking for a reply
1161 * from getting blocked by a bunch of requests.
1163 static int
1164 ndmp_process_messages(ndmp_connection_t *connection, boolean_t reply_expected)
1166 msg_info_t reply_msginfo;
1167 boolean_t reply_read = FALSE;
1168 boolean_t reply_error = FALSE;
1169 int err;
1171 NDMP_LOG(LOG_DEBUG, "reply_expected: %s",
1172 reply_expected == TRUE ? "TRUE" : "FALSE");
1174 (void) memset((void *)&reply_msginfo, 0, sizeof (msg_info_t));
1176 do {
1177 (void) memset((void *)&connection->conn_msginfo, 0,
1178 sizeof (msg_info_t));
1180 if ((err = ndmp_recv_msg(connection)) != NDMP_NO_ERR) {
1181 if (connection->conn_eof) {
1182 NDMP_LOG(LOG_DEBUG, "detected eof");
1183 return (NDMP_PROC_ERR);
1185 if (err < 1) {
1186 NDMP_LOG(LOG_DEBUG, "error decoding header");
1189 * Error occurred decoding the header.
1190 * Don't send a reply since we don't know
1191 * the message or if the message was even
1192 * a request message. To be safe, assume
1193 * that the message was a reply if a reply
1194 * was expected. Need to do this to prevent
1195 * hanging ndmp_send_request() waiting for a
1196 * reply. Don't set reply_read so that the
1197 * reply will be processed if it is received
1198 * later.
1200 if (reply_read == FALSE)
1201 reply_error = TRUE;
1203 continue;
1205 if (connection->conn_msginfo.mi_hdr.message_type
1206 != NDMP_MESSAGE_REQUEST) {
1207 NDMP_LOG(LOG_DEBUG, "received reply: 0x%x",
1208 connection->conn_msginfo.mi_hdr.message);
1210 if (reply_expected == FALSE ||
1211 reply_read == TRUE)
1212 NDMP_LOG(LOG_DEBUG,
1213 "Unexpected reply message: 0x%x",
1214 connection->conn_msginfo.mi_hdr.
1215 message);
1217 ndmp_free_message((ndmp_connection_t *)
1218 connection);
1220 if (reply_read == FALSE) {
1221 reply_read = TRUE;
1222 reply_error = TRUE;
1224 continue;
1226 NDMP_LOG(LOG_DEBUG, "received request: 0x%x",
1227 connection->conn_msginfo.mi_hdr.message);
1229 (void) ndmp_send_response((ndmp_connection_t *)
1230 connection, err, NULL);
1231 ndmp_free_message((ndmp_connection_t *)connection);
1232 continue;
1234 if (connection->conn_msginfo.mi_hdr.message_type
1235 != NDMP_MESSAGE_REQUEST) {
1236 NDMP_LOG(LOG_DEBUG, "received reply: 0x%x",
1237 connection->conn_msginfo.mi_hdr.message);
1239 if (reply_expected == FALSE || reply_read == TRUE) {
1240 NDMP_LOG(LOG_DEBUG,
1241 "Unexpected reply message: 0x%x",
1242 connection->conn_msginfo.mi_hdr.message);
1243 ndmp_free_message((ndmp_connection_t *)
1244 connection);
1245 continue;
1247 reply_read = TRUE;
1248 reply_msginfo = connection->conn_msginfo;
1249 continue;
1251 NDMP_LOG(LOG_DEBUG, "received request: 0x%x",
1252 connection->conn_msginfo.mi_hdr.message);
1255 * The following is needed to catch an improperly constructed
1256 * handler table or to deal with an NDMP client that is not
1257 * conforming to the negotiated protocol version.
1259 if (connection->conn_msginfo.mi_handler->mh_func == NULL) {
1260 NDMP_LOG(LOG_DEBUG, "No handler for message 0x%x",
1261 connection->conn_msginfo.mi_hdr.message);
1263 (void) ndmp_send_response((ndmp_connection_t *)
1264 connection, NDMP_NOT_SUPPORTED_ERR, NULL);
1265 ndmp_free_message((ndmp_connection_t *)connection);
1266 continue;
1269 * Call the handler function.
1270 * The handler will send any necessary reply.
1272 (*connection->conn_msginfo.mi_handler->mh_func) (connection,
1273 connection->conn_msginfo.mi_body);
1275 ndmp_free_message((ndmp_connection_t *)connection);
1277 } while (xdrrec_eof(&connection->conn_xdrs) == FALSE &&
1278 connection->conn_eof == FALSE);
1280 NDMP_LOG(LOG_DEBUG, "no more messages in stream buffer");
1282 if (connection->conn_eof == TRUE) {
1283 if (reply_msginfo.mi_body)
1284 free(reply_msginfo.mi_body);
1285 return (NDMP_PROC_ERR);
1287 if (reply_error) {
1288 if (reply_msginfo.mi_body)
1289 free(reply_msginfo.mi_body);
1290 return (NDMP_PROC_REP_ERR);
1292 if (reply_read) {
1293 connection->conn_msginfo = reply_msginfo;
1294 return (NDMP_PROC_MSG);
1296 return (NDMP_PROC_REP);
1301 * ndmp_get_interface
1303 * Return the NDMP interface (e.g. config, scsi, tape) for the
1304 * specific message.
1306 * Parameters:
1307 * message (input) - message number.
1309 * Returns:
1310 * NULL - message not found.
1311 * pointer to handler info.
1313 static ndmp_handler_t *
1314 ndmp_get_interface(ndmp_message message)
1316 ndmp_handler_t *ni = &ndmp_msghdl_tab[(message >> 8) % INT_MAXCMD];
1318 if ((message & 0xff) >= ni->hd_cnt)
1319 return (NULL);
1321 /* Sanity check */
1322 if (ni->hd_msgs[message & 0xff].hm_message != message)
1323 return (NULL);
1325 return (ni);
1329 * ndmp_get_handler
1331 * Return the handler info for the specified NDMP message.
1333 * Parameters:
1334 * connection (input) - connection pointer.
1335 * message (input) - message number.
1337 * Returns:
1338 * NULL - message not found.
1339 * pointer to handler info.
1341 static ndmp_msg_handler_t *
1342 ndmp_get_handler(ndmp_connection_t *connection, ndmp_message message)
1344 ndmp_msg_handler_t *handler = NULL;
1346 ndmp_handler_t *ni = ndmp_get_interface(message);
1347 int ver = connection->conn_version;
1349 if (ni)
1350 handler = &ni->hd_msgs[message & 0xff].hm_msg_v[ver - 2];
1352 return (handler);
1356 * ndmp_check_auth_required
1358 * Check if the connection needs to be authenticated before
1359 * this message is being processed.
1361 * Parameters:
1362 * message (input) - message number.
1364 * Returns:
1365 * TRUE - required
1366 * FALSE - not required
1368 static boolean_t
1369 ndmp_check_auth_required(ndmp_message message)
1371 boolean_t auth_req = FALSE;
1372 ndmp_handler_t *ni = ndmp_get_interface(message);
1374 if (ni)
1375 auth_req = ni->hd_msgs[message & 0xff].hm_auth_required;
1377 return (auth_req);
1381 * tcp_accept
1383 * A wrapper around accept for retrying and getting the IP address
1385 * Parameters:
1386 * listen_sock (input) - the socket for listening
1387 * inaddr_p (output) - the IP address of peer connection
1389 * Returns:
1390 * socket for the accepted connection
1391 * -1: error
1394 tcp_accept(int listen_sock, unsigned int *inaddr_p)
1396 struct sockaddr_in sin;
1397 int sock, i;
1398 int try;
1400 for (try = 0; try < 3; try++) {
1401 i = sizeof (sin);
1402 sock = accept(listen_sock, (struct sockaddr *)&sin, &i);
1403 if (sock < 0) {
1404 continue;
1406 *inaddr_p = sin.sin_addr.s_addr;
1407 return (sock);
1409 return (-1);
1414 * tcp_get_peer
1416 * Get the peer IP address for a connection
1418 * Parameters:
1419 * sock (input) - the active socket
1420 * inaddr_p (output) - the IP address of peer connection
1421 * port_p (output) - the port number of peer connection
1423 * Returns:
1424 * socket for the accepted connection
1425 * -1: error
1428 tcp_get_peer(int sock, unsigned int *inaddr_p, int *port_p)
1430 struct sockaddr_in sin;
1431 int i, rc;
1433 i = sizeof (sin);
1434 rc = getpeername(sock, (struct sockaddr *)&sin, &i);
1435 if (rc != 0)
1436 return (-1);
1438 if (inaddr_p)
1439 *inaddr_p = sin.sin_addr.s_addr;
1441 if (port_p)
1442 *port_p = ntohs(sin.sin_port);
1444 return (sock);
1449 * gethostaddr
1451 * Get the IP address string of the current host
1453 * Parameters:
1454 * void
1456 * Returns:
1457 * IP address
1458 * NULL: error
1460 char *
1461 gethostaddr(void)
1463 static char s[MAXHOSTNAMELEN];
1464 struct hostent *h;
1465 struct in_addr in;
1466 char *p;
1468 if (gethostname(s, sizeof (s)) == -1)
1469 return (NULL);
1471 if ((h = gethostbyname(s)) == NULL)
1472 return (NULL);
1474 p = h->h_addr_list[0];
1475 (void) memcpy(&in.s_addr, p, sizeof (in.s_addr));
1476 return (inet_ntoa(in));
1481 * get_default_nic_addr
1483 * Get the IP address of the default NIC
1485 char *
1486 get_default_nic_addr(void)
1488 struct ifaddrlist *al = NULL;
1489 char errmsg[ERRBUFSIZE];
1490 struct in_addr addr;
1491 int nifs;
1493 nifs = ifaddrlist(&al, AF_INET, LIFC_EXTERNAL_SOURCE, errmsg);
1494 if (nifs <= 0)
1495 return (NULL);
1497 /* pick the first interface's address */
1498 addr = al[0].addr.addr;
1499 free(al);
1501 return (inet_ntoa(IN_ADDR(addr.s_addr)));
1506 * ndmpd_audit_backup
1508 * Generate AUE_ndmp_backup audit record
1510 /*ARGSUSED*/
1511 void
1512 ndmpd_audit_backup(ndmp_connection_t *conn,
1513 char *path, int dest, char *local_path, int result)
1515 adt_event_data_t *event;
1517 if ((event = adt_alloc_event(conn->conn_ah, ADT_ndmp_backup)) == NULL) {
1518 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1519 return;
1521 event->adt_ndmp_backup.source = path;
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;
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.");
1537 adt_free_event(event);
1542 * ndmpd_audit_restore
1544 * Generate AUE_ndmp_restore audit record
1546 /*ARGSUSED*/
1547 void
1548 ndmpd_audit_restore(ndmp_connection_t *conn,
1549 char *path, int dest, char *local_path, int result)
1551 adt_event_data_t *event;
1553 if ((event = adt_alloc_event(conn->conn_ah,
1554 ADT_ndmp_restore)) == NULL) {
1555 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1556 return;
1558 event->adt_ndmp_restore.destination = path;
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;
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.");
1574 adt_free_event(event);
1579 * ndmpd_audit_connect
1581 * Generate AUE_ndmp_connect audit record
1583 /*ARGSUSED*/
1584 void
1585 ndmpd_audit_connect(ndmp_connection_t *conn, int result)
1587 adt_event_data_t *event;
1588 adt_termid_t *termid;
1590 if (adt_load_termid(conn->conn_sock, &termid) != 0) {
1591 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1592 return;
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;
1601 free(termid);
1603 if ((event = adt_alloc_event(conn->conn_ah,
1604 ADT_ndmp_connect)) == NULL) {
1605 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1606 return;
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.");
1617 adt_free_event(event);
1622 * ndmpd_audit_disconnect
1624 * Generate AUE_ndmp_disconnect audit record
1626 /*ARGSUSED*/
1627 void
1628 ndmpd_audit_disconnect(ndmp_connection_t *conn)
1630 adt_event_data_t *event;
1632 if ((event = adt_alloc_event(conn->conn_ah,
1633 ADT_ndmp_disconnect)) == NULL) {
1634 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1635 return;
1637 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0)
1638 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1640 adt_free_event(event);
1643 void *
1644 ndmp_malloc(size_t size)
1646 void *data;
1648 if ((data = calloc(1, size)) == NULL) {
1649 NDMP_LOG(LOG_ERR, "Out of memory.");
1652 return (data);
1656 * get_backup_path_v3
1658 * Get the backup path from the NDMP environment variables.
1660 * Parameters:
1661 * params (input) - pointer to the parameters structure.
1663 * Returns:
1664 * The backup path: if anything is specified
1665 * NULL: Otherwise
1667 char *
1668 get_backup_path_v3(ndmpd_module_params_t *params)
1670 char *bkpath;
1672 bkpath = MOD_GETENV(params, "PREFIX");
1673 if (!bkpath)
1674 bkpath = MOD_GETENV(params, "FILESYSTEM");
1677 if (!bkpath) {
1678 MOD_LOGV3(params, NDMP_LOG_ERROR,
1679 "Backup path not defined.\n");
1680 } else {
1681 NDMP_LOG(LOG_DEBUG, "bkpath: \"%s\"", bkpath);
1684 return (bkpath);
1688 * get_backup_path
1690 * Find the backup path from the environment variables (v2)
1692 char *
1693 get_backup_path_v2(ndmpd_module_params_t *params)
1695 char *bkpath;
1697 bkpath = MOD_GETENV(params, "PREFIX");
1698 if (bkpath == NULL)
1699 bkpath = MOD_GETENV(params, "FILESYSTEM");
1701 if (bkpath == NULL) {
1702 MOD_LOG(params, "Error: restore path not specified.\n");
1703 return (NULL);
1706 if (*bkpath != '/') {
1707 MOD_LOG(params, "Error: relative backup path not allowed.\n");
1708 return (NULL);
1711 return (bkpath);