#include <stdio.h>
#include <stdlib.h>
#include <stropts.h>
#include <signal.h>
#include <fcntl.h>
#include <door.h>
#include <thread.h>
#include <priv_utils.h>
#include <locale.h>
#include <strings.h>
#include <syslog.h>
#include <unistd.h>
#include <nfs/nfs4.h>
#include <nfs/nfsid_map.h>
#include <rpcsvc/daemon_utils.h>
#include <arpa/nameser.h>
#include <nfs/nfssys.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
extern struct group *_uncached_getgrgid_r(gid_t, struct group *, char *, int);
extern struct group *_uncached_getgrnam_r(const char *, struct group *,
char *, int);
extern struct passwd *_uncached_getpwuid_r(uid_t, struct passwd *, char *, int);
extern struct passwd *_uncached_getpwnam_r(const char *, struct passwd *,
char *, int);
#define NFSCFG_DEFAULT_DOMAIN_TMOUT (5 * 60)
#define NFSMAPID_DOOR "/var/run/nfsmapid_door"
extern void nfsmapid_func(void *, char *, size_t, door_desc_t *, uint_t);
extern void check_domain(int);
extern void idmap_kcall(int);
extern void open_diag_file(void);
size_t pwd_buflen = 0;
size_t grp_buflen = 0;
thread_t sig_thread;
static char *MyName;
time_t nfscfg_domain_tmout = NFSCFG_DEFAULT_DOMAIN_TMOUT;
static void
daemonize(void)
{
switch (fork()) {
case -1:
perror("nfsmapid: can't fork");
exit(2);
case 0:
break;
default:
_exit(0);
}
if (chdir("/") < 0)
syslog(LOG_ERR, gettext("chdir /: %m"));
(void) close(0);
(void) close(1);
(void) close(2);
(void) open("/dev/null", O_RDONLY);
(void) open("/dev/null", O_WRONLY);
(void) dup(1);
(void) setsid();
}
static void *
sig_handler(void *arg)
{
siginfo_t si;
sigset_t sigset;
struct timespec tmout;
int ret;
tmout.tv_nsec = 0;
(void) sigemptyset(&sigset);
(void) sigaddset(&sigset, SIGHUP);
(void) sigaddset(&sigset, SIGTERM);
#ifdef DEBUG
(void) sigaddset(&sigset, SIGINT);
#endif
while (1) {
tmout.tv_sec = nfscfg_domain_tmout;
if ((ret = sigtimedwait(&sigset, &si, &tmout)) != 0) {
if (ret == -1 && errno == EAGAIN) {
check_domain(0);
continue;
}
switch (si.si_signo) {
case SIGHUP:
check_domain(1);
break;
#ifdef DEBUG
case SIGINT:
exit(0);
#endif
case SIGTERM:
default:
exit(si.si_signo);
}
}
}
return (NULL);
}
static void
thr_init(void)
{
sigset_t sigset;
long thr_flags = (THR_NEW_LWP|THR_DAEMON|THR_SUSPENDED);
(void) thr_sigsetmask(0, NULL, &sigset);
(void) sigaddset(&sigset, SIGHUP);
(void) sigaddset(&sigset, SIGTERM);
#ifdef DEBUG
(void) sigaddset(&sigset, SIGINT);
#endif
(void) thr_sigsetmask(SIG_SETMASK, &sigset, NULL);
if (thr_create(NULL, 0, sig_handler, 0, thr_flags, &sig_thread)) {
syslog(LOG_ERR,
gettext("Failed to create signal handling thread"));
exit(4);
}
}
static void
daemon_init(void)
{
struct passwd pwd;
struct group grp;
char *pwd_buf;
char *grp_buf;
pwd_buflen = (size_t)sysconf(_SC_GETPW_R_SIZE_MAX);
grp_buflen = (size_t)sysconf(_SC_GETGR_R_SIZE_MAX);
thr_init();
check_domain(0);
setpwent();
setgrent();
(void) getpwent();
(void) getgrent();
if ((pwd_buf = malloc(pwd_buflen)) == NULL)
return;
(void) _uncached_getpwnam_r("NF21dmvP", &pwd, pwd_buf, pwd_buflen);
(void) _uncached_getpwuid_r(1181794, &pwd, pwd_buf, pwd_buflen);
if ((grp_buf = realloc(pwd_buf, grp_buflen)) == NULL) {
free(pwd_buf);
return;
}
(void) _uncached_getgrnam_r("NF21dmvP", &grp, grp_buf, grp_buflen);
(void) _uncached_getgrgid_r(1181794, &grp, grp_buf, grp_buflen);
free(grp_buf);
}
static int
start_svcs(void)
{
int doorfd = -1;
#ifdef DEBUG
int dfd;
#endif
if ((doorfd = door_create(nfsmapid_func, NULL,
DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) {
syslog(LOG_ERR, "Unable to create door: %m\n");
return (1);
}
#ifdef DEBUG
if ((dfd = open(NFSMAPID_DOOR, O_RDWR|O_CREAT|O_TRUNC,
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) {
syslog(LOG_ERR, "Unable to open %s: %m\n", NFSMAPID_DOOR);
(void) close(doorfd);
return (1);
}
(void) fdetach(NFSMAPID_DOOR);
if (fattach(doorfd, NFSMAPID_DOOR) == -1) {
syslog(LOG_ERR, "Unable to fattach door: %m\n");
(void) close(dfd);
(void) close(doorfd);
return (1);
}
(void) close(dfd);
#endif
idmap_kcall(doorfd);
while (1)
(void) pause();
syslog(LOG_ERR, gettext("Door server exited"));
return (10);
}
int
main(int argc, char **argv)
{
MyName = argv[0];
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
(void) _create_daemon_lock(NFSMAPID, DAEMON_UID, DAEMON_GID);
open_diag_file();
#ifndef DEBUG
if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET,
DAEMON_UID, DAEMON_GID, PRIV_SYS_NFS, (char *)NULL) == -1) {
(void) fprintf(stderr, gettext("%s PRIV_SYS_NFS privilege "
"missing\n"), MyName);
exit(1);
}
#endif
(void) priv_set(PRIV_OFF, PRIV_PERMITTED,
PRIV_FILE_LINK_ANY, PRIV_PROC_SESSION,
(char *)NULL);
#ifndef DEBUG
daemonize();
switch (_enter_daemon_lock(NFSMAPID)) {
case 0:
break;
case -1:
syslog(LOG_ERR, "error locking for %s: %s", NFSMAPID,
strerror(errno));
exit(3);
default:
exit(0);
}
#endif
openlog(MyName, LOG_PID | LOG_NDELAY, LOG_DAEMON);
daemon_init();
return (start_svcs());
}