int kld_load(const char *name) { if (kldload(name) == -1 && errno != EEXIST) return (-1); return (0); }
/* * Load a FreeBSD kernel module. * This is used by the DRI/DRM to load a DRM kernel module when * the X server starts. It could be used for other purposes in the future. * Input: * modName - name of the kernel module (Ex: "tdfx") * Return: * 0 for failure, 1 for success */ int xf86LoadKernelModule(const char *modName) { if (kldload(modName) != -1) return 1; else return 0; }
static int disc_setup(void) { struct ifreq ifr; int s; if (kldload("if_disc") < 0) { switch (errno) { case EEXIST: break; default: warn("disc_setup: kldload(if_disc)"); return (-1); } } s = socket(PF_INET, SOCK_RAW, 0); if (s < 0) { warn("disc_setup: socket(PF_INET, SOCK_RAW, 0)"); return (-1); } bzero(&ifr, sizeof(ifr)); snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", DISC_IFNAME, DISC_IFUNIT); if (ioctl(s, SIOCIFCREATE, &ifr) < 0) { warn("disc_setup: ioctl(%s, SIOCIFCREATE)", ifr.ifr_name); close(s); return (-1); } close(s); return (0); }
static int set_charset(struct iovec **iov, int *iovlen, const char *localcs) { int error; char *cs_disk; /* disk charset for Joliet cs conversion */ char *cs_local; /* local charset for Joliet cs conversion */ cs_disk = NULL; cs_local = NULL; if (modfind("cd9660_iconv") < 0) if (kldload("cd9660_iconv") < 0 || modfind("cd9660_iconv") < 0) { warnx( "cannot find or load \"cd9660_iconv\" kernel module"); return (-1); } if ((cs_disk = malloc(ICONV_CSNMAXLEN)) == NULL) return (-1); if ((cs_local = malloc(ICONV_CSNMAXLEN)) == NULL) { free(cs_disk); return (-1); } strncpy(cs_disk, ENCODING_UNICODE, ICONV_CSNMAXLEN); strncpy(cs_local, kiconv_quirkcs(localcs, KICONV_VENDOR_MICSFT), ICONV_CSNMAXLEN); error = kiconv_add_xlat16_cspairs(cs_disk, cs_local); if (error) return (-1); build_iovec(iov, iovlen, "cs_disk", cs_disk, (size_t)-1); build_iovec(iov, iovlen, "cs_local", cs_local, (size_t)-1); return (0); }
int load_kld(const char *kldname) { if (path_check(kldname) == 0) { return kldload(kldname); } return (-1); }
/* * Load the if_bridge.ko module in kernel if not already there. */ int bridge_kmod_load(void) { int fileid, modid; const char mod_name[] = "if_bridge"; struct module_stat mstat; /* Scan files in kernel. */ mstat.version = sizeof(struct module_stat); for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { /* Scan modules in file. */ for (modid = kldfirstmod(fileid); modid > 0; modid = modfnext(modid)) { if (modstat(modid, &mstat) < 0) continue; if (strcmp(mod_name, mstat.name) == 0) return (0); } } /* Not present - load it. */ if (kldload(mod_name) < 0) { syslog(LOG_ERR, "failed to load %s kernel module", mod_name); return (-1); } return (1); }
int main(int argc __unused, char *argv[]) { /* Prevent foot shooting. */ if (getpid() != 1) return (1); if (modfind("tmpfs") == -1 && kldload("tmpfs") == -1) die("error loading tmpfs"); /* Extract FreeBSD installation in a tmpfs. */ domount(tmpfs, sizeof(tmpfs) / sizeof(char *)); extract("/root.txz"); domount(devfs, sizeof(devfs) / sizeof(char *)); /* chroot() into system and continue boot process. */ if (chroot("/rw") != 0) die("chroot"); chdir("/"); /* Execute the real /sbin/init. */ execv(argv[0], argv); die("execv"); return (1); }
int set_charset(struct iovec **iov, int *iovlen, const char *cs_local, const char *cs_dos) { int error; if (modfind("msdosfs_iconv") < 0) if (kldload("msdosfs_iconv") < 0 || modfind("msdosfs_iconv") < 0) { warnx("cannot find or load \"msdosfs_iconv\" kernel module"); return (-1); } build_iovec_argf(iov, iovlen, "cs_win", ENCODING_UNICODE); error = kiconv_add_xlat16_cspairs(ENCODING_UNICODE, cs_local); if (error && errno != EEXIST) return (-1); if (cs_dos != NULL) { error = kiconv_add_xlat16_cspairs(cs_dos, cs_local); if (error && errno != EEXIST) return (-1); } else { build_iovec_argf(iov, iovlen, "cs_dos", cs_local); error = kiconv_add_xlat16_cspair(cs_local, cs_local, KICONV_FROM_UPPER | KICONV_LOWER); if (error && errno != EEXIST) return (-1); } return (0); }
int ID0kldload(const char *dev) { int result; ID0set0(); result = kldload(dev); log_Printf(LogID0, "%d = kldload(\"%s\")\n", result, dev); ID0setuser(); return result; }
void ifmaybeload(const char *name) { #ifndef __rtems__ #define MOD_PREFIX_LEN 3 /* "if_" */ struct module_stat mstat; int fileid, modid; char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp; const char *cp; /* loading suppressed by the user */ if (noload) return; /* trim the interface number off the end */ strlcpy(ifname, name, sizeof(ifname)); for (dp = ifname; *dp != 0; dp++) if (isdigit(*dp)) { *dp = 0; break; } /* turn interface and unit into module name */ strcpy(ifkind, "if_"); strlcpy(ifkind + MOD_PREFIX_LEN, ifname, sizeof(ifkind) - MOD_PREFIX_LEN); /* scan files in kernel */ mstat.version = sizeof(struct module_stat); for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { /* scan modules in file */ for (modid = kldfirstmod(fileid); modid > 0; modid = modfnext(modid)) { if (modstat(modid, &mstat) < 0) continue; /* strip bus name if present */ if ((cp = strchr(mstat.name, '/')) != NULL) { cp++; } else { cp = mstat.name; } /* already loaded? */ if (strncmp(ifname, cp, strlen(ifname) + 1) == 0 || strncmp(ifkind, cp, strlen(ifkind) + 1) == 0) return; } } /* not present, we should try to load it */ kldload(ifkind); #endif }
static int LoadModules(void) { const char *module[] = { "netgraph", "ng_socket", "ng_ether", "ng_pppoe" }; int f; for (f = 0; f < sizeof module / sizeof *module; f++) if (modfind(module[f]) == -1 && kldload(module[f]) == -1) { fprintf(stderr, "kldload: %s: %s\n", module[f], strerror(errno)); return 0; } return 1; }
int set_charset( char **cs_disk, char **cs_local, const char *localcs ) { int error; if ( modfind( "udf_iconv" ) < 0 ) if ( kldload( "udf_iconv" ) < 0 || modfind( "udf_iconv" ) < 0 ) { warnx( "cannot find or load \"udf_iconv\" kernel module" ); return ( -1 ); } if ( ( *cs_disk = malloc( ICONV_CSNMAXLEN ) ) == NULL ) return ( -1 ); if ( ( *cs_local = malloc( ICONV_CSNMAXLEN ) ) == NULL ) return ( -1 ); strncpy( *cs_disk, ENCODING_UNICODE, ICONV_CSNMAXLEN ); strncpy( *cs_local, localcs, ICONV_CSNMAXLEN ); error = kiconv_add_xlat16_cspairs( *cs_disk, *cs_local ); if ( error ) return ( -1 ); return ( 0 ); }
int ggate_drv_load() { if (modfind("g_gate") != -1) { /* Present in kernel. */ return 0; } if (kldload("geom_gate") == -1 || modfind("g_gate") == -1) { if (errno != EEXIST) { err("failed to load geom_gate module"); return -errno; } } return 0; }
/** * Load the MD driver if it isn't loaded already. */ static void mdmaybeload(void) { char name1[64], name2[64]; snprintf(name1, sizeof(name1), "g_%s", MD_NAME); snprintf(name2, sizeof(name2), "geom_%s", MD_NAME); if (modfind(name1) == -1) { /* Not present in kernel, try loading it. */ if (kldload(name2) == -1 || modfind(name1) == -1) { if (errno != EEXIST) { errx(EXIT_FAILURE, "%s module not available!", name2); } } } }
int main(int argc, char **argv) { int line, tokens; char buffer[BUFSIZ], *inputline, *token[GV_MAXARGS]; /* Load the module if necessary. */ if (modfind(GVINUMMOD) < 0) { if (kldload(GVINUMKLD) < 0 && modfind(GVINUMMOD) < 0) err(1, GVINUMKLD ": Kernel module not available"); } /* Arguments given on the command line. */ if (argc > 1) { argc--; argv++; parseline(argc, argv); /* Interactive mode. */ } else { for (;;) { inputline = readline("gvinum -> "); if (inputline == NULL) { if (ferror(stdin)) { err(1, "can't read input"); } else { printf("\n"); exit(0); } } else if (*inputline) { add_history(inputline); strcpy(buffer, inputline); free(inputline); line++; /* count the lines */ tokens = gv_tokenize(buffer, token, GV_MAXARGS); if (tokens) parseline(tokens, token); } } } exit(0); }
static void gcmd_createinsert(struct gctl_req *req, unsigned flags __unused) { const char *reqalgo; char name[64]; if (gctl_has_param(req, "algo")) reqalgo = gctl_get_ascii(req, "algo"); else reqalgo = GSCHED_ALGO; snprintf(name, sizeof(name), "gsched_%s", reqalgo); /* * Do not complain about errors here, gctl_issue() * will fail anyway. */ if (modfind(name) < 0) kldload(name); gctl_issue(req); }
void ifmaybeload(const char *name) { struct module_stat mstat; int fileid, modid; char ifkind[35], *dp; const char *cp; /* turn interface and unit into module name */ strcpy(ifkind, "if_"); for (cp = name, dp = ifkind + 3; (*cp != 0) && !isdigit(*cp); cp++, dp++) *dp = *cp; *dp = 0; /* scan files in kernel */ mstat.version = sizeof(struct module_stat); for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { /* scan modules in file */ for (modid = kldfirstmod(fileid); modid > 0; modid = modfnext(modid)) { if (modstat(modid, &mstat) < 0) continue; /* strip bus name if present */ if ((cp = strchr(mstat.name, '/')) != NULL) { cp++; } else { cp = mstat.name; } /* already loaded? */ if (strncmp(name, cp, strlen(cp)) == 0 || strncmp(ifkind, cp, strlen(cp)) == 0) return; } } /* not present, we should try to load it */ kldload(ifkind); }
int main(int ac, char *av[]) { int ch, res, rv, nread; size_t b_size = MIN_SIZE; char *buf, chb[READB_LEN]; fd_set fd_s; (void) setlocale(LC_TIME, ""); if (isatty(std_out)) opt_interactive = 1; else opt_interactive = 0; while ((ch = getopt(ac, av, "Wciotnf:")) != -1) switch (ch) { case 'W': opt_write = 1; break; case 'c': opt_reconn_close = 1; break; case 'i': opt_interactive = 1; break; case 'o': opt_reconn_oflow = 1; break; case 't': opt_timestamp = 1; break; case 'n': opt_no_switch = 1; break; case 'f': opt_snpdev = optarg; break; case '?': default: usage(); } if (modfind("snp") == -1) if (kldload("snp") == -1 || modfind("snp") == -1) warn("snp module not available"); signal(SIGINT, cleanup); snp_io = open_snp(); setup_scr(); if (*(av += optind) == NULL) { if (opt_interactive && !opt_no_switch) ask_dev(dev_name, MSG_INIT); else fatal(EX_DATAERR, "no device name given"); } else strncpy(dev_name, *av, DEV_NAME_LEN); set_dev(dev_name); if (!(buf = (char *) malloc(b_size))) fatal(EX_UNAVAILABLE, "malloc failed"); FD_ZERO(&fd_s); while (1) { if (opt_interactive) FD_SET(std_in, &fd_s); FD_SET(snp_io, &fd_s); res = select(snp_io + 1, &fd_s, NULL, NULL, NULL); if (opt_interactive && FD_ISSET(std_in, &fd_s)) { if ((res = ioctl(std_in, FIONREAD, &nread)) != 0) fatal(EX_OSERR, "ioctl(FIONREAD)"); if (nread > READB_LEN) nread = READB_LEN; rv = read(std_in, chb, nread); if (rv == -1 || rv != nread) fatal(EX_IOERR, "read (stdin) failed"); switch (chb[0]) { case CHR_CLEAR: clear(); break; case CHR_SWITCH: if (!opt_no_switch) { detach_snp(); ask_dev(dev_name, MSG_CHANGE); set_dev(dev_name); break; } default: if (opt_write) { rv = write(snp_io, chb, nread); if (rv == -1 || rv != nread) { detach_snp(); if (opt_no_switch) fatal(EX_IOERR, "write failed"); ask_dev(dev_name, MSG_NOWRITE); set_dev(dev_name); } } } } if (!FD_ISSET(snp_io, &fd_s)) continue; if ((res = ioctl(snp_io, FIONREAD, &nread)) != 0) fatal(EX_OSERR, "ioctl(FIONREAD)"); switch (nread) { case SNP_OFLOW: if (opt_reconn_oflow) attach_snp(); else if (opt_interactive && !opt_no_switch) { ask_dev(dev_name, MSG_OFLOW); set_dev(dev_name); } else cleanup(-1); break; case SNP_DETACH: case SNP_TTYCLOSE: if (opt_reconn_close) attach_snp(); else if (opt_interactive && !opt_no_switch) { ask_dev(dev_name, MSG_CLOSED); set_dev(dev_name); } else cleanup(-1); break; default: if (nread < (b_size / 2) && (b_size / 2) > MIN_SIZE) { free(buf); if (!(buf = (char *) malloc(b_size / 2))) fatal(EX_UNAVAILABLE, "malloc failed"); b_size = b_size / 2; } if (nread > b_size) { b_size = (nread % 2) ? (nread + 1) : (nread); free(buf); if (!(buf = (char *) malloc(b_size))) fatal(EX_UNAVAILABLE, "malloc failed"); } rv = read(snp_io, buf, nread); if (rv == -1 || rv != nread) fatal(EX_IOERR, "read failed"); rv = write(std_out, buf, nread); if (rv == -1 || rv != nread) fatal(EX_IOERR, "write failed"); } } /* While */ return(0); }
int main(int argc, char **argv) { int ch, debug = 0, error, iscsi_fd, maxproc = 30, retval, saved_errno, timeout = 60; bool dont_daemonize = false; struct pidfh *pidfh; pid_t pid, otherpid; const char *pidfile_path = DEFAULT_PIDFILE; struct iscsi_daemon_request request; while ((ch = getopt(argc, argv, "P:dl:m:t:")) != -1) { switch (ch) { case 'P': pidfile_path = optarg; break; case 'd': dont_daemonize = true; debug++; break; case 'l': debug = atoi(optarg); break; case 'm': maxproc = atoi(optarg); break; case 't': timeout = atoi(optarg); break; case '?': default: usage(); } } argc -= optind; if (argc != 0) usage(); log_init(debug); pidfh = pidfile_open(pidfile_path, 0600, &otherpid); if (pidfh == NULL) { if (errno == EEXIST) log_errx(1, "daemon already running, pid: %jd.", (intmax_t)otherpid); log_err(1, "cannot open or create pidfile \"%s\"", pidfile_path); } iscsi_fd = open(ISCSI_PATH, O_RDWR); if (iscsi_fd < 0 && errno == ENOENT) { saved_errno = errno; retval = kldload("iscsi"); if (retval != -1) iscsi_fd = open(ISCSI_PATH, O_RDWR); else errno = saved_errno; } if (iscsi_fd < 0) log_err(1, "failed to open %s", ISCSI_PATH); if (dont_daemonize == false) { if (daemon(0, 0) == -1) { log_warn("cannot daemonize"); pidfile_remove(pidfh); exit(1); } } pidfile_write(pidfh); register_sigchld(); for (;;) { log_debugx("waiting for request from the kernel"); memset(&request, 0, sizeof(request)); error = ioctl(iscsi_fd, ISCSIDWAIT, &request); if (error != 0) { if (errno == EINTR) { nchildren -= wait_for_children(false); assert(nchildren >= 0); continue; } log_err(1, "ISCSIDWAIT"); } if (dont_daemonize) { log_debugx("not forking due to -d flag; " "will exit after servicing a single request"); } else { nchildren -= wait_for_children(false); assert(nchildren >= 0); while (maxproc > 0 && nchildren >= maxproc) { log_debugx("maxproc limit of %d child processes hit; " "waiting for child process to exit", maxproc); nchildren -= wait_for_children(true); assert(nchildren >= 0); } log_debugx("incoming connection; forking child process #%d", nchildren); nchildren++; pid = fork(); if (pid < 0) log_err(1, "fork"); if (pid > 0) continue; } pidfile_close(pidfh); handle_request(iscsi_fd, &request, timeout); } return (0); }
/* * Nfs callback server daemon. * * 1 - do file descriptor and signal cleanup * 2 - fork the nfscbd(s) * 4 - create callback server socket(s) * 5 - set up server socket for rpc * * For connectionless protocols, just pass the socket into the kernel via. * nfssvc(). * For connection based sockets, loop doing accepts. When you get a new * socket from accept, pass the msgsock into the kernel via. nfssvc(). */ int main(int argc, char *argv[]) { struct nfscbd_args nfscbdargs; struct nfsd_nfscbd_args nfscbdargs2; struct sockaddr_in inetaddr, inetpeer; fd_set ready, sockbits; int ch, connect_type_cnt, len, maxsock, msgsock, error; int nfssvc_flag, on, sock, tcpsock, ret, mustfreeai = 0; char *cp, princname[128]; char myname[MAXHOSTNAMELEN], *myfqdnname = NULL; struct addrinfo *aip, hints; pid_t pid; short myport = NFSV4_CBPORT; if (modfind("nfscl") < 0) { /* Not present in kernel, try loading it */ if (kldload("nfscl") < 0 || modfind("nfscl") < 0) errx(1, "nfscl is not available"); } /* * First, get our fully qualified host name, if possible. */ if (gethostname(myname, MAXHOSTNAMELEN) >= 0) { cp = strchr(myname, '.'); if (cp != NULL && *(cp + 1) != '\0') { cp = myname; } else { /* * No domain on myname, so try looking it up. */ cp = NULL; memset((void *)&hints, 0, sizeof (hints)); hints.ai_flags = AI_CANONNAME; error = getaddrinfo(myname, NULL, &hints, &aip); if (error == 0) { if (aip->ai_canonname != NULL && (cp = strchr(aip->ai_canonname, '.')) != NULL && *(cp + 1) != '\0') { cp = aip->ai_canonname; mustfreeai = 1; } else { freeaddrinfo(aip); } } } if (cp == NULL) warnx("Can't get fully qualified host name"); myfqdnname = cp; } princname[0] = '\0'; #define GETOPT "p:P:" #define USAGE "[ -p port_num ] [ -P client_principal ]" while ((ch = getopt(argc, argv, GETOPT)) != -1) switch (ch) { case 'p': myport = atoi(optarg); if (myport < 1) { warnx("port# non-positive, reset to %d", NFSV4_CBPORT); myport = NFSV4_CBPORT; } break; case 'P': cp = optarg; if (cp != NULL && strlen(cp) > 0 && strlen(cp) < sizeof (princname)) { if (strchr(cp, '@') == NULL && myfqdnname != NULL) snprintf(princname, sizeof (princname), "%s@%s", cp, myfqdnname); else strlcpy(princname, cp, sizeof (princname)); } else { warnx("client princ invalid. ignored\n"); } break; default: case '?': usage(); }; argv += optind; argc -= optind; if (argc > 0) usage(); if (mustfreeai) freeaddrinfo(aip); nfscbdargs2.principal = (const char *)princname; if (debug == 0) { daemon(0, 0); (void)signal(SIGTERM, SIG_IGN); (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); } (void)signal(SIGSYS, nonfs); (void)signal(SIGCHLD, reapchild); openlog("nfscbd:", LOG_PID, LOG_DAEMON); pid = fork(); if (pid < 0) { syslog(LOG_ERR, "fork: %m"); nfscbd_exit(1); } else if (pid > 0) { children = pid; } else { (void)signal(SIGUSR1, child_cleanup); setproctitle("server"); nfssvc_flag = NFSSVC_NFSCBD; if (nfssvc(nfssvc_flag, &nfscbdargs2) < 0) { syslog(LOG_ERR, "nfssvc: %m"); nfscbd_exit(1); } exit(0); } (void)signal(SIGUSR1, cleanup); if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "can't create udp socket"); nfscbd_exit(1); } memset(&inetaddr, 0, sizeof inetaddr); inetaddr.sin_family = AF_INET; inetaddr.sin_addr.s_addr = INADDR_ANY; inetaddr.sin_port = htons(myport); inetaddr.sin_len = sizeof(inetaddr); ret = bind(sock, (struct sockaddr *)&inetaddr, sizeof(inetaddr)); /* If bind() fails, this is a restart, so just skip UDP. */ if (ret == 0) { len = sizeof(inetaddr); if (getsockname(sock, (struct sockaddr *)&inetaddr, &len) < 0){ syslog(LOG_ERR, "can't get bound addr"); nfscbd_exit(1); } nfscbdargs.port = ntohs(inetaddr.sin_port); if (nfscbdargs.port != myport) { syslog(LOG_ERR, "BAD PORT#"); nfscbd_exit(1); } nfscbdargs.sock = sock; nfscbdargs.name = NULL; nfscbdargs.namelen = 0; if (nfssvc(NFSSVC_CBADDSOCK, &nfscbdargs) < 0) { syslog(LOG_ERR, "can't Add UDP socket"); nfscbd_exit(1); } } (void)close(sock); /* Now set up the master server socket waiting for tcp connections. */ on = 1; FD_ZERO(&sockbits); connect_type_cnt = 0; if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR, "can't create tcp socket"); nfscbd_exit(1); } if (setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); /* sin_port is already set */ inetaddr.sin_family = AF_INET; inetaddr.sin_addr.s_addr = INADDR_ANY; inetaddr.sin_port = htons(myport); inetaddr.sin_len = sizeof(inetaddr); if (bind(tcpsock, (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { syslog(LOG_ERR, "can't bind tcp addr"); nfscbd_exit(1); } if (listen(tcpsock, 5) < 0) { syslog(LOG_ERR, "listen failed"); nfscbd_exit(1); } FD_SET(tcpsock, &sockbits); maxsock = tcpsock; connect_type_cnt++; setproctitle("master"); /* * Loop forever accepting connections and passing the sockets * into the kernel for the mounts. */ for (;;) { ready = sockbits; if (connect_type_cnt > 1) { if (select(maxsock + 1, &ready, NULL, NULL, NULL) < 1) { syslog(LOG_ERR, "select failed: %m"); nfscbd_exit(1); } } if (FD_ISSET(tcpsock, &ready)) { len = sizeof(inetpeer); if ((msgsock = accept(tcpsock, (struct sockaddr *)&inetpeer, &len)) < 0) { syslog(LOG_ERR, "accept failed: %m"); nfscbd_exit(1); } memset(inetpeer.sin_zero, 0, sizeof (inetpeer.sin_zero)); if (setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); nfscbdargs.sock = msgsock; nfscbdargs.name = (caddr_t)&inetpeer; nfscbdargs.namelen = sizeof(inetpeer); nfssvc(NFSSVC_CBADDSOCK, &nfscbdargs); (void)close(msgsock); } } }
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 main(int argc, char *argv[]) { int i, j; int error, fnd_dup, len, mustfreeai = 0, start_uidpos; struct nfsd_idargs nid; struct passwd *pwd; struct group *grp; int sock, one = 1; SVCXPRT *udptransp; u_short portnum; sigset_t signew; char hostname[MAXHOSTNAMELEN + 1], *cp; struct addrinfo *aip, hints; static uid_t check_dups[MAXUSERMAX]; if (modfind("nfscommon") < 0) { /* Not present in kernel, try loading it */ if (kldload("nfscommon") < 0 || modfind("nfscommon") < 0) errx(1, "Experimental nfs subsystem is not available"); } /* * First, figure out what our domain name and Kerberos Realm * seem to be. Command line args may override these later. */ if (gethostname(hostname, MAXHOSTNAMELEN) == 0) { if ((cp = strchr(hostname, '.')) != NULL && *(cp + 1) != '\0') { dnsname = cp + 1; } else { memset((void *)&hints, 0, sizeof (hints)); hints.ai_flags = AI_CANONNAME; error = getaddrinfo(hostname, NULL, &hints, &aip); if (error == 0) { if (aip->ai_canonname != NULL && (cp = strchr(aip->ai_canonname, '.')) != NULL && *(cp + 1) != '\0') { dnsname = cp + 1; mustfreeai = 1; } else { freeaddrinfo(aip); } } } } nid.nid_usermax = DEFUSERMAX; nid.nid_usertimeout = defusertimeout; argc--; argv++; while (argc >= 1) { if (!strcmp(*argv, "-domain")) { if (argc == 1) usage(); argc--; argv++; strncpy(hostname, *argv, MAXHOSTNAMELEN); hostname[MAXHOSTNAMELEN] = '\0'; dnsname = hostname; } else if (!strcmp(*argv, "-verbose")) { verbose = 1; } else if (!strcmp(*argv, "-force")) { forcestart = 1; } else if (!strcmp(*argv, "-usermax")) { if (argc == 1) usage(); argc--; argv++; i = atoi(*argv); if (i < MINUSERMAX || i > MAXUSERMAX) { fprintf(stderr, "usermax %d out of range %d<->%d\n", i, MINUSERMAX, MAXUSERMAX); usage(); } nid.nid_usermax = i; } else if (!strcmp(*argv, "-usertimeout")) { if (argc == 1) usage(); argc--; argv++; i = atoi(*argv); if (i < 0 || i > 100000) { fprintf(stderr, "usertimeout %d out of range 0<->100000\n", i); usage(); } nid.nid_usertimeout = defusertimeout = i * 60; } else if (nfsuserdcnt == -1) { nfsuserdcnt = atoi(*argv); if (nfsuserdcnt < 1) usage(); if (nfsuserdcnt > MAXNFSUSERD) { warnx("nfsuserd count %d; reset to %d", nfsuserdcnt, DEFNFSUSERD); nfsuserdcnt = DEFNFSUSERD; } } else { usage(); } argc--; argv++; } if (nfsuserdcnt < 1) nfsuserdcnt = DEFNFSUSERD; /* * Strip off leading and trailing '.'s in domain name and map * alphabetics to lower case. */ while (*dnsname == '.') dnsname++; if (*dnsname == '\0') errx(1, "Domain name all '.'"); len = strlen(dnsname); cp = dnsname + len - 1; while (*cp == '.') { *cp = '\0'; len--; cp--; } for (i = 0; i < len; i++) { if (!isascii(dnsname[i])) errx(1, "Domain name has non-ascii char"); if (isupper(dnsname[i])) dnsname[i] = tolower(dnsname[i]); } /* * If the nfsuserd died off ungracefully, this is necessary to * get them to start again. */ if (forcestart && nfssvc(NFSSVC_NFSUSERDDELPORT, NULL) < 0) errx(1, "Can't do nfssvc() to delete the port"); if (verbose) fprintf(stderr, "nfsuserd: domain=%s usermax=%d usertimeout=%d\n", dnsname, nid.nid_usermax, nid.nid_usertimeout); for (i = 0; i < nfsuserdcnt; i++) slaves[i] = (pid_t)-1; /* * Set up the service port to accept requests via UDP from * localhost (127.0.0.1). */ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) err(1, "cannot create udp socket"); /* * Not sure what this does, so I'll leave it here for now. */ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if ((udptransp = svcudp_create(sock)) == NULL) err(1, "Can't set up socket"); /* * By not specifying a protocol, it is linked into the * dispatch queue, but not registered with portmapper, * which is just what I want. */ if (!svc_register(udptransp, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, nfsuserdsrv, 0)) err(1, "Can't register nfsuserd"); /* * Tell the kernel what my port# is. */ portnum = htons(udptransp->xp_port); #ifdef DEBUG printf("portnum=0x%x\n", portnum); #else if (nfssvc(NFSSVC_NFSUSERDPORT, (caddr_t)&portnum) < 0) { if (errno == EPERM) { fprintf(stderr, "Can't start nfsuserd when already running"); fprintf(stderr, " If not running, use the -force option.\n"); } else { fprintf(stderr, "Can't do nfssvc() to add port\n"); } exit(1); } #endif pwd = getpwnam(defaultuser); if (pwd) nid.nid_uid = pwd->pw_uid; else nid.nid_uid = defaultuid; grp = getgrnam(defaultgroup); if (grp) nid.nid_gid = grp->gr_gid; else nid.nid_gid = defaultgid; nid.nid_name = dnsname; nid.nid_namelen = strlen(nid.nid_name); nid.nid_flag = NFSID_INITIALIZE; #ifdef DEBUG printf("Initialize uid=%d gid=%d dns=%s\n", nid.nid_uid, nid.nid_gid, nid.nid_name); #else error = nfssvc(NFSSVC_IDNAME, &nid); if (error) errx(1, "Can't initialize nfs user/groups"); #endif i = 0; /* * Loop around adding all groups. */ setgrent(); while (i < nid.nid_usermax && (grp = getgrent())) { nid.nid_gid = grp->gr_gid; nid.nid_name = grp->gr_name; nid.nid_namelen = strlen(grp->gr_name); nid.nid_flag = NFSID_ADDGID; #ifdef DEBUG printf("add gid=%d name=%s\n", nid.nid_gid, nid.nid_name); #else error = nfssvc(NFSSVC_IDNAME, &nid); if (error) errx(1, "Can't add group %s", grp->gr_name); #endif i++; } /* * Loop around adding all users. */ start_uidpos = i; setpwent(); while (i < nid.nid_usermax && (pwd = getpwent())) { fnd_dup = 0; /* * Yes, this is inefficient, but it is only done once when * the daemon is started and will run in a fraction of a second * for nid_usermax at 10000. If nid_usermax is cranked up to * 100000, it will take several seconds, depending on the CPU. */ for (j = 0; j < (i - start_uidpos); j++) if (check_dups[j] == pwd->pw_uid) { /* Found another entry for uid, so skip it */ fnd_dup = 1; break; } if (fnd_dup != 0) continue; check_dups[i - start_uidpos] = pwd->pw_uid; nid.nid_uid = pwd->pw_uid; nid.nid_name = pwd->pw_name; nid.nid_namelen = strlen(pwd->pw_name); nid.nid_flag = NFSID_ADDUID; #ifdef DEBUG printf("add uid=%d name=%s\n", nid.nid_uid, nid.nid_name); #else error = nfssvc(NFSSVC_IDNAME, &nid); if (error) errx(1, "Can't add user %s", pwd->pw_name); #endif i++; } /* * I should feel guilty for not calling this for all the above exit() * upon error cases, but I don't. */ if (mustfreeai) freeaddrinfo(aip); #ifdef DEBUG exit(0); #endif /* * Temporarily block SIGUSR1 and SIGCHLD, so slaves[] can't * end up bogus. */ sigemptyset(&signew); sigaddset(&signew, SIGUSR1); sigaddset(&signew, SIGCHLD); sigprocmask(SIG_BLOCK, &signew, NULL); daemon(0, 0); (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGTERM, SIG_IGN); (void)signal(SIGUSR1, cleanup_term); (void)signal(SIGCHLD, cleanup_term); openlog("nfsuserd:", LOG_PID, LOG_DAEMON); /* * Fork off the slave daemons that do the work. All the master * does is kill them off and cleanup. */ for (i = 0; i < nfsuserdcnt; i++) { slaves[i] = fork(); if (slaves[i] == 0) { im_a_slave = 1; setproctitle("slave"); sigemptyset(&signew); sigaddset(&signew, SIGUSR1); sigprocmask(SIG_UNBLOCK, &signew, NULL); /* * and away we go. */ svc_run(); syslog(LOG_ERR, "nfsuserd died: %m"); exit(1); } else if (slaves[i] < 0) { syslog(LOG_ERR, "fork: %m"); } } /* * Just wait for SIGUSR1 or a child to die and then... * As the Governor of California would say, "Terminate them". */ setproctitle("master"); sigemptyset(&signew); while (1) sigsuspend(&signew); }
int main(int argc, char *argv[]) { int ch, options = 0, action = CCD_CONFIG; while ((ch = getopt(argc, argv, "cCf:guUv")) != -1) { switch (ch) { case 'c': action = CCD_CONFIG; ++options; break; case 'C': action = CCD_CONFIGALL; ++options; break; case 'f': ccdconf = optarg; break; case 'g': action = CCD_DUMP; break; case 'u': action = CCD_UNCONFIG; ++options; break; case 'U': action = CCD_UNCONFIGALL; ++options; break; case 'v': verbose = 1; break; default: usage(); } } argc -= optind; argv += optind; if (options > 1) usage(); if (modfind("g_ccd") < 0) { /* Not present in kernel, try loading it */ if (kldload("geom_ccd") < 0 || modfind("g_ccd") < 0) warn("geom_ccd module not available!"); } switch (action) { case CCD_CONFIG: case CCD_UNCONFIG: exit(do_single(argc, argv, action)); /* NOTREACHED */ case CCD_CONFIGALL: case CCD_UNCONFIGALL: exit(do_all(action)); /* NOTREACHED */ case CCD_DUMP: exit(dump_ccd(argc, argv)); /* NOTREACHED */ } /* NOTREACHED */ return (0); }
/* * Create a socket type node and give it the supplied name. * Return data and control sockets corresponding to the node. * Returns -1 if error and sets errno. */ int NgMkSockNode(const char *name, int *csp, int *dsp) { char namebuf[NG_NODESIZ]; int cs = -1; /* control socket */ int ds = -1; /* data socket */ int errnosv; /* Empty name means no name */ if (name && *name == 0) name = NULL; /* Create control socket; this also creates the netgraph node. If we get an EPROTONOSUPPORT then the socket node type is not loaded, so load it and try again. */ if ((cs = socket(AF_NETGRAPH, SOCK_DGRAM, NG_CONTROL)) < 0) { if (errno == EPROTONOSUPPORT) { if (kldload(NG_SOCKET_KLD) < 0) { errnosv = errno; if (_gNgDebugLevel >= 1) NGLOG("can't load %s", NG_SOCKET_KLD); goto errout; } cs = socket(AF_NETGRAPH, SOCK_DGRAM, NG_CONTROL); if (cs >= 0) goto gotNode; } errnosv = errno; if (_gNgDebugLevel >= 1) NGLOG("socket"); goto errout; } gotNode: /* Assign the node the desired name, if any */ if (name != NULL) { u_char sbuf[NG_NODESIZ + NGSA_OVERHEAD]; struct sockaddr_ng *const sg = (struct sockaddr_ng *) sbuf; /* Assign name */ strlcpy(sg->sg_data, name, NG_NODESIZ); sg->sg_family = AF_NETGRAPH; sg->sg_len = strlen(sg->sg_data) + 1 + NGSA_OVERHEAD; if (bind(cs, (struct sockaddr *) sg, sg->sg_len) < 0) { errnosv = errno; if (_gNgDebugLevel >= 1) NGLOG("bind(%s)", sg->sg_data); goto errout; } /* Save node name */ strlcpy(namebuf, name, sizeof(namebuf)); } else if (dsp != NULL) { u_char rbuf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)]; struct ng_mesg *const resp = (struct ng_mesg *) rbuf; struct nodeinfo *const ni = (struct nodeinfo *) resp->data; /* Find out the node ID */ if (NgSendMsg(cs, ".", NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0) { errnosv = errno; if (_gNgDebugLevel >= 1) NGLOG("send nodeinfo"); goto errout; } if (NgRecvMsg(cs, resp, sizeof(rbuf), NULL) < 0) { errnosv = errno; if (_gNgDebugLevel >= 1) NGLOG("recv nodeinfo"); goto errout; } /* Save node "name" */ snprintf(namebuf, sizeof(namebuf), "[%lx]", (u_long) ni->id); } /* Create data socket if desired */ if (dsp != NULL) { u_char sbuf[NG_NODESIZ + 1 + NGSA_OVERHEAD]; struct sockaddr_ng *const sg = (struct sockaddr_ng *) sbuf; /* Create data socket, initially just "floating" */ if ((ds = socket(AF_NETGRAPH, SOCK_DGRAM, NG_DATA)) < 0) { errnosv = errno; if (_gNgDebugLevel >= 1) NGLOG("socket"); goto errout; } /* Associate the data socket with the node */ snprintf(sg->sg_data, NG_NODESIZ + 1, "%s:", namebuf); sg->sg_family = AF_NETGRAPH; sg->sg_len = strlen(sg->sg_data) + 1 + NGSA_OVERHEAD; if (connect(ds, (struct sockaddr *) sg, sg->sg_len) < 0) { errnosv = errno; if (_gNgDebugLevel >= 1) NGLOG("connect(%s)", sg->sg_data); goto errout; } } /* Return the socket(s) */ if (csp) *csp = cs; else close(cs); if (dsp) *dsp = ds; return (0); errout: /* Failed */ if (cs >= 0) close(cs); if (ds >= 0) close(ds); errno = errnosv; return (-1); }
int load_gre_module(void) { #if defined(__APPLE__) fprintf(stderr, "OSX, kextload GRE.kext\n"); int pid; if ((pid = fork()) < 0) return -1; if (pid == 0) { execle("/sbin/kextload", "kextload", "/Library/Extensions/GRE.kext", NULL, NULL); exit(EXIT_FAILURE); } while (waitpid(pid, 0, 0) < 0) { if (errno == EINTR) continue; return -1; } return 0; #else #if defined(__FreeBSD__) if (modfind("if_gre") < 0) { #ifdef DEBUG fprintf(stderr, "FreeBSD, kldload if_gre\n"); #endif if (kldload("if_gre") < 0) { perror("can't load if_gre"); return -1; } } return 0; #else #if defined(__linux__) fprintf(stderr, "Linux, insmod ip_gre\n"); int fd; if ((fd = open("/proc/modules", O_RDONLY)) < 0) { perror("open(\"proc/modules\")"); return -1; } int i; char buff[128]; bzero(buff, sizeof(buff)); while ((i = read(fd, buff, sizeof(buff) - 1)) > 0) { if (strstr(buff, "ip_gre")) { close(fd); return 0; } bzero(buff, sizeof(buff)); } close(fd); /* module ip_gre not found, try to load ip_gre */ fprintf(stderr, "load ip_gre...\n"); int pid; if ((pid = fork()) < 0) return -1; if (pid == 0) { execle("/sbin/modprobe", "modprobe", "ip_gre", NULL, NULL); execle("/sbin/insmod", "insmod", "ip_gre", NULL, NULL); exit(1); } while (waitpid(pid, 0, 0) < 0) { if (errno == EINTR) continue; return -1; } return 0; #else fprintf(stderr, "%s: Your OS is not supported yet\n", __FUNCTION__); return -1; #endif #endif #endif }
int main(int argc, char *argv[]) { int ch; struct xvfsconf vfc; int error; unsigned int iodmin, iodmax, num_servers; size_t len; error = getvfsbyname("nfs", &vfc); if (error) { if (kldload("nfs") == -1) err(1, "kldload(nfs)"); error = getvfsbyname("nfs", &vfc); } if (error) errx(1, "NFS support is not available in the running kernel"); num_servers = 0; while ((ch = getopt(argc, argv, "n:")) != -1) switch (ch) { case 'n': num_servers = atoi(optarg); if (num_servers < 1) { warnx("nfsiod count %u; reset to %d", num_servers, 1); num_servers = 1; } if (num_servers > MAXNFSDCNT) { warnx("nfsiod count %u; reset to %d", num_servers, MAXNFSDCNT); num_servers = MAXNFSDCNT; } break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc > 0) usage(); len = sizeof iodmin; error = sysctlbyname("vfs.nfs.iodmin", &iodmin, &len, NULL, 0); if (error < 0) err(1, "sysctlbyname(\"vfs.nfs.iodmin\")"); len = sizeof iodmax; error = sysctlbyname("vfs.nfs.iodmax", &iodmax, &len, NULL, 0); if (error < 0) err(1, "sysctlbyname(\"vfs.nfs.iodmax\")"); if (num_servers == 0) { /* no change */ printf("vfs.nfs.iodmin=%u\nvfs.nfs.iodmax=%u\n", iodmin, iodmax); exit(0); } /* Catch the case where we're lowering num_servers below iodmin */ if (iodmin > num_servers) { iodmin = num_servers; error = sysctlbyname("vfs.nfs.iodmin", NULL, 0, &iodmin, sizeof iodmin); if (error < 0) err(1, "sysctlbyname(\"vfs.nfs.iodmin\")"); } iodmax = num_servers; error = sysctlbyname("vfs.nfs.iodmax", NULL, 0, &iodmax, sizeof iodmax); if (error < 0) err(1, "sysctlbyname(\"vfs.nfs.iodmax\")"); exit (0); }
int main(int cc, char **vv) { int ch, disco; char *pname, *p, *q, *ta, *kw; isc_opt_t *op; FILE *fd; /* Try to load iscsi_initiator module before starting its operation */ if (modfind(INITIATORMOD) < 0) { if (kldload(INITIATORMOD) < 0 || modfind(INITIATORMOD) < 0) { perror(INITIATORMOD ": Error while handling kernel module"); return 1; } } op = &opvals; iscsidev = "/dev/"ISCSIDEV; fd = NULL; pname = vv[0]; if((p = strrchr(pname, '/')) != NULL) pname = p + 1; kw = ta = NULL; disco = 0; while((ch = getopt(cc, vv, OPTIONS)) != -1) { switch(ch) { case 'v': vflag++; break; case 'c': fd = fopen(optarg, "r"); if(fd == NULL) { perror(optarg); exit(1); } break; case 'd': disco = 1; break; case 't': ta = optarg; break; case 'n': kw = optarg; break; default: badu: fprintf(stderr, "Usage: %s %s\n", pname, USAGE); exit(1); } } if(fd == NULL) fd = fopen("/etc/iscsi.conf", "r"); if(fd != NULL) { parseConfig(fd, kw, op); fclose(fd); } cc -= optind; vv += optind; if(cc > 0) { if(vflag) printf("adding '%s'\n", *vv); parseArgs(cc, vv, op); } if(ta) op->targetAddress = ta; if(op->targetAddress == NULL) { fprintf(stderr, "No target!\n"); goto badu; } q = op->targetAddress; if(*q == '[' && (q = strchr(q, ']')) != NULL) { *q++ = '\0'; op->targetAddress++; } else q = op->targetAddress; if((p = strchr(q, ':')) != NULL) { *p++ = 0; op->port = atoi(p); p = strchr(p, ','); } if(p || ((p = strchr(q, ',')) != NULL)) { *p++ = 0; op->targetPortalGroupTag = atoi(p); } if(op->initiatorName == 0) { char hostname[256]; if(op->iqn) { if(gethostname(hostname, sizeof(hostname)) == 0) asprintf(&op->initiatorName, "%s:%s", op->iqn, hostname); else asprintf(&op->initiatorName, "%s:%d", op->iqn, (int)time(0) & 0xff); // XXX: } else { if(gethostname(hostname, sizeof(hostname)) == 0) asprintf(&op->initiatorName, "%s", hostname); else asprintf(&op->initiatorName, "%d", (int)time(0) & 0xff); // XXX: } } if(disco) { op->sessionType = "Discovery"; op->targetName = 0; } fsm(op); exit(0); }
int main(int argc, char *argv[], char *envp[]) { struct stat histstat; if (modfind(VINUMMOD) < 0) { /* need to load the vinum module */ if (kldload(VINUMMOD) < 0 || modfind(VINUMMOD) < 0) { perror(VINUMMOD ": Kernel module not available"); return 1; } } dateformat = getenv("VINUM_DATEFORMAT"); if (dateformat == NULL) dateformat = "%e %b %Y %H:%M:%S"; historyfile = getenv("VINUM_HISTORY"); if (historyfile == NULL) historyfile = DEFAULT_HISTORYFILE; if (stat(historyfile, &histstat) == 0) { /* history file exists */ if ((histstat.st_mode & S_IFMT) != S_IFREG) { fprintf(stderr, "Vinum history file %s must be a regular file\n", historyfile); exit(1); } } else if ((errno != ENOENT) /* not "not there", */ &&(errno != EROFS)) { /* and not read-only file system */ fprintf(stderr, "Can't open %s: %s (%d)\n", historyfile, strerror(errno), errno); exit(1); } hist = fopen(historyfile, "a+"); if (hist != NULL) { timestamp(); fprintf(hist, "*** " VINUMMOD " started ***\n"); fflush(hist); /* before we start the daemon */ } superdev = open(VINUM_SUPERDEV_NAME, O_RDWR); /* open vinum superdevice */ if (superdev < 0) { /* no go */ if (errno == ENODEV) { /* not configured, */ superdev = open(VINUM_WRONGSUPERDEV_NAME, O_RDWR); /* do we have a debug mismatch? */ if (superdev >= 0) { /* yup! */ #if VINUMDEBUG fprintf(stderr, "This program is compiled with debug support, but the kernel module does\n" "not have debug support. This program must be matched with the kernel\n" "module. Please alter /usr/src/sbin/" VINUMMOD "/Makefile and remove\n" "the option -DVINUMDEBUG from the CFLAGS definition, or alternatively\n" "edit /usr/src/sys/modules/" VINUMMOD "/Makefile and add the option\n" "-DVINUMDEBUG to the CFLAGS definition. Then rebuild the component\n" "of your choice with 'make clean all install'. If you rebuild the kernel\n" "module, you must stop " VINUMMOD " and restart it\n"); #else fprintf(stderr, "This program is compiled without debug support, but the kernel module\n" "includes debug support. This program must be matched with the kernel\n" "module. Please alter /usr/src/sbin/" VINUMMOD "/Makefile and add\n" "the option -DVINUMDEBUG to the CFLAGS definition, or alternatively\n" "edit /usr/src/sys/modules/" VINUMMOD "/Makefile and remove the option\n" "-DVINUMDEBUG from the CFLAGS definition. Then rebuild the component\n" "of your choice with 'make clean all install'. If you rebuild the kernel\n" "module, you must stop " VINUMMOD " and restart it\n"); #endif return 1; } } else if (errno == ENOENT) /* we don't have our node, */ make_devices(); /* create them first */ if (superdev < 0) { perror("Can't open " VINUM_SUPERDEV_NAME); return 1; } } /* Check if the dæmon is running. If not, start it in the * background */ start_daemon(); if (argc > 1) { /* we have a command on the line */ if (setjmp(command_fail) != 0) /* long jumped out */ return -1; parseline(argc - 1, &argv[1]); /* do it */ } else { /* * Catch a possible race condition which could cause us to * longjmp() into nowhere if we receive a SIGINT in the next few * lines. */ if (setjmp(command_fail)) /* come back here on catastrophic failure */ return 1; setsigs(); /* set signal handler */ for (;;) { /* ugh */ char *c; int childstatus; /* from wait4 */ if (setjmp(command_fail) == 2) /* come back here on catastrophic failure */ fprintf(stderr, "*** interrupted ***\n"); /* interrupted */ while (wait4(-1, &childstatus, WNOHANG, NULL) > 0); /* wait for all dead children */ c = readline(VINUMMOD " -> "); /* get an input */ if (c == NULL) { /* EOF or error */ if (ferror(stdin)) { fprintf(stderr, "Can't read input: %s (%d)\n", strerror(errno), errno); return 1; } else { /* EOF */ printf("\n"); return 0; } } else if (*c) { /* got something there */ add_history(c); /* save it in the history */ strcpy(buffer, c); /* put it where we can munge it */ free(c); line++; /* count the lines */ tokens = tokenize(buffer, token); /* got something potentially worth parsing */ if (tokens) parseline(tokens, token); /* and do what he says */ } if (hist) fflush(hist); } } return 0; /* normal completion */ }
/* * Nfs server daemon mostly just a user context for nfssvc() * * 1 - do file descriptor and signal cleanup * 2 - fork the nfsd(s) * 3 - create server socket(s) * 4 - register socket with rpcbind * * For connectionless protocols, just pass the socket into the kernel via. * nfssvc(). * For connection based sockets, loop doing accepts. When you get a new * socket from accept, pass the msgsock into the kernel via. nfssvc(). * The arguments are: * -r - reregister with rpcbind * -d - unregister with rpcbind * -t - support tcp nfs clients * -u - support udp nfs clients * -e - forces it to run a server that supports nfsv4 * followed by "n" which is the number of nfsds' to fork off */ int main(int argc, char **argv) { struct nfsd_addsock_args addsockargs; struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints; struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6; struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6; struct sockaddr_in inetpeer; struct sockaddr_in6 inet6peer; fd_set ready, sockbits; fd_set v4bits, v6bits; int ch, connect_type_cnt, i, maxsock, msgsock; socklen_t len; int on = 1, unregister, reregister, sock; int tcp6sock, ip6flag, tcpflag, tcpsock; int udpflag, ecode, error, s; int bindhostc, bindanyflag, rpcbreg, rpcbregcnt; int nfssvc_addsock; int longindex = 0; const char *lopt; char **bindhost = NULL; pid_t pid; nfsdcnt = DEFNFSDCNT; unregister = reregister = tcpflag = maxsock = 0; bindanyflag = udpflag = connect_type_cnt = bindhostc = 0; getopt_shortopts = "ah:n:rdtue"; getopt_usage = "usage:\n" " nfsd [-ardtue] [-h bindip]\n" " [-n numservers] [--minthreads #] [--maxthreads #]\n"; while ((ch = getopt_long(argc, argv, getopt_shortopts, longopts, &longindex)) != -1) switch (ch) { case 'a': bindanyflag = 1; break; case 'n': set_nfsdcnt(atoi(optarg)); break; case 'h': bindhostc++; bindhost = realloc(bindhost,sizeof(char *)*bindhostc); if (bindhost == NULL) errx(1, "Out of memory"); bindhost[bindhostc-1] = strdup(optarg); if (bindhost[bindhostc-1] == NULL) errx(1, "Out of memory"); break; case 'r': reregister = 1; break; case 'd': unregister = 1; break; case 't': tcpflag = 1; break; case 'u': udpflag = 1; break; case 'e': /* now a no-op, since this is the default */ break; case 0: lopt = longopts[longindex].name; if (!strcmp(lopt, "minthreads")) { minthreads = atoi(optarg); } else if (!strcmp(lopt, "maxthreads")) { maxthreads = atoi(optarg); } break; default: case '?': usage(); } if (!tcpflag && !udpflag) udpflag = 1; argv += optind; argc -= optind; if (minthreads_set && maxthreads_set && minthreads > maxthreads) errx(EX_USAGE, "error: minthreads(%d) can't be greater than " "maxthreads(%d)", minthreads, maxthreads); /* * XXX * Backward compatibility, trailing number is the count of daemons. */ if (argc > 1) usage(); if (argc == 1) set_nfsdcnt(atoi(argv[0])); /* * Unless the "-o" option was specified, try and run "nfsd". * If "-o" was specified, try and run "nfsserver". */ if (modfind("nfsd") < 0) { /* Not present in kernel, try loading it */ if (kldload("nfsd") < 0 || modfind("nfsd") < 0) errx(1, "NFS server is not available"); } ip6flag = 1; s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (s == -1) { if (errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT) err(1, "socket"); ip6flag = 0; } else if (getnetconfigent("udp6") == NULL || getnetconfigent("tcp6") == NULL) { ip6flag = 0; } if (s != -1) close(s); if (bindhostc == 0 || bindanyflag) { bindhostc++; bindhost = realloc(bindhost,sizeof(char *)*bindhostc); if (bindhost == NULL) errx(1, "Out of memory"); bindhost[bindhostc-1] = strdup("*"); if (bindhost[bindhostc-1] == NULL) errx(1, "Out of memory"); } if (unregister) { unregistration(); exit (0); } if (reregister) { if (udpflag) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); if (ecode != 0) err(1, "getaddrinfo udp: %s", gai_strerror(ecode)); nconf_udp = getnetconfigent("udp"); if (nconf_udp == NULL) err(1, "getnetconfigent udp failed"); nb_udp.buf = ai_udp->ai_addr; nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; if ((!rpcb_set(NFS_PROGRAM, 2, nconf_udp, &nb_udp)) || (!rpcb_set(NFS_PROGRAM, 3, nconf_udp, &nb_udp))) err(1, "rpcb_set udp failed"); freeaddrinfo(ai_udp); } if (udpflag && ip6flag) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); if (ecode != 0) err(1, "getaddrinfo udp6: %s", gai_strerror(ecode)); nconf_udp6 = getnetconfigent("udp6"); if (nconf_udp6 == NULL) err(1, "getnetconfigent udp6 failed"); nb_udp6.buf = ai_udp6->ai_addr; nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; if ((!rpcb_set(NFS_PROGRAM, 2, nconf_udp6, &nb_udp6)) || (!rpcb_set(NFS_PROGRAM, 3, nconf_udp6, &nb_udp6))) err(1, "rpcb_set udp6 failed"); freeaddrinfo(ai_udp6); } if (tcpflag) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp); if (ecode != 0) err(1, "getaddrinfo tcp: %s", gai_strerror(ecode)); nconf_tcp = getnetconfigent("tcp"); if (nconf_tcp == NULL) err(1, "getnetconfigent tcp failed"); nb_tcp.buf = ai_tcp->ai_addr; nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; if ((!rpcb_set(NFS_PROGRAM, 2, nconf_tcp, &nb_tcp)) || (!rpcb_set(NFS_PROGRAM, 3, nconf_tcp, &nb_tcp))) err(1, "rpcb_set tcp failed"); freeaddrinfo(ai_tcp); } if (tcpflag && ip6flag) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); if (ecode != 0) err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode)); nconf_tcp6 = getnetconfigent("tcp6"); if (nconf_tcp6 == NULL) err(1, "getnetconfigent tcp6 failed"); nb_tcp6.buf = ai_tcp6->ai_addr; nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; if ((!rpcb_set(NFS_PROGRAM, 2, nconf_tcp6, &nb_tcp6)) || (!rpcb_set(NFS_PROGRAM, 3, nconf_tcp6, &nb_tcp6))) err(1, "rpcb_set tcp6 failed"); freeaddrinfo(ai_tcp6); } exit (0); } if (debug == 0) { daemon(0, 0); (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); /* * nfsd sits in the kernel most of the time. It needs * to ignore SIGTERM/SIGQUIT in order to stay alive as long * as possible during a shutdown, otherwise loopback * mounts will not be able to unmount. */ (void)signal(SIGTERM, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); } (void)signal(SIGSYS, nonfs); (void)signal(SIGCHLD, reapchild); (void)signal(SIGUSR2, backup_stable); openlog("nfsd", LOG_PID | (debug ? LOG_PERROR : 0), LOG_DAEMON); /* * For V4, we open the stablerestart file and call nfssvc() * to get it loaded. This is done before the daemons do the * regular nfssvc() call to service NFS requests. * (This way the file remains open until the last nfsd is killed * off.) * It and the backup copy will be created as empty files * the first time this nfsd is started and should never be * deleted/replaced if at all possible. It should live on a * local, non-volatile storage device that does not do hardware * level write-back caching. (See SCSI doc for more information * on how to prevent write-back caching on SCSI disks.) */ open_stable(&stablefd, &backupfd); if (stablefd < 0) { syslog(LOG_ERR, "Can't open %s: %m\n", NFSD_STABLERESTART); exit(1); } /* This system call will fail for old kernels, but that's ok. */ nfssvc(NFSSVC_BACKUPSTABLE, NULL); if (nfssvc(NFSSVC_STABLERESTART, (caddr_t)&stablefd) < 0) { syslog(LOG_ERR, "Can't read stable storage file: %m\n"); exit(1); } nfssvc_addsock = NFSSVC_NFSDADDSOCK; nfssvc_nfsd = NFSSVC_NFSDNFSD; if (tcpflag) { /* * For TCP mode, we fork once to start the first * kernel nfsd thread. The kernel will add more * threads as needed. */ pid = fork(); if (pid == -1) { syslog(LOG_ERR, "fork: %m"); nfsd_exit(1); } if (pid) { children[0] = pid; } else { (void)signal(SIGUSR1, child_cleanup); setproctitle("server"); start_server(0); } } (void)signal(SIGUSR1, cleanup); FD_ZERO(&v4bits); FD_ZERO(&v6bits); FD_ZERO(&sockbits); rpcbregcnt = 0; /* Set up the socket for udp and rpcb register it. */ if (udpflag) { rpcbreg = 0; for (i = 0; i < bindhostc; i++) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; if (setbindhost(&ai_udp, bindhost[i], hints) == 0) { rpcbreg = 1; rpcbregcnt++; if ((sock = socket(ai_udp->ai_family, ai_udp->ai_socktype, ai_udp->ai_protocol)) < 0) { syslog(LOG_ERR, "can't create udp socket"); nfsd_exit(1); } if (bind(sock, ai_udp->ai_addr, ai_udp->ai_addrlen) < 0) { syslog(LOG_ERR, "can't bind udp addr %s: %m", bindhost[i]); nfsd_exit(1); } freeaddrinfo(ai_udp); addsockargs.sock = sock; addsockargs.name = NULL; addsockargs.namelen = 0; if (nfssvc(nfssvc_addsock, &addsockargs) < 0) { syslog(LOG_ERR, "can't Add UDP socket"); nfsd_exit(1); } (void)close(sock); } } if (rpcbreg == 1) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); if (ecode != 0) { syslog(LOG_ERR, "getaddrinfo udp: %s", gai_strerror(ecode)); nfsd_exit(1); } nconf_udp = getnetconfigent("udp"); if (nconf_udp == NULL) err(1, "getnetconfigent udp failed"); nb_udp.buf = ai_udp->ai_addr; nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; if ((!rpcb_set(NFS_PROGRAM, 2, nconf_udp, &nb_udp)) || (!rpcb_set(NFS_PROGRAM, 3, nconf_udp, &nb_udp))) err(1, "rpcb_set udp failed"); freeaddrinfo(ai_udp); } } /* Set up the socket for udp6 and rpcb register it. */ if (udpflag && ip6flag) { rpcbreg = 0; for (i = 0; i < bindhostc; i++) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) { rpcbreg = 1; rpcbregcnt++; if ((sock = socket(ai_udp6->ai_family, ai_udp6->ai_socktype, ai_udp6->ai_protocol)) < 0) { syslog(LOG_ERR, "can't create udp6 socket"); nfsd_exit(1); } if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof on) < 0) { syslog(LOG_ERR, "can't set v6-only binding for " "udp6 socket: %m"); nfsd_exit(1); } if (bind(sock, ai_udp6->ai_addr, ai_udp6->ai_addrlen) < 0) { syslog(LOG_ERR, "can't bind udp6 addr %s: %m", bindhost[i]); nfsd_exit(1); } freeaddrinfo(ai_udp6); addsockargs.sock = sock; addsockargs.name = NULL; addsockargs.namelen = 0; if (nfssvc(nfssvc_addsock, &addsockargs) < 0) { syslog(LOG_ERR, "can't add UDP6 socket"); nfsd_exit(1); } (void)close(sock); } } if (rpcbreg == 1) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); if (ecode != 0) { syslog(LOG_ERR, "getaddrinfo udp6: %s", gai_strerror(ecode)); nfsd_exit(1); } nconf_udp6 = getnetconfigent("udp6"); if (nconf_udp6 == NULL) err(1, "getnetconfigent udp6 failed"); nb_udp6.buf = ai_udp6->ai_addr; nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; if ((!rpcb_set(NFS_PROGRAM, 2, nconf_udp6, &nb_udp6)) || (!rpcb_set(NFS_PROGRAM, 3, nconf_udp6, &nb_udp6))) err(1, "rpcb_set udp6 failed"); freeaddrinfo(ai_udp6); } } /* Set up the socket for tcp and rpcb register it. */ if (tcpflag) { rpcbreg = 0; for (i = 0; i < bindhostc; i++) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) { rpcbreg = 1; rpcbregcnt++; if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR, "can't create tcp socket"); nfsd_exit(1); } if (setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); if (bind(tcpsock, ai_tcp->ai_addr, ai_tcp->ai_addrlen) < 0) { syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]); nfsd_exit(1); } if (listen(tcpsock, -1) < 0) { syslog(LOG_ERR, "listen failed"); nfsd_exit(1); } freeaddrinfo(ai_tcp); FD_SET(tcpsock, &sockbits); FD_SET(tcpsock, &v4bits); maxsock = tcpsock; connect_type_cnt++; } } if (rpcbreg == 1) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp); if (ecode != 0) { syslog(LOG_ERR, "getaddrinfo tcp: %s", gai_strerror(ecode)); nfsd_exit(1); } nconf_tcp = getnetconfigent("tcp"); if (nconf_tcp == NULL) err(1, "getnetconfigent tcp failed"); nb_tcp.buf = ai_tcp->ai_addr; nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; if ((!rpcb_set(NFS_PROGRAM, 2, nconf_tcp, &nb_tcp)) || (!rpcb_set(NFS_PROGRAM, 3, nconf_tcp, &nb_tcp))) err(1, "rpcb_set tcp failed"); freeaddrinfo(ai_tcp); } } /* Set up the socket for tcp6 and rpcb register it. */ if (tcpflag && ip6flag) { rpcbreg = 0; for (i = 0; i < bindhostc; i++) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) { rpcbreg = 1; rpcbregcnt++; if ((tcp6sock = socket(ai_tcp6->ai_family, ai_tcp6->ai_socktype, ai_tcp6->ai_protocol)) < 0) { syslog(LOG_ERR, "can't create tcp6 socket"); nfsd_exit(1); } if (setsockopt(tcp6sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); if (setsockopt(tcp6sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof on) < 0) { syslog(LOG_ERR, "can't set v6-only binding for tcp6 " "socket: %m"); nfsd_exit(1); } if (bind(tcp6sock, ai_tcp6->ai_addr, ai_tcp6->ai_addrlen) < 0) { syslog(LOG_ERR, "can't bind tcp6 addr %s: %m", bindhost[i]); nfsd_exit(1); } if (listen(tcp6sock, -1) < 0) { syslog(LOG_ERR, "listen failed"); nfsd_exit(1); } freeaddrinfo(ai_tcp6); FD_SET(tcp6sock, &sockbits); FD_SET(tcp6sock, &v6bits); if (maxsock < tcp6sock) maxsock = tcp6sock; connect_type_cnt++; } } if (rpcbreg == 1) { memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); if (ecode != 0) { syslog(LOG_ERR, "getaddrinfo tcp6: %s", gai_strerror(ecode)); nfsd_exit(1); } nconf_tcp6 = getnetconfigent("tcp6"); if (nconf_tcp6 == NULL) err(1, "getnetconfigent tcp6 failed"); nb_tcp6.buf = ai_tcp6->ai_addr; nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; if ((!rpcb_set(NFS_PROGRAM, 2, nconf_tcp6, &nb_tcp6)) || (!rpcb_set(NFS_PROGRAM, 3, nconf_tcp6, &nb_tcp6))) err(1, "rpcb_set tcp6 failed"); freeaddrinfo(ai_tcp6); } } if (rpcbregcnt == 0) { syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m"); nfsd_exit(1); } if (tcpflag && connect_type_cnt == 0) { syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m"); nfsd_exit(1); } setproctitle("master"); /* * We always want a master to have a clean way to to shut nfsd down * (with unregistration): if the master is killed, it unregisters and * kills all children. If we run for UDP only (and so do not have to * loop waiting waiting for accept), we instead make the parent * a "server" too. start_server will not return. */ if (!tcpflag) start_server(1); /* * Loop forever accepting connections and passing the sockets * into the kernel for the mounts. */ for (;;) { ready = sockbits; if (connect_type_cnt > 1) { if (select(maxsock + 1, &ready, NULL, NULL, NULL) < 1) { error = errno; if (error == EINTR) continue; syslog(LOG_ERR, "select failed: %m"); nfsd_exit(1); } } for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) { if (FD_ISSET(tcpsock, &ready)) { if (FD_ISSET(tcpsock, &v4bits)) { len = sizeof(inetpeer); if ((msgsock = accept(tcpsock, (struct sockaddr *)&inetpeer, &len)) < 0) { error = errno; syslog(LOG_ERR, "accept failed: %m"); if (error == ECONNABORTED || error == EINTR) continue; nfsd_exit(1); } memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); if (setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); addsockargs.sock = msgsock; addsockargs.name = (caddr_t)&inetpeer; addsockargs.namelen = len; nfssvc(nfssvc_addsock, &addsockargs); (void)close(msgsock); } else if (FD_ISSET(tcpsock, &v6bits)) { len = sizeof(inet6peer); if ((msgsock = accept(tcpsock, (struct sockaddr *)&inet6peer, &len)) < 0) { error = errno; syslog(LOG_ERR, "accept failed: %m"); if (error == ECONNABORTED || error == EINTR) continue; nfsd_exit(1); } if (setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt " "SO_KEEPALIVE: %m"); addsockargs.sock = msgsock; addsockargs.name = (caddr_t)&inet6peer; addsockargs.namelen = len; nfssvc(nfssvc_addsock, &addsockargs); (void)close(msgsock); } } } } }
int main(int argc, char *argv[]) { struct iovec *iov; unsigned int iovlen; struct smb_ctx sctx, *ctx = &sctx; struct stat st; #ifdef APPLE extern void dropsuid(); extern int loadsmbvfs(); #else struct xvfsconf vfc; #endif char *next, *p, *val; int opt, error, mntflags, caseopt, fd; uid_t uid; gid_t gid; mode_t dir_mode, file_mode; char errmsg[255] = { 0 }; iov = NULL; iovlen = 0; fd = 0; uid = (uid_t)-1; gid = (gid_t)-1; caseopt = 0; file_mode = 0; dir_mode = 0; #ifdef APPLE dropsuid(); #endif if (argc == 2) { if (strcmp(argv[1], "-h") == 0) { usage(); } } if (argc < 3) usage(); #ifdef APPLE error = loadsmbvfs(); #else error = getvfsbyname(smbfs_vfsname, &vfc); if (error) { if (kldload(smbfs_vfsname) < 0) err(EX_OSERR, "kldload(%s)", smbfs_vfsname); error = getvfsbyname(smbfs_vfsname, &vfc); } #endif if (error) errx(EX_OSERR, "SMB filesystem is not available"); if (smb_lib_init() != 0) exit(1); mntflags = error = 0; caseopt = SMB_CS_NONE; if (smb_ctx_init(ctx, argc, argv, SMBL_SHARE, SMBL_SHARE, SMB_ST_DISK) != 0) exit(1); if (smb_ctx_readrc(ctx) != 0) exit(1); if (smb_rc) rc_close(smb_rc); while ((opt = getopt(argc, argv, STDPARAM_OPT"c:d:f:g:l:n:o:u:w:")) != -1) { switch (opt) { case STDPARAM_ARGS: error = smb_ctx_opt(ctx, opt, optarg); if (error) exit(1); break; case 'u': { struct passwd *pwd; pwd = isdigit(optarg[0]) ? getpwuid(atoi(optarg)) : getpwnam(optarg); if (pwd == NULL) errx(EX_NOUSER, "unknown user '%s'", optarg); uid = pwd->pw_uid; break; } case 'g': { struct group *grp; grp = isdigit(optarg[0]) ? getgrgid(atoi(optarg)) : getgrnam(optarg); if (grp == NULL) errx(EX_NOUSER, "unknown group '%s'", optarg); gid = grp->gr_gid; break; } case 'd': errno = 0; dir_mode = strtol(optarg, &next, 8); if (errno || *next != 0) errx(EX_DATAERR, "invalid value for directory mode"); break; case 'f': errno = 0; file_mode = strtol(optarg, &next, 8); if (errno || *next != 0) errx(EX_DATAERR, "invalid value for file mode"); break; case '?': usage(); /*NOTREACHED*/ case 'n': { char *inp, *nsp; nsp = inp = optarg; while ((nsp = strsep(&inp, ",;:")) != NULL) { if (strcasecmp(nsp, "LONG") == 0) { build_iovec(&iov, &iovlen, "nolong", NULL, 0); } else { errx(EX_DATAERR, "unknown suboption '%s'", nsp); } } break; }; case 'o': getmntopts(optarg, mopts, &mntflags, 0); p = strchr(optarg, '='); val = NULL; if (p != NULL) { *p = '\0'; val = p + 1; } build_iovec(&iov, &iovlen, optarg, val, (size_t)-1); break; case 'c': switch (optarg[0]) { case 'l': caseopt |= SMB_CS_LOWER; break; case 'u': caseopt |= SMB_CS_UPPER; break; default: errx(EX_DATAERR, "invalid suboption '%c' for -c", optarg[0]); } break; default: usage(); } } if (optind == argc - 2) optind++; if (optind != argc - 1) usage(); realpath(argv[optind], mount_point); if (stat(mount_point, &st) == -1) err(EX_OSERR, "could not find mount point %s", mount_point); if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; err(EX_OSERR, "can't mount on %s", mount_point); } /* if (smb_getextattr(mount_point, &einfo) == 0) errx(EX_OSERR, "can't mount on %s twice", mount_point); */ if (uid == (uid_t)-1) uid = st.st_uid; if (gid == (gid_t)-1) gid = st.st_gid; if (file_mode == 0 ) file_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); if (dir_mode == 0) { dir_mode = file_mode; if (dir_mode & S_IRUSR) dir_mode |= S_IXUSR; if (dir_mode & S_IRGRP) dir_mode |= S_IXGRP; if (dir_mode & S_IROTH) dir_mode |= S_IXOTH; } /* * For now, let connection be private for this mount */ ctx->ct_ssn.ioc_opt |= SMBVOPT_PRIVATE; ctx->ct_ssn.ioc_owner = ctx->ct_sh.ioc_owner = 0; /* root */ ctx->ct_ssn.ioc_group = ctx->ct_sh.ioc_group = gid; opt = 0; if (dir_mode & S_IXGRP) opt |= SMBM_EXECGRP; if (dir_mode & S_IXOTH) opt |= SMBM_EXECOTH; ctx->ct_ssn.ioc_rights |= opt; ctx->ct_sh.ioc_rights |= opt; error = smb_ctx_resolve(ctx); if (error) exit(1); error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE); if (error) { exit(1); } fd = ctx->ct_fd; build_iovec(&iov, &iovlen, "fstype", strdup("smbfs"), -1); build_iovec(&iov, &iovlen, "fspath", mount_point, -1); build_iovec_argf(&iov, &iovlen, "fd", "%d", fd); build_iovec(&iov, &iovlen, "mountpoint", mount_point, -1); build_iovec_argf(&iov, &iovlen, "uid", "%d", uid); build_iovec_argf(&iov, &iovlen, "gid", "%d", gid); build_iovec_argf(&iov, &iovlen, "file_mode", "%d", file_mode); build_iovec_argf(&iov, &iovlen, "dir_mode", "%d", dir_mode); build_iovec_argf(&iov, &iovlen, "caseopt", "%d", caseopt); build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof errmsg); error = nmount(iov, iovlen, mntflags); smb_ctx_done(ctx); if (error) { smb_error("mount error: %s %s", error, mount_point, errmsg); exit(1); } return 0; }