Merge commit '00f1a4f432b3d8aad1aa270e91c44c57f03ef407'
[unleashed.git] / usr / src / cmd / ndmpd / ndmp / ndmpd_comm.c
blob958b7a10a7eed9950f117f9729d5ef8003fe8905
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);
110 * ndmp_create_connection
112 * Allocate and initialize a connection structure.
114 * Parameters:
115 * handler_tbl (input) - message handlers.
117 * Returns:
118 * NULL - error
119 * connection pointer
121 * Notes:
122 * The returned connection should be destroyed using
123 * ndmp_destroy_connection().
125 ndmp_connection_t *
126 ndmp_create_connection(void)
128 ndmp_connection_t *connection;
130 connection = ndmp_malloc(sizeof (ndmp_connection_t));
131 if (connection == NULL)
132 return (NULL);
134 connection->conn_sock = -1;
135 connection->conn_my_sequence = 0;
136 connection->conn_authorized = FALSE;
137 connection->conn_eof = FALSE;
138 connection->conn_msginfo.mi_body = 0;
139 connection->conn_version = ndmp_ver;
140 connection->conn_client_data = 0;
141 (void) mutex_init(&connection->conn_lock, 0, NULL);
142 connection->conn_xdrs.x_ops = 0;
144 xdrrec_create(&connection->conn_xdrs, 0, 0, (caddr_t)connection,
145 ndmp_readit, ndmp_writeit);
147 if (connection->conn_xdrs.x_ops == 0) {
148 NDMP_LOG(LOG_DEBUG, "xdrrec_create failed");
149 (void) mutex_destroy(&connection->conn_lock);
150 (void) close(connection->conn_sock);
151 free(connection);
152 return (0);
154 return ((ndmp_connection_t *)connection);
158 * ndmp_destroy_connection
160 * Shutdown a connection and release allocated resources.
162 * Parameters:
163 * connection_handle (Input) - connection handle.
165 * Returns:
166 * void
168 void
169 ndmp_destroy_connection(ndmp_connection_t *connection_handle)
171 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
173 if (connection->conn_sock >= 0) {
174 (void) mutex_destroy(&connection->conn_lock);
175 (void) close(connection->conn_sock);
176 connection->conn_sock = -1;
178 xdr_destroy(&connection->conn_xdrs);
179 free(connection);
184 * ndmp_close
186 * Close a connection.
188 * Parameters:
189 * connection_handle (Input) - connection handle.
191 * Returns:
192 * void
194 void
195 ndmp_close(ndmp_connection_t *connection_handle)
197 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
199 ndmpd_audit_disconnect(connection);
200 if (connection->conn_sock >= 0) {
201 (void) mutex_destroy(&connection->conn_lock);
202 (void) close(connection->conn_sock);
203 connection->conn_sock = -1;
205 connection->conn_eof = TRUE;
208 * We should close all the tapes that are used by this connection.
209 * In some cases the ndmp client opens a tape, but does not close the
210 * tape and closes the connection.
212 ndmp_open_list_release(connection_handle);
216 * ndmp_start_worker
218 * Initializes and starts a ndmp_worker thread
221 ndmp_start_worker(ndmpd_worker_arg_t *argp)
223 pthread_attr_t tattr;
224 int rc;
226 (void) pthread_attr_init(&tattr);
227 (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
228 rc = pthread_create(NULL, &tattr, ndmpd_worker, (void *)argp);
229 (void) pthread_attr_destroy(&tattr);
230 return (rc);
234 * ndmp_run
236 * Creates a socket for listening and accepting connections
237 * from NDMP clients.
238 * Accepts connections and passes each connection to the connection
239 * handler.
241 * Parameters:
242 * port (input) - NDMP server port.
243 * If 0, the port number will be retrieved from
244 * the network service database. If not found there,
245 * the default NDMP port number (from ndmp.x)
246 * will be used.
247 * handler (input) - connection handler function.
249 * Returns:
250 * This function normally never returns unless there's error.
251 * -1 : error
253 * Notes:
254 * This function does not return unless encountering an error
255 * related to the listen socket.
258 ndmp_run(ulong_t port, ndmp_con_handler_func_t con_handler_func)
260 int ns;
261 int on;
262 int server_socket;
263 unsigned int ipaddr;
264 struct sockaddr_in sin;
265 ndmpd_worker_arg_t *argp;
267 sin.sin_family = AF_INET;
268 sin.sin_addr.s_addr = INADDR_ANY;
269 sin.sin_port = htons(port);
271 if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
272 NDMP_LOG(LOG_DEBUG, "Socket error: %m");
273 return (-1);
276 on = 1;
277 (void) setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR,
278 (char *)&on, sizeof (on));
281 if (bind(server_socket, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
282 NDMP_LOG(LOG_DEBUG, "bind error: %m");
283 (void) close(server_socket);
284 return (-1);
286 if (listen(server_socket, 5) < 0) {
287 NDMP_LOG(LOG_DEBUG, "listen error: %m");
288 (void) close(server_socket);
289 return (-1);
292 for (; ; ) {
293 if ((ns = tcp_accept(server_socket, &ipaddr)) < 0) {
294 NDMP_LOG(LOG_DEBUG, "tcp_accept error: %m");
295 continue;
297 NDMP_LOG(LOG_DEBUG, "connection fd: %d", ns);
298 set_socket_options(ns);
300 if ((argp = ndmp_malloc(sizeof (ndmpd_worker_arg_t))) != NULL) {
301 argp->nw_sock = ns;
302 argp->nw_ipaddr = ipaddr;
303 argp->nw_con_handler_func = con_handler_func;
304 (void) ndmp_start_worker(argp);
310 * ndmpd_worker thread
312 * Parameters:
313 * argp (input) - structure containing socket and handler function
315 * Returns:
316 * 0 - successful connection.
317 * -1 - error.
319 void *
320 ndmpd_worker(void *ptarg)
322 int sock;
323 ndmp_connection_t *connection;
324 ndmpd_worker_arg_t *argp = (ndmpd_worker_arg_t *)ptarg;
326 if (!argp)
327 return ((void *)-1);
329 NS_INC(trun);
330 sock = argp->nw_sock;
332 if ((connection = ndmp_create_connection()) == NULL) {
333 (void) close(sock);
334 free(argp);
335 exit(1);
338 /* initialize auditing session */
339 if (adt_start_session(&connection->conn_ah, NULL, 0) != 0) {
340 free(argp);
341 return ((void *)-1);
344 ((ndmp_connection_t *)connection)->conn_sock = sock;
345 (*argp->nw_con_handler_func)(connection);
346 (void) adt_end_session(connection->conn_ah);
347 ndmp_destroy_connection(connection);
348 NS_DEC(trun);
350 free(argp);
351 return (NULL);
355 * ndmp_process_requests
357 * Reads the next request message into the stream buffer.
358 * Processes messages until the stream buffer is empty.
360 * Parameters:
361 * connection_handle (input) - connection handle.
363 * Returns:
364 * 0 - 1 or more messages successfully processed.
365 * -1 - error; connection no longer established.
368 ndmp_process_requests(ndmp_connection_t *connection_handle)
370 int rv;
371 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
373 (void) mutex_lock(&connection->conn_lock);
374 rv = 0;
375 if (ndmp_process_messages(connection, FALSE) < 0)
376 rv = -1;
378 (void) mutex_unlock(&connection->conn_lock);
379 return (rv);
384 * ndmp_send_request
386 * Send an NDMP request message.
388 * Parameters:
389 * connection_handle (input) - connection pointer.
390 * message (input) - message number.
391 * err (input) - error code to place in header.
392 * request_data (input) - message body.
393 * reply (output) - reply message. If 0, reply will be
394 * discarded.
396 * Returns:
397 * 0 - successful send.
398 * -1 - error.
399 * otherwise - error from reply header.
401 * Notes:
402 * - The reply body is only returned if the error code is NDMP_NO_ERR.
405 ndmp_send_request(ndmp_connection_t *connection_handle, ndmp_message message,
406 ndmp_error err, void *request_data, void **reply)
408 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
409 ndmp_header header;
410 ndmp_msg_handler_t *handler;
411 int r;
412 struct timeval time;
414 /* Lookup info necessary for processing this request. */
415 if (!(handler = ndmp_get_handler(connection, message))) {
416 NDMP_LOG(LOG_DEBUG, "Sending message 0x%x: not supported",
417 message);
418 return (-1);
420 (void) gettimeofday(&time, 0);
422 header.sequence = ++(connection->conn_my_sequence);
423 header.time_stamp = time.tv_sec;
424 header.message_type = NDMP_MESSAGE_REQUEST;
425 header.message = message;
426 header.reply_sequence = 0;
427 header.error = err;
429 connection->conn_xdrs.x_op = XDR_ENCODE;
430 if (!xdr_ndmp_header(&connection->conn_xdrs, &header)) {
431 NDMP_LOG(LOG_DEBUG,
432 "Sending message 0x%x: encoding request header", message);
433 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
434 return (-1);
436 if (err == NDMP_NO_ERR && handler->mh_xdr_request && request_data) {
437 if (!(*handler->mh_xdr_request)(&connection->conn_xdrs,
438 request_data)) {
439 NDMP_LOG(LOG_DEBUG,
440 "Sending message 0x%x: encoding request body",
441 message);
442 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
443 return (-1);
446 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
448 if (handler->mh_xdr_reply == 0) {
449 NDMP_LOG(LOG_DEBUG, "handler->mh_xdr_reply == 0");
450 return (0);
454 * Process messages until the reply to this request has been
455 * processed.
457 for (; ; ) {
458 r = ndmp_process_messages(connection, TRUE);
460 /* connection error? */
461 if (r < 0)
462 return (-1);
464 /* no reply received? */
465 if (r == 0)
466 continue;
468 /* reply received? */
469 if (r == 1) {
470 if (message !=
471 connection->conn_msginfo.mi_hdr.message) {
472 NDMP_LOG(LOG_DEBUG,
473 "Received unexpected reply 0x%x",
474 connection->conn_msginfo.mi_hdr.message);
475 ndmp_free_message(connection_handle);
476 return (-1);
478 if (reply != NULL)
479 *reply = connection->conn_msginfo.mi_body;
480 else
481 ndmp_free_message(connection_handle);
483 return (connection->conn_msginfo.mi_hdr.error);
485 /* error handling reply */
487 return (-1);
493 * ndmp_send_request_lock
495 * A wrapper for ndmp_send_request with locks.
497 * Parameters:
498 * connection_handle (input) - connection pointer.
499 * message (input) - message number.
500 * err (input) - error code to place in header.
501 * request_data (input) - message body.
502 * reply (output) - reply message. If 0, reply will be
503 * discarded.
505 * Returns:
506 * 0 - successful send.
507 * -1 - error.
508 * otherwise - error from reply header.
510 * Notes:
511 * - The reply body is only returned if the error code is NDMP_NO_ERR.
514 ndmp_send_request_lock(ndmp_connection_t *connection_handle,
515 ndmp_message message, ndmp_error err, void *request_data, void **reply)
517 int rv;
518 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
520 (void) mutex_lock(&connection->conn_lock);
522 rv = ndmp_send_request(connection_handle, message, err, request_data,
523 reply);
524 (void) mutex_unlock(&connection->conn_lock);
525 return (rv);
530 * ndmp_send_response
532 * Send an NDMP reply message.
534 * Parameters:
535 * connection_handle (input) - connection pointer.
536 * err (input) - error code to place in header.
537 * reply (input) - reply message body.
539 * Returns:
540 * 0 - successful send.
541 * -1 - error.
543 * Notes:
544 * - The body is only sent if the error code is NDMP_NO_ERR.
547 ndmp_send_response(ndmp_connection_t *connection_handle, ndmp_error err,
548 void *reply)
550 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
551 ndmp_header header;
552 struct timeval time;
554 (void) gettimeofday(&time, 0);
556 header.sequence = ++(connection->conn_my_sequence);
557 header.time_stamp = time.tv_sec;
558 header.message_type = NDMP_MESSAGE_REPLY;
559 header.message = connection->conn_msginfo.mi_hdr.message;
560 header.reply_sequence = connection->conn_msginfo.mi_hdr.sequence;
561 header.error = err;
563 connection->conn_xdrs.x_op = XDR_ENCODE;
564 if (!xdr_ndmp_header(&connection->conn_xdrs, &header)) {
565 NDMP_LOG(LOG_DEBUG, "Sending message 0x%x: "
566 "encoding reply header",
567 header.message);
568 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
569 return (-1);
571 if (err == NDMP_NO_ERR &&
572 connection->conn_msginfo.mi_handler->mh_xdr_reply &&
573 reply) {
574 if (!(*connection->conn_msginfo.mi_handler->mh_xdr_reply)(
575 &connection->conn_xdrs, reply)) {
576 NDMP_LOG(LOG_DEBUG,
577 "Sending message 0x%x: encoding reply body",
578 header.message);
579 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
580 return (-1);
583 (void) xdrrec_endofrecord(&connection->conn_xdrs, 1);
584 return (0);
588 * ndmp_free_message
590 * Free the memory of NDMP message body.
592 * Parameters:
593 * connection_handle (input) - connection pointer.
595 * Returns:
596 * void
599 void
600 ndmp_free_message(ndmp_connection_t *connection_handle)
602 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
604 if (connection->conn_msginfo.mi_handler == NULL ||
605 connection->conn_msginfo.mi_body == NULL)
606 return;
608 connection->conn_xdrs.x_op = XDR_FREE;
609 if (connection->conn_msginfo.mi_hdr.message_type ==
610 NDMP_MESSAGE_REQUEST) {
611 if (connection->conn_msginfo.mi_handler->mh_xdr_request)
612 (*connection->conn_msginfo.mi_handler->mh_xdr_request)(
613 &connection->conn_xdrs,
614 connection->conn_msginfo.mi_body);
615 } else {
616 if (connection->conn_msginfo.mi_handler->mh_xdr_reply)
617 (*connection->conn_msginfo.mi_handler->mh_xdr_reply)(
618 &connection->conn_xdrs,
619 connection->conn_msginfo.mi_body);
622 (void) free(connection->conn_msginfo.mi_body);
623 connection->conn_msginfo.mi_body = 0;
627 * ndmp_get_fd
629 * Returns the connection file descriptor.
631 * Parameters:
632 * connection_handle (input) - connection handle
634 * Returns:
635 * >=0 - file descriptor.
636 * -1 - connection not open.
639 ndmp_get_fd(ndmp_connection_t *connection_handle)
641 return (((ndmp_connection_t *)connection_handle)->conn_sock);
646 * ndmp_set_client_data
648 * This function provides a means for the library client to provide
649 * a pointer to some user data structure that is retrievable by
650 * each message handler via ndmp_get_client_data.
652 * Parameters:
653 * connection_handle (input) - connection handle.
654 * client_data (input) - user data pointer.
656 * Returns:
657 * void
659 void
660 ndmp_set_client_data(ndmp_connection_t *connection_handle, void *client_data)
662 ((ndmp_connection_t *)connection_handle)->conn_client_data =
663 client_data;
668 * ndmp_get_client_data
670 * This function provides a means for the library client to provide
671 * a pointer to some user data structure that is retrievable by
672 * each message handler via ndmp_get_client_data.
674 * Parameters:
675 * connection_handle (input) - connection handle.
677 * Returns:
678 * client data pointer.
680 void *
681 ndmp_get_client_data(ndmp_connection_t *connection_handle)
683 return (((ndmp_connection_t *)connection_handle)->conn_client_data);
688 * ndmp_set_version
690 * Sets the NDMP protocol version to be used on the connection.
692 * Parameters:
693 * connection_handle (input) - connection handle.
694 * version (input) - protocol version.
696 * Returns:
697 * void
699 void
700 ndmp_set_version(ndmp_connection_t *connection_handle, ushort_t version)
702 ((ndmp_connection_t *)connection_handle)->conn_version = version;
707 * ndmp_get_version
709 * Gets the NDMP protocol version in use on the connection.
711 * Parameters:
712 * connection_handle (input) - connection handle.
713 * version (input) - protocol version.
715 * Returns:
716 * void
718 ushort_t
719 ndmp_get_version(ndmp_connection_t *connection_handle)
721 return (((ndmp_connection_t *)connection_handle)->conn_version);
726 * ndmp_set_authorized
728 * Mark the connection as either having been authorized or not.
730 * Parameters:
731 * connection_handle (input) - connection handle.
732 * authorized (input) - TRUE or FALSE.
734 * Returns:
735 * void
737 void
738 ndmp_set_authorized(ndmp_connection_t *connection_handle, boolean_t authorized)
740 ((ndmp_connection_t *)connection_handle)->conn_authorized = authorized;
745 * ndmpd_main
747 * NDMP main function called from main().
749 * Parameters:
750 * void
752 * Returns:
753 * void
755 void
756 ndmpd_main(void)
758 char *propval;
760 ndmp_load_params();
763 * Find ndmp port number to be used. If ndmpd is run as command line
764 * and port number is supplied, use that port number. If port number is
765 * is not supplied, find out if ndmp port property is set. If ndmp
766 * port property is set, use that port number otherwise use the defaule
767 * port number.
769 if (ndmp_port == 0) {
770 if ((propval = ndmpd_get_prop(NDMP_TCP_PORT)) == NULL ||
771 *propval == 0)
772 ndmp_port = NDMPPORT;
773 else
774 ndmp_port = strtol(propval, 0, 0);
777 if (ndmp_run(ndmp_port, connection_handler) == -1)
778 perror("ndmp_run ERROR");
782 * connection_handler
784 * NDMP connection handler.
785 * Waits for, reads, and processes NDMP requests on a connection.
787 * Parameters:
788 * connection (input) - connection handle.
790 * Return:
791 * void
793 void
794 connection_handler(ndmp_connection_t *connection)
796 static int conn_id = 1;
797 ndmpd_session_t session;
798 ndmp_notify_connected_request req;
799 int connection_fd;
801 (void) memset(&session, 0, sizeof (session));
802 session.ns_connection = connection;
803 session.ns_eof = FALSE;
805 * The 'protocol_version' must be 1 at first, since the client talks
806 * to the server in version 1 then they can move to a higher
807 * protocol version.
809 session.ns_protocol_version = ndmp_ver;
811 session.ns_scsi.sd_is_open = -1;
812 session.ns_scsi.sd_devid = -1;
814 session.ns_scsi.sd_sid = 0;
815 session.ns_scsi.sd_lun = 0;
816 session.ns_scsi.sd_valid_target_set = 0;
817 (void) memset(session.ns_scsi.sd_adapter_name, 0,
818 sizeof (session.ns_scsi.sd_adapter_name));
820 session.ns_tape.td_fd = -1;
821 session.ns_tape.td_sid = 0;
822 session.ns_tape.td_lun = 0;
823 (void) memset(session.ns_tape.td_adapter_name, 0,
824 sizeof (session.ns_tape.td_adapter_name));
825 session.ns_tape.td_pos = 0;
826 session.ns_tape.td_record_count = 0;
827 session.ns_file_handler_list = 0;
829 (void) ndmpd_data_init(&session);
830 ndmpd_file_history_init(&session);
831 if (ndmpd_mover_init(&session) < 0)
832 return;
834 if (ndmp_lbr_init(&session) < 0)
835 return;
838 * Setup defaults here. The init functions can not set defaults
839 * since the init functions are called by the stop request handlers
840 * and client set variables need to persist across data operations.
842 session.ns_mover.md_record_size = MAX_RECORD_SIZE;
844 ndmp_set_client_data(connection, (void *)&session);
846 req.reason = NDMP_CONNECTED;
847 req.protocol_version = ndmp_ver;
848 req.text_reason = "";
850 if (ndmp_send_request_lock(connection, NDMP_NOTIFY_CONNECTION_STATUS,
851 NDMP_NO_ERR, (void *)&req, 0) < 0) {
852 NDMP_LOG(LOG_DEBUG, "Connection terminated");
853 return;
855 connection_fd = ndmp_get_fd(connection);
857 NDMP_LOG(LOG_DEBUG, "connection_fd: %d", connection_fd);
860 * Add the handler function for the connection to the DMA.
862 if (ndmpd_add_file_handler(&session, (void *)&session, connection_fd,
863 NDMPD_SELECT_MODE_READ, HC_CLIENT, connection_file_handler) != 0) {
864 NDMP_LOG(LOG_DEBUG, "Could not register session handler.");
865 return;
869 * Register the connection in the list of active connections.
871 if (ndmp_connect_list_add(connection, &conn_id) != 0) {
872 NDMP_LOG(LOG_ERR,
873 "Could not register the session to the server.");
874 (void) ndmpd_remove_file_handler(&session, connection_fd);
875 return;
878 session.hardlink_q = hardlink_q_init();
880 while (session.ns_eof == FALSE)
881 (void) ndmpd_select(&session, TRUE, HC_ALL);
883 hardlink_q_cleanup(session.hardlink_q);
885 NDMP_LOG(LOG_DEBUG, "Connection terminated");
887 (void) ndmpd_remove_file_handler(&session, connection_fd);
889 if (session.ns_scsi.sd_is_open != -1) {
890 NDMP_LOG(LOG_DEBUG, "scsi.is_open: %d",
891 session.ns_scsi.sd_is_open);
892 (void) ndmp_open_list_del(session.ns_scsi.sd_adapter_name,
893 session.ns_scsi.sd_sid, session.ns_scsi.sd_lun);
895 if (session.ns_tape.td_fd != -1) {
896 NDMP_LOG(LOG_DEBUG, "tape.fd: %d", session.ns_tape.td_fd);
897 (void) close(session.ns_tape.td_fd);
898 (void) ndmp_open_list_del(session.ns_tape.td_adapter_name,
899 session.ns_tape.td_sid, session.ns_tape.td_lun);
901 ndmpd_mover_shut_down(&session);
902 ndmp_lbr_cleanup(&session);
903 ndmpd_data_cleanup(&session);
904 ndmpd_file_history_cleanup(&session, FALSE);
905 ndmpd_mover_cleanup(&session);
907 (void) ndmp_connect_list_del(connection);
912 * connection_file_handler
914 * ndmp_connection_t file handler function.
915 * Called by ndmpd_select when data is available to be read on the
916 * NDMP connection.
918 * Parameters:
919 * cookie (input) - session pointer.
920 * fd (input) - connection file descriptor.
921 * mode (input) - select mode.
923 * Returns:
924 * void.
926 /*ARGSUSED*/
927 static void
928 connection_file_handler(void *cookie, int fd, ulong_t mode)
930 ndmpd_session_t *session = (ndmpd_session_t *)cookie;
932 if (ndmp_process_requests(session->ns_connection) < 0)
933 session->ns_eof = TRUE;
937 /* ************* private functions *************************************** */
940 * ndmp_readit
942 * Low level read routine called by the xdrrec library.
944 * Parameters:
945 * connection (input) - connection pointer.
946 * buf (input) - location to store received data.
947 * len (input) - max number of bytes to read.
949 * Returns:
950 * >0 - number of bytes received.
951 * -1 - error.
953 static int
954 ndmp_readit(void *connection_handle, caddr_t buf, int len)
956 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
958 len = read(connection->conn_sock, buf, len);
959 if (len <= 0) {
960 /* ndmp_connection_t has been closed. */
961 connection->conn_eof = TRUE;
962 return (-1);
964 return (len);
968 * ndmp_writeit
970 * Low level write routine called by the xdrrec library.
972 * Parameters:
973 * connection (input) - connection pointer.
974 * buf (input) - location to store received data.
975 * len (input) - max number of bytes to read.
977 * Returns:
978 * >0 - number of bytes sent.
979 * -1 - error.
981 static int
982 ndmp_writeit(void *connection_handle, caddr_t buf, int len)
984 ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle;
985 register int n;
986 register int cnt;
988 for (cnt = len; cnt > 0; cnt -= n, buf += n) {
989 if ((n = write(connection->conn_sock, buf, cnt)) < 0) {
990 connection->conn_eof = TRUE;
991 return (-1);
995 return (len);
1000 * ndmp_recv_msg
1002 * Read the next message.
1004 * Parameters:
1005 * connection (input) - connection pointer.
1006 * msg (output) - received message.
1008 * Returns:
1009 * 0 - Message successfully received.
1010 * error number - Message related error.
1011 * -1 - Error decoding the message header.
1013 static int
1014 ndmp_recv_msg(ndmp_connection_t *connection)
1016 bool_t(*xdr_func) (XDR *, ...) = NULL;
1018 /* Decode the header. */
1019 connection->conn_xdrs.x_op = XDR_DECODE;
1020 (void) xdrrec_skiprecord(&connection->conn_xdrs);
1021 if (!xdr_ndmp_header(&connection->conn_xdrs,
1022 &connection->conn_msginfo.mi_hdr))
1023 return (-1);
1025 /* Lookup info necessary for processing this message. */
1026 if ((connection->conn_msginfo.mi_handler = ndmp_get_handler(connection,
1027 connection->conn_msginfo.mi_hdr.message)) == 0) {
1028 NDMP_LOG(LOG_DEBUG, "Message 0x%x not supported",
1029 connection->conn_msginfo.mi_hdr.message);
1030 return (NDMP_NOT_SUPPORTED_ERR);
1032 connection->conn_msginfo.mi_body = 0;
1034 if (connection->conn_msginfo.mi_hdr.error != NDMP_NO_ERR)
1035 return (0);
1037 /* Determine body type */
1038 if (connection->conn_msginfo.mi_hdr.message_type ==
1039 NDMP_MESSAGE_REQUEST) {
1040 if (ndmp_check_auth_required(
1041 connection->conn_msginfo.mi_hdr.message) &&
1042 !connection->conn_authorized) {
1043 NDMP_LOG(LOG_DEBUG,
1044 "Processing request 0x%x:connection not authorized",
1045 connection->conn_msginfo.mi_hdr.message);
1046 return (NDMP_NOT_AUTHORIZED_ERR);
1048 if (connection->conn_msginfo.mi_handler->mh_sizeof_request >
1049 0) {
1050 xdr_func =
1051 connection->conn_msginfo.mi_handler->mh_xdr_request;
1052 if (xdr_func == NULL) {
1053 NDMP_LOG(LOG_DEBUG,
1054 "Processing request 0x%x: no xdr function "
1055 "in handler table",
1056 connection->conn_msginfo.mi_hdr.message);
1057 return (NDMP_NOT_SUPPORTED_ERR);
1059 connection->conn_msginfo.mi_body = ndmp_malloc(
1060 connection->conn_msginfo.mi_handler->
1061 mh_sizeof_request);
1062 if (connection->conn_msginfo.mi_body == NULL)
1063 return (NDMP_NO_MEM_ERR);
1065 (void) memset(connection->conn_msginfo.mi_body, 0,
1066 connection->conn_msginfo.mi_handler->
1067 mh_sizeof_request);
1069 } else {
1070 if (connection->conn_msginfo.mi_handler->mh_sizeof_reply > 0) {
1071 xdr_func =
1072 connection->conn_msginfo.mi_handler->mh_xdr_reply;
1073 if (xdr_func == NULL) {
1074 NDMP_LOG(LOG_DEBUG,
1075 "Processing reply 0x%x: no xdr function "
1076 "in handler table",
1077 connection->conn_msginfo.mi_hdr.message);
1078 return (NDMP_NOT_SUPPORTED_ERR);
1080 connection->conn_msginfo.mi_body = ndmp_malloc(
1081 connection->conn_msginfo.mi_handler->
1082 mh_sizeof_reply);
1083 if (connection->conn_msginfo.mi_body == NULL)
1084 return (NDMP_NO_MEM_ERR);
1086 (void) memset(connection->conn_msginfo.mi_body, 0,
1087 connection->conn_msginfo.mi_handler->
1088 mh_sizeof_reply);
1092 /* Decode message arguments if needed */
1093 if (xdr_func) {
1094 if (!(*xdr_func)(&connection->conn_xdrs,
1095 connection->conn_msginfo.mi_body)) {
1096 NDMP_LOG(LOG_DEBUG,
1097 "Processing message 0x%x: error decoding arguments",
1098 connection->conn_msginfo.mi_hdr.message);
1099 free(connection->conn_msginfo.mi_body);
1100 connection->conn_msginfo.mi_body = 0;
1101 return (NDMP_XDR_DECODE_ERR);
1104 return (0);
1108 * ndmp_process_messages
1110 * Reads the next message into the stream buffer.
1111 * Processes messages until the stream buffer is empty.
1113 * This function processes all data in the stream buffer before returning.
1114 * This allows functions like poll() to be used to determine when new
1115 * messages have arrived. If only some of the messages in the stream buffer
1116 * were processed and then poll was called, poll() could block waiting for
1117 * a message that had already been received and read into the stream buffer.
1119 * This function processes both request and reply messages.
1120 * Request messages are dispatched using the appropriate function from the
1121 * message handling table.
1122 * Only one reply messages may be pending receipt at a time.
1123 * A reply message, if received, is placed in connection->conn_msginfo
1124 * before returning to the caller.
1125 * Errors are reported if a reply is received but not expected or if
1126 * more than one reply message is received
1128 * Parameters:
1129 * connection (input) - connection pointer.
1130 * reply_expected (output) - TRUE - a reply message is expected.
1131 * FALSE - no reply message is expected and
1132 * an error will be reported if a reply
1133 * is received.
1135 * Returns:
1136 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed,
1137 * error processing reply message.
1138 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed,
1139 * reply seen.
1140 * NDMP_PROC_REP_ERR - 1 or more messages successfully processed,
1141 * no reply seen.
1142 * NDMP_PROC_REP_ERR - error; connection no longer established.
1144 * Notes:
1145 * If the peer is generating a large number of requests, a caller
1146 * looking for a reply will be blocked while the requests are handled.
1147 * This is because this function does not return until the stream
1148 * buffer is empty.
1149 * Code needs to be added to allow a return if the stream buffer
1150 * is not empty but there is data available on the socket. This will
1151 * prevent poll() from blocking and prevent a caller looking for a reply
1152 * from getting blocked by a bunch of requests.
1154 static int
1155 ndmp_process_messages(ndmp_connection_t *connection, boolean_t reply_expected)
1157 msg_info_t reply_msginfo;
1158 boolean_t reply_read = FALSE;
1159 boolean_t reply_error = FALSE;
1160 int err;
1162 NDMP_LOG(LOG_DEBUG, "reply_expected: %s",
1163 reply_expected == TRUE ? "TRUE" : "FALSE");
1165 (void) memset(&reply_msginfo, 0, sizeof (msg_info_t));
1167 do {
1168 (void) memset(&connection->conn_msginfo, 0,
1169 sizeof (msg_info_t));
1171 if ((err = ndmp_recv_msg(connection)) != NDMP_NO_ERR) {
1172 if (connection->conn_eof) {
1173 NDMP_LOG(LOG_DEBUG, "detected eof");
1174 return (NDMP_PROC_ERR);
1176 if (err < 1) {
1177 NDMP_LOG(LOG_DEBUG, "error decoding header");
1180 * Error occurred decoding the header.
1181 * Don't send a reply since we don't know
1182 * the message or if the message was even
1183 * a request message. To be safe, assume
1184 * that the message was a reply if a reply
1185 * was expected. Need to do this to prevent
1186 * hanging ndmp_send_request() waiting for a
1187 * reply. Don't set reply_read so that the
1188 * reply will be processed if it is received
1189 * later.
1191 if (reply_read == FALSE)
1192 reply_error = TRUE;
1194 continue;
1196 if (connection->conn_msginfo.mi_hdr.message_type
1197 != NDMP_MESSAGE_REQUEST) {
1198 NDMP_LOG(LOG_DEBUG, "received reply: 0x%x",
1199 connection->conn_msginfo.mi_hdr.message);
1201 if (reply_expected == FALSE ||
1202 reply_read == TRUE)
1203 NDMP_LOG(LOG_DEBUG,
1204 "Unexpected reply message: 0x%x",
1205 connection->conn_msginfo.mi_hdr.
1206 message);
1208 ndmp_free_message((ndmp_connection_t *)
1209 connection);
1211 if (reply_read == FALSE) {
1212 reply_read = TRUE;
1213 reply_error = TRUE;
1215 continue;
1217 NDMP_LOG(LOG_DEBUG, "received request: 0x%x",
1218 connection->conn_msginfo.mi_hdr.message);
1220 (void) ndmp_send_response((ndmp_connection_t *)
1221 connection, err, NULL);
1222 ndmp_free_message((ndmp_connection_t *)connection);
1223 continue;
1225 if (connection->conn_msginfo.mi_hdr.message_type
1226 != NDMP_MESSAGE_REQUEST) {
1227 NDMP_LOG(LOG_DEBUG, "received reply: 0x%x",
1228 connection->conn_msginfo.mi_hdr.message);
1230 if (reply_expected == FALSE || reply_read == TRUE) {
1231 NDMP_LOG(LOG_DEBUG,
1232 "Unexpected reply message: 0x%x",
1233 connection->conn_msginfo.mi_hdr.message);
1234 ndmp_free_message((ndmp_connection_t *)
1235 connection);
1236 continue;
1238 reply_read = TRUE;
1239 reply_msginfo = connection->conn_msginfo;
1240 continue;
1242 NDMP_LOG(LOG_DEBUG, "received request: 0x%x",
1243 connection->conn_msginfo.mi_hdr.message);
1246 * The following is needed to catch an improperly constructed
1247 * handler table or to deal with an NDMP client that is not
1248 * conforming to the negotiated protocol version.
1250 if (connection->conn_msginfo.mi_handler->mh_func == NULL) {
1251 NDMP_LOG(LOG_DEBUG, "No handler for message 0x%x",
1252 connection->conn_msginfo.mi_hdr.message);
1254 (void) ndmp_send_response((ndmp_connection_t *)
1255 connection, NDMP_NOT_SUPPORTED_ERR, NULL);
1256 ndmp_free_message((ndmp_connection_t *)connection);
1257 continue;
1260 * Call the handler function.
1261 * The handler will send any necessary reply.
1263 (*connection->conn_msginfo.mi_handler->mh_func) (connection,
1264 connection->conn_msginfo.mi_body);
1266 ndmp_free_message((ndmp_connection_t *)connection);
1268 } while (xdrrec_eof(&connection->conn_xdrs) == FALSE &&
1269 connection->conn_eof == FALSE);
1271 NDMP_LOG(LOG_DEBUG, "no more messages in stream buffer");
1273 if (connection->conn_eof == TRUE) {
1274 free(reply_msginfo.mi_body);
1275 return (NDMP_PROC_ERR);
1277 if (reply_error) {
1278 free(reply_msginfo.mi_body);
1279 return (NDMP_PROC_REP_ERR);
1281 if (reply_read) {
1282 connection->conn_msginfo = reply_msginfo;
1283 return (NDMP_PROC_MSG);
1285 return (NDMP_PROC_REP);
1290 * ndmp_get_interface
1292 * Return the NDMP interface (e.g. config, scsi, tape) for the
1293 * specific message.
1295 * Parameters:
1296 * message (input) - message number.
1298 * Returns:
1299 * NULL - message not found.
1300 * pointer to handler info.
1302 static ndmp_handler_t *
1303 ndmp_get_interface(ndmp_message message)
1305 ndmp_handler_t *ni = &ndmp_msghdl_tab[(message >> 8) % INT_MAXCMD];
1307 if ((message & 0xff) >= ni->hd_cnt)
1308 return (NULL);
1310 /* Sanity check */
1311 if (ni->hd_msgs[message & 0xff].hm_message != message)
1312 return (NULL);
1314 return (ni);
1318 * ndmp_get_handler
1320 * Return the handler info for the specified NDMP message.
1322 * Parameters:
1323 * connection (input) - connection pointer.
1324 * message (input) - message number.
1326 * Returns:
1327 * NULL - message not found.
1328 * pointer to handler info.
1330 static ndmp_msg_handler_t *
1331 ndmp_get_handler(ndmp_connection_t *connection, ndmp_message message)
1333 ndmp_msg_handler_t *handler = NULL;
1335 ndmp_handler_t *ni = ndmp_get_interface(message);
1336 int ver = connection->conn_version;
1338 if (ni)
1339 handler = &ni->hd_msgs[message & 0xff].hm_msg_v[ver - 2];
1341 return (handler);
1345 * ndmp_check_auth_required
1347 * Check if the connection needs to be authenticated before
1348 * this message is being processed.
1350 * Parameters:
1351 * message (input) - message number.
1353 * Returns:
1354 * TRUE - required
1355 * FALSE - not required
1357 static boolean_t
1358 ndmp_check_auth_required(ndmp_message message)
1360 boolean_t auth_req = FALSE;
1361 ndmp_handler_t *ni = ndmp_get_interface(message);
1363 if (ni)
1364 auth_req = ni->hd_msgs[message & 0xff].hm_auth_required;
1366 return (auth_req);
1370 * tcp_accept
1372 * A wrapper around accept for retrying and getting the IP address
1374 * Parameters:
1375 * listen_sock (input) - the socket for listening
1376 * inaddr_p (output) - the IP address of peer connection
1378 * Returns:
1379 * socket for the accepted connection
1380 * -1: error
1383 tcp_accept(int listen_sock, unsigned int *inaddr_p)
1385 struct sockaddr_in sin;
1386 int sock;
1387 socklen_t i;
1388 int try;
1390 for (try = 0; try < 3; try++) {
1391 i = sizeof (sin);
1392 sock = accept(listen_sock, (struct sockaddr *)&sin, &i);
1393 if (sock < 0) {
1394 continue;
1396 *inaddr_p = sin.sin_addr.s_addr;
1397 return (sock);
1399 return (-1);
1404 * tcp_get_peer
1406 * Get the peer IP address for a connection
1408 * Parameters:
1409 * sock (input) - the active socket
1410 * inaddr_p (output) - the IP address of peer connection
1411 * port_p (output) - the port number of peer connection
1413 * Returns:
1414 * socket for the accepted connection
1415 * -1: error
1418 tcp_get_peer(int sock, unsigned int *inaddr_p, int *port_p)
1420 struct sockaddr_in sin;
1421 socklen_t i;
1422 int rc;
1424 i = sizeof (sin);
1425 rc = getpeername(sock, (struct sockaddr *)&sin, &i);
1426 if (rc != 0)
1427 return (-1);
1429 if (inaddr_p)
1430 *inaddr_p = sin.sin_addr.s_addr;
1432 if (port_p)
1433 *port_p = ntohs(sin.sin_port);
1435 return (sock);
1440 * gethostaddr
1442 * Get the IP address string of the current host
1444 * Parameters:
1445 * void
1447 * Returns:
1448 * IP address
1449 * NULL: error
1451 char *
1452 gethostaddr(void)
1454 static char s[MAXHOSTNAMELEN];
1455 struct hostent *h;
1456 struct in_addr in;
1457 char *p;
1459 if (gethostname(s, sizeof (s)) == -1)
1460 return (NULL);
1462 if ((h = gethostbyname(s)) == NULL)
1463 return (NULL);
1465 p = h->h_addr_list[0];
1466 (void) memcpy(&in.s_addr, p, sizeof (in.s_addr));
1467 return (inet_ntoa(in));
1472 * get_default_nic_addr
1474 * Get the IP address of the default NIC
1476 char *
1477 get_default_nic_addr(void)
1479 struct ifaddrlist *al = NULL;
1480 char errmsg[ERRBUFSIZE];
1481 struct in_addr addr;
1482 int nifs;
1484 nifs = ifaddrlist(&al, AF_INET, LIFC_EXTERNAL_SOURCE, errmsg);
1485 if (nifs <= 0)
1486 return (NULL);
1488 /* pick the first interface's address */
1489 addr = al[0].addr.addr;
1490 free(al);
1492 return (inet_ntoa(IN_ADDR(addr.s_addr)));
1497 * ndmpd_audit_backup
1499 * Generate AUE_ndmp_backup audit record
1501 /*ARGSUSED*/
1502 void
1503 ndmpd_audit_backup(ndmp_connection_t *conn,
1504 char *path, int dest, char *local_path, int result)
1506 adt_event_data_t *event;
1508 if ((event = adt_alloc_event(conn->conn_ah, ADT_ndmp_backup)) == NULL) {
1509 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1510 return;
1512 event->adt_ndmp_backup.source = path;
1514 if (dest == NDMP_ADDR_LOCAL) {
1515 event->adt_ndmp_backup.local_dest = local_path;
1516 } else {
1517 event->adt_ndmp_backup.remote_dest = conn->conn_sock;
1520 if (result == 0) {
1521 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0)
1522 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1523 } else {
1524 if (adt_put_event(event, ADT_FAILURE, result) != 0)
1525 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1528 adt_free_event(event);
1533 * ndmpd_audit_restore
1535 * Generate AUE_ndmp_restore audit record
1537 /*ARGSUSED*/
1538 void
1539 ndmpd_audit_restore(ndmp_connection_t *conn,
1540 char *path, int dest, char *local_path, int result)
1542 adt_event_data_t *event;
1544 if ((event = adt_alloc_event(conn->conn_ah,
1545 ADT_ndmp_restore)) == NULL) {
1546 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1547 return;
1549 event->adt_ndmp_restore.destination = path;
1551 if (dest == NDMP_ADDR_LOCAL) {
1552 event->adt_ndmp_restore.local_source = local_path;
1553 } else {
1554 event->adt_ndmp_restore.remote_source = conn->conn_sock;
1557 if (result == 0) {
1558 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0)
1559 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1560 } else {
1561 if (adt_put_event(event, ADT_FAILURE, result) != 0)
1562 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1565 adt_free_event(event);
1570 * ndmpd_audit_connect
1572 * Generate AUE_ndmp_connect audit record
1574 /*ARGSUSED*/
1575 void
1576 ndmpd_audit_connect(ndmp_connection_t *conn, int result)
1578 adt_event_data_t *event;
1579 adt_termid_t *termid;
1581 if (adt_load_termid(conn->conn_sock, &termid) != 0) {
1582 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1583 return;
1586 if (adt_set_user(conn->conn_ah, ADT_NO_ATTRIB, ADT_NO_ATTRIB,
1587 ADT_NO_ATTRIB, ADT_NO_ATTRIB, termid, ADT_NEW) != 0) {
1588 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1589 free(termid);
1590 return;
1592 free(termid);
1594 if ((event = adt_alloc_event(conn->conn_ah,
1595 ADT_ndmp_connect)) == NULL) {
1596 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1597 return;
1600 if (result == 0) {
1601 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0)
1602 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1603 } else {
1604 if (adt_put_event(event, ADT_FAILURE, result) != 0)
1605 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1608 adt_free_event(event);
1613 * ndmpd_audit_disconnect
1615 * Generate AUE_ndmp_disconnect audit record
1617 /*ARGSUSED*/
1618 void
1619 ndmpd_audit_disconnect(ndmp_connection_t *conn)
1621 adt_event_data_t *event;
1623 if ((event = adt_alloc_event(conn->conn_ah,
1624 ADT_ndmp_disconnect)) == NULL) {
1625 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1626 return;
1628 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0)
1629 NDMP_LOG(LOG_ERR, "Audit failure: %m.");
1631 adt_free_event(event);
1634 void *
1635 ndmp_malloc(size_t size)
1637 void *data;
1639 if ((data = calloc(1, size)) == NULL) {
1640 NDMP_LOG(LOG_ERR, "Out of memory.");
1643 return (data);
1647 * get_backup_path_v3
1649 * Get the backup path from the NDMP environment variables.
1651 * Parameters:
1652 * params (input) - pointer to the parameters structure.
1654 * Returns:
1655 * The backup path: if anything is specified
1656 * NULL: Otherwise
1658 char *
1659 get_backup_path_v3(ndmpd_module_params_t *params)
1661 char *bkpath;
1663 bkpath = MOD_GETENV(params, "PREFIX");
1664 if (!bkpath)
1665 bkpath = MOD_GETENV(params, "FILESYSTEM");
1668 if (!bkpath) {
1669 MOD_LOGV3(params, NDMP_LOG_ERROR,
1670 "Backup path not defined.\n");
1671 } else {
1672 NDMP_LOG(LOG_DEBUG, "bkpath: \"%s\"", bkpath);
1675 return (bkpath);
1679 * get_backup_path
1681 * Find the backup path from the environment variables (v2)
1683 char *
1684 get_backup_path_v2(ndmpd_module_params_t *params)
1686 char *bkpath;
1688 bkpath = MOD_GETENV(params, "PREFIX");
1689 if (bkpath == NULL)
1690 bkpath = MOD_GETENV(params, "FILESYSTEM");
1692 if (bkpath == NULL) {
1693 MOD_LOG(params, "Error: restore path not specified.\n");
1694 return (NULL);
1697 if (*bkpath != '/') {
1698 MOD_LOG(params, "Error: relative backup path not allowed.\n");
1699 return (NULL);
1702 return (bkpath);