4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
33 #include <priv_utils.h>
39 #include <nfs/nfsid_map.h>
40 #include <rpcsvc/daemon_utils.h>
41 #include <arpa/nameser.h>
42 #include <nfs/nfssys.h>
47 extern struct group
*_uncached_getgrgid_r(gid_t
, struct group
*, char *, int);
48 extern struct group
*_uncached_getgrnam_r(const char *, struct group
*,
50 extern struct passwd
*_uncached_getpwuid_r(uid_t
, struct passwd
*, char *, int);
51 extern struct passwd
*_uncached_getpwnam_r(const char *, struct passwd
*,
55 * seconds to cache nfsmapid domain info
57 #define NFSCFG_DEFAULT_DOMAIN_TMOUT (5 * 60)
58 #define NFSMAPID_DOOR "/var/run/nfsmapid_door"
60 extern void nfsmapid_func(void *, char *, size_t, door_desc_t
*, uint_t
);
62 extern void check_domain(int);
63 extern void idmap_kcall(int);
64 extern void open_diag_file(void);
66 size_t pwd_buflen
= 0;
67 size_t grp_buflen
= 0;
72 * nfscfg_domain_tmout is used by nfsv4-test scripts to query
73 * the nfsmapid daemon for the proper timeout. Don't delete !
75 time_t nfscfg_domain_tmout
= NFSCFG_DEFAULT_DOMAIN_TMOUT
;
78 * Processing for daemonization
85 perror("nfsmapid: can't fork");
96 syslog(LOG_ERR
, gettext("chdir /: %m"));
99 * Close stdin, stdout, and stderr.
100 * Open again to redirect input+output
105 (void) open("/dev/null", O_RDONLY
);
106 (void) open("/dev/null", O_WRONLY
);
113 sig_handler(void *arg
)
117 struct timespec tmout
;
121 (void) sigemptyset(&sigset
);
122 (void) sigaddset(&sigset
, SIGHUP
);
123 (void) sigaddset(&sigset
, SIGTERM
);
125 (void) sigaddset(&sigset
, SIGINT
);
130 tmout
.tv_sec
= nfscfg_domain_tmout
;
131 if ((ret
= sigtimedwait(&sigset
, &si
, &tmout
)) != 0) {
133 * EAGAIN: no signals arrived during timeout.
134 * check/update config files and continue.
136 if (ret
== -1 && errno
== EAGAIN
) {
141 switch (si
.si_signo
) {
160 * Thread initialization. Mask out all signals we want our
161 * signal handler to handle for us from any other threads.
167 long thr_flags
= (THR_NEW_LWP
|THR_DAEMON
|THR_SUSPENDED
);
170 * Before we kick off any other threads, mask out desired
171 * signals from main thread so that any subsequent threads
172 * don't receive said signals.
174 (void) thr_sigsetmask(0, NULL
, &sigset
);
175 (void) sigaddset(&sigset
, SIGHUP
);
176 (void) sigaddset(&sigset
, SIGTERM
);
178 (void) sigaddset(&sigset
, SIGINT
);
180 (void) thr_sigsetmask(SIG_SETMASK
, &sigset
, NULL
);
183 * Create the signal handler thread suspended ! We do things
184 * this way at setup time to minimize the probability of
185 * introducing any race conditions _if_ the process were to
186 * get a SIGHUP signal while creating a new DNS query thread
187 * in get_dns_txt_domain().
189 if (thr_create(NULL
, 0, sig_handler
, 0, thr_flags
, &sig_thread
)) {
191 gettext("Failed to create signal handling thread"));
205 * passwd/group reentrant interfaces limits
207 pwd_buflen
= (size_t)sysconf(_SC_GETPW_R_SIZE_MAX
);
208 grp_buflen
= (size_t)sysconf(_SC_GETGR_R_SIZE_MAX
);
211 * MT initialization is done first so that if there is the
212 * need to fire an additional thread to continue to query
213 * DNS, that thread is started off with the main thread's
219 * Determine nfsmapid domain.
224 * In the case of nfsmapid running diskless, it is important
225 * to get the initial connections to the nameservices
226 * established to prevent problems like opening a devfs
227 * node to contact a nameservice being blocked by the
228 * resolution of an active devfs lookup.
229 * First issue a set*ent to "open" the databases and then
230 * get an entry and finally lookup a bogus entry to trigger
237 if ((pwd_buf
= malloc(pwd_buflen
)) == NULL
)
240 (void) _uncached_getpwnam_r("NF21dmvP", &pwd
, pwd_buf
, pwd_buflen
);
241 (void) _uncached_getpwuid_r(1181794, &pwd
, pwd_buf
, pwd_buflen
);
243 if ((grp_buf
= realloc(pwd_buf
, grp_buflen
)) == NULL
) {
248 (void) _uncached_getgrnam_r("NF21dmvP", &grp
, grp_buf
, grp_buflen
);
249 (void) _uncached_getgrgid_r(1181794, &grp
, grp_buf
, grp_buflen
);
261 if ((doorfd
= door_create(nfsmapid_func
, NULL
,
262 DOOR_REFUSE_DESC
| DOOR_NO_CANCEL
)) == -1) {
263 syslog(LOG_ERR
, "Unable to create door: %m\n");
269 * Create a file system path for the door
271 if ((dfd
= open(NFSMAPID_DOOR
, O_RDWR
|O_CREAT
|O_TRUNC
,
272 S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IROTH
)) == -1) {
273 syslog(LOG_ERR
, "Unable to open %s: %m\n", NFSMAPID_DOOR
);
274 (void) close(doorfd
);
279 * Clean up any stale associations
281 (void) fdetach(NFSMAPID_DOOR
);
284 * Register in namespace to pass to the kernel to door_ki_open
286 if (fattach(doorfd
, NFSMAPID_DOOR
) == -1) {
287 syslog(LOG_ERR
, "Unable to fattach door: %m\n");
289 (void) close(doorfd
);
296 * Now that we're actually running, go
297 * ahead and flush the kernel flushes
298 * Pass door name to kernel for door_ki_open
303 * Wait for incoming calls
309 syslog(LOG_ERR
, gettext("Door server exited"));
315 main(int argc
, char **argv
)
319 (void) setlocale(LC_ALL
, "");
320 (void) textdomain(TEXT_DOMAIN
);
322 /* _check_services() framework setup */
323 (void) _create_daemon_lock(NFSMAPID
, DAEMON_UID
, DAEMON_GID
);
326 * Open diag file in /var/run while we've got the perms
331 * Initialize the daemon to basic + sys_nfs
334 if (__init_daemon_priv(PU_RESETGROUPS
|PU_CLEARLIMITSET
,
335 DAEMON_UID
, DAEMON_GID
, PRIV_SYS_NFS
, NULL
) == -1) {
336 (void) fprintf(stderr
, gettext("%s PRIV_SYS_NFS privilege "
337 "missing\n"), MyName
);
343 * Take away a subset of basic, while this is not the absolute
344 * minimum, it is important that it is unique among other
345 * daemons to insure that we get a unique cred that will
346 * result in a unique open_owner. If not, we run the risk
347 * of a diskless client deadlocking with a thread holding
348 * the open_owner seqid lock while upcalling the daemon.
349 * XXX This restriction will go away once we stop holding
350 * XXX open_owner lock across rfscalls!
352 (void) priv_set(PRIV_OFF
, PRIV_PERMITTED
, PRIV_FILE_LINK_ANY
,
353 PRIV_PROC_SESSION
, NULL
);
357 switch (_enter_daemon_lock(NFSMAPID
)) {
362 syslog(LOG_ERR
, "error locking for %s: %s", NFSMAPID
,
367 /* daemon was already running */
371 openlog(MyName
, LOG_PID
| LOG_NDELAY
, LOG_DAEMON
);
373 /* Initialize daemon subsystems */
377 return (start_svcs());