void fmd_rpc_init(void) { int err, prog, mode = RPC_SVC_MT_USER; uint64_t sndsize = 0, rcvsize = 0; const char *s; if (rpc_control(RPC_SVC_MTMODE_SET, &mode) == FALSE) fmd_panic("failed to enable user-MT rpc mode"); (void) fmd_conf_getprop(fmd.d_conf, "rpc.sndsize", &sndsize); (void) fmd_conf_getprop(fmd.d_conf, "rpc.rcvsize", &rcvsize); /* * Infer whether we are the "default" fault manager or an alternate one * based on whether the initial setting of rpc.adm.prog is non-zero. */ (void) fmd_conf_getprop(fmd.d_conf, "rpc.adm.prog", &prog); (void) fmd_conf_getprop(fmd.d_conf, "rpc.adm.path", &s); if (prog != 0) { err = fmd_rpc_svc_init(fmd_adm_1, "FMD_ADM", s, "rpc.adm.prog", FMD_ADM, FMD_ADM, FMD_ADM_VERSION_1, (uint_t)sndsize, (uint_t)rcvsize, TRUE); } else { err = fmd_rpc_svc_init(fmd_adm_1, "FMD_ADM", s, "rpc.adm.prog", RPC_TRANS_MIN, RPC_TRANS_MAX, FMD_ADM_VERSION_1, (uint_t)sndsize, (uint_t)rcvsize, FALSE); } if (err != 0) fmd_error(EFMD_EXIT, "failed to create rpc server bindings"); if (fmd_thread_create(fmd.d_rmod, (fmd_thread_f *)svc_run, 0) == NULL) fmd_error(EFMD_EXIT, "failed to create rpc server thread"); }
int main(int argc, char *argv[]) { int pid; int c; int rpc_svc_mode = RPC_SVC_MT_AUTO; int maxthreads; int maxrecsz = RPC_MAXDATASIZE; bool_t exclbind = TRUE; bool_t can_do_mlp; long thr_flags = (THR_NEW_LWP|THR_DAEMON); /* * Mountd requires uid 0 for: * /etc/rmtab updates (we could chown it to daemon) * /etc/dfs/dfstab reading (it wants to lock out share which * doesn't do any locking before first truncate; * NFS share does; should use fcntl locking instead) * Needed privileges: * auditing * nfs syscall * file dac search (so it can stat all files) * Optional privileges: * MLP */ can_do_mlp = priv_ineffect(PRIV_NET_BINDMLP); if (__init_daemon_priv(PU_RESETGROUPS|PU_CLEARLIMITSET, -1, -1, PRIV_SYS_NFS, PRIV_PROC_AUDIT, PRIV_FILE_DAC_SEARCH, can_do_mlp ? PRIV_NET_BINDMLP : NULL, NULL) == -1) { (void) fprintf(stderr, "%s must be run as with sufficient privileges\n", argv[0]); exit(1); } maxthreads = 0; while ((c = getopt(argc, argv, "vrm:")) != EOF) { switch (c) { case 'v': verbose++; break; case 'r': rejecting = 1; break; case 'm': maxthreads = atoi(optarg); if (maxthreads < 1) { (void) fprintf(stderr, "%s: must specify positive maximum threads count, using default\n", argv[0]); maxthreads = 0; } break; } } /* * Read in the NFS version values from config file. */ if ((defopen(NFSADMIN)) == 0) { char *defval; int defvers; if ((defval = defread("NFS_SERVER_VERSMIN=")) != NULL) { errno = 0; defvers = strtol(defval, (char **)NULL, 10); if (errno == 0) { mount_vers_min = defvers; /* * special because NFSv2 is * supported by mount v1 & v2 */ if (defvers == NFS_VERSION) mount_vers_min = MOUNTVERS; } } if ((defval = defread("NFS_SERVER_VERSMAX=")) != NULL) { errno = 0; defvers = strtol(defval, (char **)NULL, 10); if (errno == 0) { mount_vers_max = defvers; } } /* close defaults file */ defopen(NULL); } /* * Sanity check versions, * even though we may get versions > MOUNTVERS3, we still need * to start nfsauth service, so continue on regardless of values. */ if (mount_vers_min > mount_vers_max) { syslog(LOG_NOTICE, "NFS_SERVER_VERSMIN > NFS_SERVER_VERSMAX"); mount_vers_max = mount_vers_min; } (void) setlocale(LC_ALL, ""); (void) rwlock_init(&sharetab_lock, USYNC_THREAD, NULL); (void) mutex_init(&mnttab_lock, USYNC_THREAD, NULL); netgroup_init(); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); /* Don't drop core if the NFS module isn't loaded. */ (void) signal(SIGSYS, SIG_IGN); (void) signal(SIGHUP, sigexit); (void) signal(SIGCLD, sigexit); switch (fork()) { case 0: /* child */ break; case -1: perror("mountd: can't fork"); exit(1); default: /* parent */ for (;;) (void) pause(); /* NOTREACHED */ } (void) signal(SIGHUP, SIG_DFL); (void) signal(SIGCLD, SIG_DFL); /* * If we coredump it'll be in /core */ if (chdir("/") < 0) syslog(LOG_ERR, "chdir /: %m"); /* * Close existing file descriptors, open "/dev/null" as * standard input, output, and error, and detach from * controlling terminal. */ closefrom(0); (void) open("/dev/null", O_RDONLY); (void) open("/dev/null", O_WRONLY); (void) dup(1); (void) setsid(); openlog("mountd", LOG_PID, LOG_DAEMON); /* * establish our lock on the lock file and write our pid to it. * exit if some other process holds the lock, or if there's any * error in writing/locking the file. */ pid = _enter_daemon_lock(MOUNTD); switch (pid) { case 0: break; case -1: syslog(LOG_ERR, "error locking for %s: %s", MOUNTD, strerror(errno)); exit(2); default: /* daemon was already running */ exit(0); } audit_mountd_setup(); /* BSM */ /* * Tell RPC that we want automatic thread mode. * A new thread will be spawned for each request. */ if (!rpc_control(RPC_SVC_MTMODE_SET, &rpc_svc_mode)) { syslog(LOG_ERR, "unable to set automatic MT mode"); exit(1); } /* * Enable non-blocking mode and maximum record size checks for * connection oriented transports. */ if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) { syslog(LOG_INFO, "unable to set RPC max record size"); } /* * Prevent our non-priv udp and tcp ports bound w/wildcard addr * from being hijacked by a bind to a more specific addr. */ if (!rpc_control(__RPC_SVC_EXCLBIND_SET, &exclbind)) { syslog(LOG_INFO, "warning: unable to set udp/tcp EXCLBIND"); } /* * If the -m argument was specified, then set the * maximum number of threads to the value specified. */ if (maxthreads > 0 && !rpc_control(RPC_SVC_THRMAX_SET, &maxthreads)) { syslog(LOG_ERR, "unable to set maxthreads"); exit(1); } /* * Make sure to unregister any previous versions in case the * user is reconfiguring the server in interesting ways. */ svc_unreg(MOUNTPROG, MOUNTVERS); svc_unreg(MOUNTPROG, MOUNTVERS_POSIX); svc_unreg(MOUNTPROG, MOUNTVERS3); /* * Create the nfsauth thread with same signal disposition * as the main thread. We need to create a separate thread * since mountd() will be both an RPC server (for remote * traffic) _and_ a doors server (for kernel upcalls). */ if (thr_create(NULL, 0, nfsauth_svc, 0, thr_flags, &nfsauth_thread)) { syslog(LOG_ERR, gettext("Failed to create NFSAUTH svc thread")); exit(2); } /* * Create datagram and connection oriented services */ if (mount_vers_max >= MOUNTVERS) { if (svc_create(mnt, MOUNTPROG, MOUNTVERS, "datagram_v") == 0) { syslog(LOG_ERR, "couldn't register datagram_v MOUNTVERS"); exit(1); } if (svc_create(mnt, MOUNTPROG, MOUNTVERS, "circuit_v") == 0) { syslog(LOG_ERR, "couldn't register circuit_v MOUNTVERS"); exit(1); } } if (mount_vers_max >= MOUNTVERS_POSIX) { if (svc_create(mnt, MOUNTPROG, MOUNTVERS_POSIX, "datagram_v") == 0) { syslog(LOG_ERR, "couldn't register datagram_v MOUNTVERS_POSIX"); exit(1); } if (svc_create(mnt, MOUNTPROG, MOUNTVERS_POSIX, "circuit_v") == 0) { syslog(LOG_ERR, "couldn't register circuit_v MOUNTVERS_POSIX"); exit(1); } } if (mount_vers_max >= MOUNTVERS3) { if (svc_create(mnt, MOUNTPROG, MOUNTVERS3, "datagram_v") == 0) { syslog(LOG_ERR, "couldn't register datagram_v MOUNTVERS3"); exit(1); } if (svc_create(mnt, MOUNTPROG, MOUNTVERS3, "circuit_v") == 0) { syslog(LOG_ERR, "couldn't register circuit_v MOUNTVERS3"); exit(1); } } /* * Start serving */ rmtab_load(); (void) kill(getppid(), SIGHUP); /* Get rid of the most dangerous basic privileges. */ __fini_daemon_priv(PRIV_PROC_EXEC, PRIV_PROC_INFO, PRIV_PROC_SESSION, (char *)NULL); svc_run(); syslog(LOG_ERR, "Error: svc_run shouldn't have returned"); abort(); /* NOTREACHED */ return (0); }
int main(int argc, char *argv[]) { int sflag = 0, s1flag = 0, s2flag = 0, nflag = 0, dflag = 0, eflag = 0; char *options, *value; extern char *optarg; extern int optind; int c, d; struct rlimit rl; int mode = RPC_SVC_MT_AUTO; int maxrecsz = RPC_MAXDATASIZE; void detachfromtty(void); int setmodulus(); int pk_nodefaultkeys(); int svc_create_local_service(); char domainname[MAXNETNAMELEN + 1]; /* * Set our allowed number of file descriptors to the max * of what the system will allow, limited by FD_SETSIZE. */ if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { rlim_t limit; if ((limit = rl.rlim_max) > FD_SETSIZE) limit = FD_SETSIZE; rl.rlim_cur = limit; (void) setrlimit(RLIMIT_NOFILE, &rl); (void) enable_extended_FILE_stdio(-1, -1); } __key_encryptsession_pk_LOCAL = &__key_encrypt_pk_2_svc; __key_decryptsession_pk_LOCAL = &__key_decrypt_pk_2_svc; __key_gendes_LOCAL = &__key_gen_1_svc; /* * Pre-option initialisation */ (void) umask(066); /* paranoia */ if (geteuid() != 0) { (void) fprintf(stderr, "%s must be run as root\n", argv[0]); exit(1); } setmodulus(HEXMODULUS); openlog("keyserv", LOG_PID, LOG_DAEMON); /* * keyserv will not work with a null domainname. */ if (getdomainname(domainname, MAXNETNAMELEN+1) || (domainname[0] == '\0')) { syslog(LOG_ERR, "could not get a valid domainname.\n"); exit(SMF_EXIT_ERR_CONFIG); } /* * Initialise security mechanisms */ cache_size = NULL; cache_options = NULL; if (init_mechs() == -1) { disk_caching = 0; } defaults(); while ((c = getopt(argc, argv, "ndDet:cs:")) != -1) switch (c) { case 'n': nflag++; break; case 'd': dflag++; use_nobody_keys = FALSE; break; case 'e': eflag++; use_nobody_keys = TRUE; break; case 'D': debugging = 1; break; case 't': nthreads = atoi(optarg); break; case 'c': disk_caching = 0; break; case 's': if (!disk_caching) { fprintf(stderr, "missing configuration file"); fprintf(stderr, " or -c option specified\n"); usage(); } sflag++; /* * Which version of [-s] do we have...? */ if (strchr((const char *) optarg, '=') == NULL) { /* * -s <size> */ if (s1flag) { fprintf(stderr, "duplicate" " [-s <size>]\n"); usage(); } s1flag++; default_cache = get_cache_size(optarg); break; } /* * -s <mechtype>=<size>[,...] */ s2flag++; options = optarg; while (*options != '\0') { d = getsubopt(&options, cache_options, &value); if (d == -1) { /* Ignore unknown mechtype */ continue; } if (value == NULL) { fprintf(stderr, "missing cache size for " "mechtype %s\n", cache_options[d]); usage(); } cache_size[d] = get_cache_size(value); } break; default: usage(); break; } if (dflag && eflag) { (void) fprintf(stderr, "specify only one of -d and -e\n"); usage(); } if (use_nobody_keys == FALSE) { pk_nodefaultkeys(); } if (optind != argc) { usage(); } if (!disk_caching && sflag) { fprintf(stderr, "missing configuration file"); fprintf(stderr, " or -c option specified\n"); usage(); } if (debugging) { if (disk_caching) { char **cpp = cache_options; int *ip = cache_size; (void) fprintf(stderr, "default disk cache size: "); if (default_cache < 0) { (void) fprintf(stderr, "%d entries\n", abs(default_cache)); } else { (void) fprintf(stderr, "%dMB\n", default_cache); } (void) fprintf(stderr, "supported mechanisms:\n"); (void) fprintf(stderr, "\talias\t\tdisk cache size\n"); (void) fprintf(stderr, "\t=====\t\t===============\n"); while (*cpp != NULL) { (void) fprintf(stderr, "\t%s\t\t", *cpp++); if (*ip < 0) { (void) fprintf(stderr, "%d entries\n", abs(*ip)); } else { (void) fprintf(stderr, "%dMB\n", *ip); } ip++; } } else { (void) fprintf(stderr, "common key disk caching disabled\n"); } } /* * Post-option initialisation */ if (disk_caching) { int i; for (i = 0; mechs[i]; i++) { if ((AUTH_DES_COMPAT_CHK(mechs[i])) || (mechs[i]->keylen < 0) || (mechs[i]->algtype < 0)) continue; create_cache_file(mechs[i]->keylen, mechs[i]->algtype, cache_size[i] ? cache_size[i] : default_cache); } } getrootkey(&masterkey, nflag); /* * Set MT mode */ if (nthreads > 0) { (void) rpc_control(RPC_SVC_MTMODE_SET, &mode); (void) rpc_control(RPC_SVC_THRMAX_SET, &nthreads); } /* * Enable non-blocking mode and maximum record size checks for * connection oriented transports. */ if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) { syslog(LOG_INFO, "unable to set max RPC record size"); } if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS, "netpath", "keyserv") == 0) { syslog(LOG_ERR, "%s: unable to create service for version %d\n", argv[0], KEY_VERS); exit(1); } if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS2, "netpath", "keyserv") == 0) { syslog(LOG_ERR, "%s: unable to create service for version %d\n", argv[0], KEY_VERS2); exit(1); } if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS3, "netpath", "keyserv") == 0) { syslog(LOG_ERR, "%s: unable to create service for version %d\n", argv[0], KEY_VERS3); exit(1); } if (!debugging) { detachfromtty(); } if (svc_create(keyprogram, KEY_PROG, KEY_VERS, "door") == 0) { syslog(LOG_ERR, "%s: unable to create service over doors for version %d\n", argv[0], KEY_VERS); exit(1); } if (svc_create(keyprogram, KEY_PROG, KEY_VERS2, "door") == 0) { syslog(LOG_ERR, "%s: unable to create service over doors for version %d\n", argv[0], KEY_VERS2); exit(1); } if (svc_create(keyprogram, KEY_PROG, KEY_VERS3, "door") == 0) { syslog(LOG_ERR, "%s: unable to create service over doors for version %d\n", argv[0], KEY_VERS3); exit(1); } svc_run(); abort(); /* NOTREACHED */ return (0); }
int main(int argc, char *argv[]) { pid_t pid; int c; char *progname = argv[0]; int connmaxrec = RPC_MAXDATASIZE; while ((c = getopt(argc, argv, "d")) != -1) switch ((char)c) { case 'd': debug++; break; default: (void) fprintf(stderr, "usage: %s [-d]\n", progname); exit(EXIT_FAILURE); } /* * Set non-blocking mode and maximum record size for * connection oriented RPC transports. */ if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) { msgout("unable to set maximum RPC record size"); } /* * If stdin looks like a TLI endpoint, we assume * that we were started by a port monitor. If * t_getstate fails with TBADF, this is not a * TLI endpoint. */ if (t_getstate(0) != -1 || t_errno != TBADF) { char *netid; struct netconfig *nconf = NULL; SVCXPRT *transp; int pmclose; if ((netid = getenv("NLSPROVIDER")) == NULL) { if (debug) msgout("cannot get transport name"); } else if ((nconf = getnetconfigent(netid)) == NULL) { if (debug) msgout("cannot get transport info"); } pmclose = (t_getstate(0) != T_DATAXFER); if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { msgout("cannot create server handle"); exit(EXIT_FAILURE); } if (nconf) freenetconfigent(nconf); if (!svc_reg(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, 0)) { msgout("unable to register (BOOTPARAMPROG, " "BOOTPARAMVERS)."); exit(EXIT_FAILURE); } if (pmclose) { (void) signal(SIGALRM, closedown); (void) alarm(_RPCSVC_CLOSEDOWN); } svc_run(); exit(EXIT_FAILURE); /* NOTREACHED */ } /* * run this process in the background only if it was started from * a shell and the debug flag was not given. */ if (!server_child && !debug) { pid = fork(); if (pid < 0) { perror("cannot fork"); exit(EXIT_FAILURE); } if (pid) exit(EXIT_SUCCESS); closefrom(0); (void) setsid(); } /* * messges go to syslog if the program was started by * another server, or if it was run from the command line without * the debug flag. */ if (server_child || !debug) openlog("bootparam_prot", LOG_PID, LOG_DAEMON); if (debug) { if (debug == 1) msgout("in debug mode."); else msgout("in debug mode (level %d).", debug); } if (!svc_create(bootparamprog_1, BOOTPARAMPROG, BOOTPARAMVERS, "netpath")) { msgout("unable to create (BOOTPARAMPROG, BOOTPARAMVERS) " "for netpath."); exit(EXIT_FAILURE); } svc_run(); msgout("svc_run returned"); return (EXIT_FAILURE); }
int main(int argc, char **argv) { struct sigaction sa; struct netconfig *nconf; void *nc_handle; in_port_t svcport; int ch, i, s; char *endptr, **hosts_bak; int have_v6 = 1; int maxrec = RPC_MAXDATASIZE; int attempt_cnt, port_len, port_pos, ret; char **port_list; while ((ch = getopt(argc, argv, "dh:p:")) != -1) switch (ch) { case 'd': debug = 1; break; case 'h': ++nhosts; hosts_bak = hosts; hosts_bak = realloc(hosts, nhosts * sizeof(char *)); if (hosts_bak == NULL) { if (hosts != NULL) { for (i = 0; i < nhosts; i++) free(hosts[i]); free(hosts); out_of_mem(); } } hosts = hosts_bak; hosts[nhosts - 1] = strdup(optarg); if (hosts[nhosts - 1] == NULL) { for (i = 0; i < (nhosts - 1); i++) free(hosts[i]); free(hosts); out_of_mem(); } break; case 'p': endptr = NULL; svcport = (in_port_t)strtoul(optarg, &endptr, 10); if (endptr == NULL || *endptr != '\0' || svcport == 0 || svcport >= IPPORT_MAX) usage(); svcport_str = strdup(optarg); break; default: usage(); } argc -= optind; argv += optind; (void)rpcb_unset(SM_PROG, SM_VERS, NULL); /* * Check if IPv6 support is present. */ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (s < 0) have_v6 = 0; else close(s); rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); /* * If no hosts were specified, add a wildcard entry to bind to * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the * list. */ if (nhosts == 0) { hosts = malloc(sizeof(char *)); if (hosts == NULL) out_of_mem(); hosts[0] = "*"; nhosts = 1; } else { hosts_bak = hosts; if (have_v6) { hosts_bak = realloc(hosts, (nhosts + 2) * sizeof(char *)); if (hosts_bak == NULL) { for (i = 0; i < nhosts; i++) free(hosts[i]); free(hosts); out_of_mem(); } else hosts = hosts_bak; nhosts += 2; hosts[nhosts - 2] = "::1"; } else { hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *)); if (hosts_bak == NULL) { for (i = 0; i < nhosts; i++) free(hosts[i]); free(hosts); out_of_mem(); } else { nhosts += 1; hosts = hosts_bak; } } hosts[nhosts - 1] = "127.0.0.1"; } attempt_cnt = 1; sock_fdcnt = 0; sock_fd = NULL; port_list = NULL; port_len = 0; nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { /* We want to listen only on udp6, tcp6, udp, tcp transports */ if (nconf->nc_flag & NC_VISIBLE) { /* Skip if there's no IPv6 support */ if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ } else { ret = create_service(nconf); if (ret == 1) /* Ignore this call */ continue; if (ret < 0) { /* * Failed to bind port, so close off * all sockets created and try again * if the port# was dynamically * assigned via bind(2). */ clearout_service(); if (mallocd_svcport != 0 && attempt_cnt < GETPORT_MAXTRY) { free(svcport_str); svcport_str = NULL; mallocd_svcport = 0; } else { errno = EADDRINUSE; syslog(LOG_ERR, "bindresvport_sa: %m"); exit(1); } /* Start over at the first service. */ free(sock_fd); sock_fdcnt = 0; sock_fd = NULL; nc_handle = setnetconfig(); attempt_cnt++; } else if (mallocd_svcport != 0 && attempt_cnt == GETPORT_MAXTRY) { /* * For the last attempt, allow * different port #s for each nconf * by saving the svcport_str and * setting it back to NULL. */ port_list = realloc(port_list, (port_len + 1) * sizeof(char *)); if (port_list == NULL) out_of_mem(); port_list[port_len++] = svcport_str; svcport_str = NULL; mallocd_svcport = 0; } } } } /* * Successfully bound the ports, so call complete_service() to * do the rest of the setup on the service(s). */ sock_fdpos = 0; port_pos = 0; nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { /* We want to listen only on udp6, tcp6, udp, tcp transports */ if (nconf->nc_flag & NC_VISIBLE) { /* Skip if there's no IPv6 support */ if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ } else if (port_list != NULL) { if (port_pos >= port_len) { syslog(LOG_ERR, "too many port#s"); exit(1); } complete_service(nconf, port_list[port_pos++]); } else complete_service(nconf, svcport_str); } } endnetconfig(nc_handle); free(sock_fd); if (port_list != NULL) { for (port_pos = 0; port_pos < port_len; port_pos++) free(port_list[port_pos]); free(port_list); } init_file("/var/db/statd.status"); /* Note that it is NOT sensible to run this program from inetd - the */ /* protocol assumes that it will run immediately at boot time. */ daemon(0, 0); openlog("rpc.statd", 0, LOG_DAEMON); if (debug) syslog(LOG_INFO, "Starting - debug enabled"); else syslog(LOG_INFO, "Starting"); /* Install signal handler to collect exit status of child processes */ sa.sa_handler = handle_sigchld; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGCHLD); sa.sa_flags = SA_RESTART; sigaction(SIGCHLD, &sa, NULL); /* Initialisation now complete - start operating */ notify_hosts(); /* Forks a process (if necessary) to do the */ /* SM_NOTIFY calls, which may be slow. */ svc_run(); /* Should never return */ exit(1); }
int main(int argc, char *argv[]) { struct netconfig *nconf; void *nc_handle; /* Net config handle */ struct rlimit rl; int maxrec = RPC_MAXDATASIZE; parseargs(argc, argv); /* Check that another rpcbind isn't already running. */ if ((rpcbindlockfd = (open(RPCBINDDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) err(1, "%s", RPCBINDDLOCK); if(flock(rpcbindlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) errx(1, "another rpcbind is already running. Aborting"); getrlimit(RLIMIT_NOFILE, &rl); if (rl.rlim_cur < 128) { if (rl.rlim_max <= 128) rl.rlim_cur = rl.rlim_max; else rl.rlim_cur = 128; setrlimit(RLIMIT_NOFILE, &rl); } openlog("rpcbind", LOG_CONS, LOG_DAEMON); if (geteuid()) { /* This command allowed only to root */ fprintf(stderr, "Sorry. You are not superuser\n"); exit(1); } /* * Make sure we use the local service file * for service lookkups */ __nss_configure_lookup("services", "files"); nc_handle = setnetconfig(); /* open netconfig file */ if (nc_handle == NULL) { syslog(LOG_ERR, "could not read /etc/netconfig"); exit(1); } nconf = getnetconfigent("local"); if (nconf == NULL) nconf = getnetconfigent("unix"); if (nconf == NULL) { syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]); exit(1); } rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); init_transport(nconf); while ((nconf = getnetconfig(nc_handle))) { if (nconf->nc_flag & NC_VISIBLE) init_transport(nconf); } endnetconfig(nc_handle); #ifdef PORTMAP if (!udptrans) udptrans = ""; if (!tcptrans) tcptrans = ""; #endif /* catch the usual termination signals for graceful exit */ (void) signal(SIGCHLD, reap); (void) signal(SIGINT, terminate); (void) signal(SIGTERM, terminate); (void) signal(SIGQUIT, terminate); /* ignore others that could get sent */ (void) signal(SIGPIPE, SIG_IGN); (void) signal(SIGHUP, SIG_IGN); (void) signal(SIGUSR1, SIG_IGN); (void) signal(SIGUSR2, SIG_IGN); if (debugging) { #ifdef RPCBIND_DEBUG printf("rpcbind debugging enabled."); if (doabort) { printf(" Will abort on errors!\n"); } else { printf("\n"); } #endif } else { if (daemon(0, 0)) err(1, "fork failed"); } if (runasdaemon || rpcbinduser) { struct passwd *p; char *id = runasdaemon ? RUN_AS : rpcbinduser; /* * Make sure we use the local password file * for these lookups. */ __nss_configure_lookup("passwd", "files"); if((p = getpwnam(id)) == NULL) { syslog(LOG_ERR, "cannot get uid of '%s': %m", id); exit(1); } if (setgid(p->pw_gid) == -1) { syslog(LOG_ERR, "setgid to '%s' (%d) failed: %m", id, p->pw_gid); exit(1); } if (setuid(p->pw_uid) == -1) { syslog(LOG_ERR, "setuid to '%s' (%d) failed: %m", id, p->pw_uid); exit(1); } } #ifdef WARMSTART if (warmstart) { read_warmstart(); } #endif network_init(); my_svc_run(); syslog(LOG_ERR, "svc_run returned unexpectedly"); rpcbind_abort(); /* NOTREACHED */ return 0; }
int main(int argc, char **argv) { int ch, i, s; void *nc_handle; char *endptr, **hosts_bak; struct sigaction sigalarm; int grace_period = 30; struct netconfig *nconf; int have_v6 = 1; int maxrec = RPC_MAXDATASIZE; in_port_t svcport = 0; int attempt_cnt, port_len, port_pos, ret; char **port_list; while ((ch = getopt(argc, argv, "d:g:h:p:")) != (-1)) { switch (ch) { case 'd': debug_level = atoi(optarg); if (!debug_level) { usage(); /* NOTREACHED */ } break; case 'g': grace_period = atoi(optarg); if (!grace_period) { usage(); /* NOTREACHED */ } break; case 'h': ++nhosts; hosts_bak = hosts; hosts_bak = realloc(hosts, nhosts * sizeof(char *)); if (hosts_bak == NULL) { if (hosts != NULL) { for (i = 0; i < nhosts; i++) free(hosts[i]); free(hosts); out_of_mem(); } } hosts = hosts_bak; hosts[nhosts - 1] = strdup(optarg); if (hosts[nhosts - 1] == NULL) { for (i = 0; i < (nhosts - 1); i++) free(hosts[i]); free(hosts); out_of_mem(); } break; case 'p': endptr = NULL; svcport = (in_port_t)strtoul(optarg, &endptr, 10); if (endptr == NULL || *endptr != '\0' || svcport == 0 || svcport >= IPPORT_MAX) usage(); svcport_str = strdup(optarg); break; default: case '?': usage(); /* NOTREACHED */ } } if (geteuid()) { /* This command allowed only to root */ fprintf(stderr, "Sorry. You are not superuser\n"); exit(1); } kernel_lockd = FALSE; kernel_lockd_client = FALSE; if (modfind("nfslockd") < 0) { if (kldload("nfslockd") < 0) { fprintf(stderr, "Can't find or load kernel support for rpc.lockd - using non-kernel implementation\n"); } else { kernel_lockd = TRUE; } } else { kernel_lockd = TRUE; } if (kernel_lockd) { if (getosreldate() >= 800040) kernel_lockd_client = TRUE; } (void)rpcb_unset(NLM_PROG, NLM_SM, NULL); (void)rpcb_unset(NLM_PROG, NLM_VERS, NULL); (void)rpcb_unset(NLM_PROG, NLM_VERSX, NULL); (void)rpcb_unset(NLM_PROG, NLM_VERS4, NULL); /* * Check if IPv6 support is present. */ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (s < 0) have_v6 = 0; else close(s); rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); /* * If no hosts were specified, add a wildcard entry to bind to * INADDR_ANY. Otherwise make sure 127.0.0.1 and ::1 are added to the * list. */ if (nhosts == 0) { hosts = malloc(sizeof(char**)); if (hosts == NULL) out_of_mem(); hosts[0] = "*"; nhosts = 1; } else { hosts_bak = hosts; if (have_v6) { hosts_bak = realloc(hosts, (nhosts + 2) * sizeof(char *)); if (hosts_bak == NULL) { for (i = 0; i < nhosts; i++) free(hosts[i]); free(hosts); out_of_mem(); } else hosts = hosts_bak; nhosts += 2; hosts[nhosts - 2] = "::1"; } else { hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *)); if (hosts_bak == NULL) { for (i = 0; i < nhosts; i++) free(hosts[i]); free(hosts); out_of_mem(); } else { nhosts += 1; hosts = hosts_bak; } } hosts[nhosts - 1] = "127.0.0.1"; } if (kernel_lockd) { if (!kernel_lockd_client) { /* * For the case where we have a kernel lockd but it * doesn't provide client locking, we run a cut-down * RPC service on a local-domain socket. The kernel's * RPC server will pass what it can't handle (mainly * client replies) down to us. */ struct sockaddr_un sun; int fd, oldmask; SVCXPRT *xprt; memset(&sun, 0, sizeof sun); sun.sun_family = AF_LOCAL; unlink(_PATH_RPCLOCKDSOCK); strcpy(sun.sun_path, _PATH_RPCLOCKDSOCK); sun.sun_len = SUN_LEN(&sun); fd = socket(AF_LOCAL, SOCK_STREAM, 0); if (!fd) { err(1, "Can't create local lockd socket"); } oldmask = umask(S_IXUSR|S_IRWXG|S_IRWXO); if (bind(fd, (struct sockaddr *) &sun, sun.sun_len) < 0) { err(1, "Can't bind local lockd socket"); } umask(oldmask); if (listen(fd, SOMAXCONN) < 0) { err(1, "Can't listen on local lockd socket"); } xprt = svc_vc_create(fd, RPC_MAXDATASIZE, RPC_MAXDATASIZE); if (!xprt) { err(1, "Can't create transport for local lockd socket"); } if (!svc_reg(xprt, NLM_PROG, NLM_VERS4, nlm_prog_4, NULL)) { err(1, "Can't register service for local lockd socket"); } } /* * We need to look up the addresses so that we can * hand uaddrs (ascii encoded address+port strings) to * the kernel. */ nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { /* We want to listen only on udp6, tcp6, udp, tcp transports */ if (nconf->nc_flag & NC_VISIBLE) { /* Skip if there's no IPv6 support */ if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ } else { lookup_addresses(nconf); } } } endnetconfig(nc_handle); } else { attempt_cnt = 1; sock_fdcnt = 0; sock_fd = NULL; port_list = NULL; port_len = 0; nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { /* We want to listen only on udp6, tcp6, udp, tcp transports */ if (nconf->nc_flag & NC_VISIBLE) { /* Skip if there's no IPv6 support */ if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ } else { ret = create_service(nconf); if (ret == 1) /* Ignore this call */ continue; if (ret < 0) { /* * Failed to bind port, so close * off all sockets created and * try again if the port# was * dynamically assigned via * bind(2). */ clearout_service(); if (mallocd_svcport != 0 && attempt_cnt < GETPORT_MAXTRY) { free(svcport_str); svcport_str = NULL; mallocd_svcport = 0; } else { errno = EADDRINUSE; syslog(LOG_ERR, "bindresvport_sa: %m"); exit(1); } /* * Start over at the first * service. */ free(sock_fd); sock_fdcnt = 0; sock_fd = NULL; nc_handle = setnetconfig(); attempt_cnt++; } else if (mallocd_svcport != 0 && attempt_cnt == GETPORT_MAXTRY) { /* * For the last attempt, allow * different port #s for each * nconf by saving the * svcport_str and setting it * back to NULL. */ port_list = realloc(port_list, (port_len + 1) * sizeof(char *)); if (port_list == NULL) out_of_mem(); port_list[port_len++] = svcport_str; svcport_str = NULL; mallocd_svcport = 0; } } } } /* * Successfully bound the ports, so call complete_service() to * do the rest of the setup on the service(s). */ sock_fdpos = 0; port_pos = 0; nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { /* We want to listen only on udp6, tcp6, udp, tcp transports */ if (nconf->nc_flag & NC_VISIBLE) { /* Skip if there's no IPv6 support */ if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ } else if (port_list != NULL) { if (port_pos >= port_len) { syslog(LOG_ERR, "too many port#s"); exit(1); } complete_service(nconf, port_list[port_pos++]); } else complete_service(nconf, svcport_str); } } endnetconfig(nc_handle); free(sock_fd); if (port_list != NULL) { for (port_pos = 0; port_pos < port_len; port_pos++) free(port_list[port_pos]); free(port_list); } } /* * Note that it is NOT sensible to run this program from inetd - the * protocol assumes that it will run immediately at boot time. */ if (daemon(0, debug_level > 0)) { err(1, "cannot fork"); /* NOTREACHED */ } openlog("rpc.lockd", 0, LOG_DAEMON); if (debug_level) syslog(LOG_INFO, "Starting, debug level %d", debug_level); else syslog(LOG_INFO, "Starting"); sigalarm.sa_handler = (sig_t) sigalarm_handler; sigemptyset(&sigalarm.sa_mask); sigalarm.sa_flags = SA_RESETHAND; /* should only happen once */ sigalarm.sa_flags |= SA_RESTART; if (sigaction(SIGALRM, &sigalarm, NULL) != 0) { syslog(LOG_WARNING, "sigaction(SIGALRM) failed: %s", strerror(errno)); exit(1); } if (kernel_lockd) { if (!kernel_lockd_client) { init_nsm(); client_pid = client_request(); /* * Create a child process to enter the kernel and then * wait for RPCs on our local domain socket. */ if (!fork()) nlm_syscall(debug_level, grace_period, naddrs, addrs); else svc_run(); } else { /* * The kernel lockd implementation provides * both client and server so we don't need to * do anything else. */ nlm_syscall(debug_level, grace_period, naddrs, addrs); } } else { grace_expired = 0; alarm(grace_period); init_nsm(); client_pid = client_request(); svc_run(); /* Should never return */ } exit(1); }
int rpcbind_main(void *arg) #endif { struct netconfig *nconf; void *nc_handle; /* Net config handle */ struct rlimit rl; int maxrec = RPC_MAXDATASIZE; #ifdef RPCBIND_RUMP svc_fdset_init(SVC_FDSET_MT); #else parseargs(argc, argv); #endif if (getrlimit(RLIMIT_NOFILE, &rl) == -1) err(EXIT_FAILURE, "getrlimit(RLIMIT_NOFILE)"); if (rl.rlim_cur < 128) { if (rl.rlim_max <= 128) rl.rlim_cur = rl.rlim_max; else rl.rlim_cur = 128; if (setrlimit(RLIMIT_NOFILE, &rl) < 0) err(EXIT_FAILURE, "setrlimit(RLIMIT_NOFILE)"); } nc_handle = setnetconfig(); /* open netconfig file */ if (nc_handle == NULL) errx(EXIT_FAILURE, "could not read /etc/netconfig"); #ifdef PORTMAP udptrans = ""; tcptrans = ""; #endif nconf = getnetconfigent("local"); if (nconf == NULL) errx(EXIT_FAILURE, "can't find local transport"); rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); init_transport(nconf); while ((nconf = getnetconfig(nc_handle))) { if (nconf->nc_flag & NC_VISIBLE) init_transport(nconf); } endnetconfig(nc_handle); /* catch the usual termination signals for graceful exit */ (void) signal(SIGCHLD, reap); (void) signal(SIGINT, terminate); (void) signal(SIGTERM, terminate); (void) signal(SIGQUIT, terminate); /* ignore others that could get sent */ (void) signal(SIGPIPE, SIG_IGN); #ifndef RPCBIND_RUMP (void) signal(SIGHUP, SIG_IGN); #endif (void) signal(SIGUSR1, SIG_IGN); (void) signal(SIGUSR2, SIG_IGN); #ifdef WARMSTART if (warmstart) { read_warmstart(); } #endif if (debugging) { printf("rpcbind debugging enabled."); if (doabort) { printf(" Will abort on errors!\n"); } else { printf("\n"); } } else { if (daemon(0, 0)) err(EXIT_FAILURE, "fork failed"); } openlog("rpcbind", 0, LOG_DAEMON); pidfile(NULL); if (runasdaemon) { struct passwd *p; if((p = getpwnam(RUN_AS)) == NULL) { syslog(LOG_ERR, "cannot get uid of daemon: %m"); exit(EXIT_FAILURE); } if (setuid(p->pw_uid) == -1) { syslog(LOG_ERR, "setuid to daemon failed: %m"); exit(EXIT_FAILURE); } } network_init(); #ifdef RPCBIND_RUMP sem_post(&gensem); #endif my_svc_run(); syslog(LOG_ERR, "svc_run returned unexpectedly"); rpcbind_abort(); /* NOTREACHED */ return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { pid_t pid; int i; int connmaxrec = RPC_MAXDATASIZE; /* * Set non-blocking mode and maximum record size for * connection oriented RPC transports. */ if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) { msgout("unable to set maximum RPC record size"); } /* * If stdin looks like a TLI endpoint, we assume * that we were started by a port monitor. If * t_getstate fails with TBADF, this is not a * TLI endpoint. */ if (t_getstate(0) != -1 || t_errno != TBADF) { char *netid; struct netconfig *nconf = NULL; SVCXPRT *transp; int pmclose; extern char *getenv(); _rpcpmstart = 1; openlog("rusers", LOG_PID, LOG_DAEMON); if ((netid = getenv("NLSPROVIDER")) == NULL) { #ifdef DEBUG msgout("cannot get transport name"); #endif } else if ((nconf = getnetconfigent(netid)) == NULL) { #ifdef DEBUG msgout("cannot get transport info"); #endif } if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) { msgout("cannot create server handle"); exit(1); } if (nconf) freenetconfigent(nconf); if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_3, rusers_service, 0)) { msgout("unable to register (RUSERSPROG, RUSERSVERS_3)."); exit(1); } if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_IDLE, rusers_service, 0)) { msgout("unable to register (RUSERSPROG, RUSERSVERS_IDLE)."); exit(1); } (void) signal(SIGALRM, closedown); (void) alarm(_RPCSVC_CLOSEDOWN); svc_run(); msgout("svc_run returned"); exit(1); /* NOTREACHED */ } #ifndef RPC_SVC_FG pid = fork(); if (pid < 0) { perror("rpc.rusersd: cannot fork"); exit(1); } if (pid) exit(0); for (i = 0; i < 20; i++) (void) close(i); setsid(); openlog("rusers", LOG_PID, LOG_DAEMON); #endif if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_3, "netpath")) { msgout("unable to create (RUSERSPROG, RUSERSVERS_3) for netpath"); exit(1); } if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_IDLE, "netpath")) { msgout( "unable to create (RUSERSPROG, RUSERSVERS_IDLE) for netpath"); exit(1); } svc_run(); msgout("svc_run returned"); return (1); }