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