2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
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
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
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
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) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
48 #include <tsol/label.h>
51 #include "ndmpd_common.h"
53 /* zfs library handle & mutex */
54 libzfs_handle_t
*zlibh
;
58 static void ndmpd_sig_handler(int sig
);
60 typedef struct ndmpd
{
61 int s_shutdown_flag
; /* Fields for shutdown control */
69 * Load and initialize the plug-in module
75 ndmp_plugin_t
*(*plugin_init
)(int);
79 plname
= ndmpd_get_prop(NDMP_PLUGIN_PATH
);
80 if (plname
== NULL
|| *plname
== '\0')
83 if ((mod_plp
= dlopen(plname
, RTLD_LOCAL
| RTLD_NOW
)) == NULL
) {
84 NDMP_LOG(LOG_ERR
, "Error loading the plug-in %s: %s",
89 plugin_init
= (ndmp_plugin_t
*(*)(int))dlsym(mod_plp
, "_ndmp_init");
90 if (plugin_init
== NULL
) {
91 (void) dlclose(mod_plp
);
94 if ((ndmp_pl
= plugin_init(NDMP_PLUGIN_VERSION
)) == NULL
) {
95 NDMP_LOG(LOG_ERR
, "Error loading the plug-in %s", plname
);
110 void (*plugin_fini
)(ndmp_plugin_t
*);
112 plugin_fini
= (void (*)(ndmp_plugin_t
*))dlsym(mod_plp
, "_ndmp_fini");
113 if (plugin_fini
== NULL
) {
114 (void) dlclose(mod_plp
);
117 plugin_fini(ndmp_pl
);
118 (void) dlclose(mod_plp
);
124 priv_set_t
*pset
= priv_allocset();
127 * Set effective sets privileges to 'least' required. If fails, send
128 * error messages to log file and proceed.
132 (void) priv_addset(pset
, PRIV_PROC_AUDIT
);
133 (void) priv_addset(pset
, PRIV_PROC_SETID
);
134 (void) priv_addset(pset
, PRIV_PROC_OWNER
);
135 (void) priv_addset(pset
, PRIV_FILE_CHOWN
);
136 (void) priv_addset(pset
, PRIV_FILE_CHOWN_SELF
);
137 (void) priv_addset(pset
, PRIV_FILE_DAC_READ
);
138 (void) priv_addset(pset
, PRIV_FILE_DAC_SEARCH
);
139 (void) priv_addset(pset
, PRIV_FILE_DAC_WRITE
);
140 (void) priv_addset(pset
, PRIV_FILE_OWNER
);
141 (void) priv_addset(pset
, PRIV_FILE_SETID
);
142 (void) priv_addset(pset
, PRIV_SYS_LINKDIR
);
143 (void) priv_addset(pset
, PRIV_SYS_DEVICES
);
144 (void) priv_addset(pset
, PRIV_SYS_MOUNT
);
145 (void) priv_addset(pset
, PRIV_SYS_CONFIG
);
148 if (pset
== NULL
|| setppriv(PRIV_SET
, PRIV_EFFECTIVE
, pset
) != 0) {
149 (void) fprintf(stderr
,
150 "Failed to set least required privileges to the service\n");
162 * Block all signals prior to the fork and leave them blocked in the
163 * parent so we don't get in a situation where the parent gets SIGINT
164 * and returns non-zero exit status and the child is actually running.
165 * In the child, restore the signal mask once we've done our setsid().
167 (void) sigfillset(&set
);
168 (void) sigdelset(&set
, SIGABRT
);
169 (void) sigprocmask(SIG_BLOCK
, &set
, &oset
);
171 if ((pid
= fork()) == -1) {
172 (void) fprintf(stderr
,
173 "Failed to start process in background.\n");
174 exit(SMF_EXIT_ERR_CONFIG
);
177 /* If we're the parent process, exit. */
182 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);
189 * The main NDMP daemon function
192 * argc (input) - the argument count
193 * argv (input) - command line options
199 main(int argc
, char *argv
[])
201 struct sigaction act
;
205 boolean_t run_in_foreground
= B_FALSE
;
206 boolean_t override_debug
= B_FALSE
;
209 * Check for existing ndmpd door server (make sure ndmpd is not already
212 if (ndmp_door_check()) {
213 /* ndmpd is already running, exit. */
214 (void) fprintf(stderr
, "ndmpd is already running.\n");
218 /* Global zone check */
219 if (getzoneid() != GLOBAL_ZONEID
) {
220 (void) fprintf(stderr
, "Non-global zone not supported.\n");
221 exit(SMF_EXIT_ERR_FATAL
);
224 /* Trusted Solaris check */
225 if (is_system_labeled()) {
226 (void) fprintf(stderr
, "Trusted Solaris not supported.\n");
227 exit(SMF_EXIT_ERR_FATAL
);
230 /* load SMF configuration */
231 if (ndmpd_load_prop()) {
232 (void) fprintf(stderr
,
233 "SMF properties initialization failed.\n");
234 exit(SMF_EXIT_ERR_CONFIG
);
238 while ((c
= getopt(argc
, argv
, "df")) != -1) {
241 override_debug
= B_TRUE
;
244 run_in_foreground
= B_TRUE
;
247 (void) fprintf(stderr
, "%s: Invalid option -%c.\n",
249 (void) fprintf(stderr
, "Usage: %s [-df]\n", argv
[0]);
250 exit(SMF_EXIT_ERR_CONFIG
);
254 /* set up signal handler */
255 (void) sigfillset(&set
);
256 (void) sigdelset(&set
, SIGABRT
); /* always unblocked for ASSERT() */
257 (void) sigfillset(&act
.sa_mask
);
258 act
.sa_handler
= ndmpd_sig_handler
;
261 (void) sigaction(SIGTERM
, &act
, NULL
);
262 (void) sigaction(SIGHUP
, &act
, NULL
);
263 (void) sigaction(SIGINT
, &act
, NULL
);
264 (void) sigaction(SIGUSR1
, &act
, NULL
);
265 (void) sigaction(SIGPIPE
, &act
, NULL
);
266 (void) sigdelset(&set
, SIGTERM
);
267 (void) sigdelset(&set
, SIGHUP
);
268 (void) sigdelset(&set
, SIGINT
);
269 (void) sigdelset(&set
, SIGUSR1
);
270 (void) sigdelset(&set
, SIGPIPE
);
274 openlog(argv
[0], LOG_PID
| LOG_NDELAY
, LOG_DAEMON
);
277 * Open log file before we detach from terminal in case that open
278 * fails and error message is printed to stderr.
280 if (ndmp_log_open_file(run_in_foreground
, override_debug
) != 0)
281 exit(SMF_EXIT_ERR_FATAL
);
283 if (!run_in_foreground
)
286 (void) mutex_init(&ndmpd_zfs_fd_lock
, 0, NULL
);
288 if (mod_init() != 0) {
289 NDMP_LOG(LOG_ERR
, "Failed to load the plugin module.");
290 exit(SMF_EXIT_ERR_CONFIG
);
294 if ((zlibh
= libzfs_init()) == NULL
) {
295 NDMP_LOG(LOG_ERR
, "Failed to initialize ZFS library.");
296 exit(SMF_EXIT_ERR_CONFIG
);
299 /* initialize and start the door server */
300 if (ndmp_door_init()) {
301 NDMP_LOG(LOG_ERR
, "Can not start ndmpd door server.");
302 exit(SMF_EXIT_ERR_CONFIG
);
305 if (tlm_init() == -1) {
306 NDMP_LOG(LOG_ERR
, "Failed to initialize tape manager.");
307 exit(SMF_EXIT_ERR_CONFIG
);
311 * Prior to this point, we are single-threaded. We will be
312 * multi-threaded from this point on.
314 (void) pthread_create(NULL
, NULL
, (funct_t
)ndmpd_main
,
317 while (!ndmpd
.s_shutdown_flag
) {
318 (void) sigsuspend(&set
);
320 switch (ndmpd
.s_sigval
) {
328 /* Refresh SMF properties */
329 if (ndmpd_load_prop())
331 "Service properties initialization "
337 * Typically SIGINT or SIGTERM.
339 ndmpd
.s_shutdown_flag
= 1;
346 (void) mutex_destroy(&ndmpd_zfs_fd_lock
);
350 ndmp_log_close_file();
352 return (SMF_EXIT_OK
);
356 ndmpd_sig_handler(int sig
)
358 if (ndmpd
.s_sigval
== 0)
359 ndmpd
.s_sigval
= sig
;
363 * Enable libumem debugging by default on DEBUG builds.
367 _umem_debug_init(void)
369 return ("default,verbose"); /* $UMEM_DEBUG setting */
373 _umem_logging_init(void)
375 return ("fail,contents"); /* $UMEM_LOGGING setting */