static void exports_update_one(nfs_export *exp, int verbose) { /* check mountpoint option */ if (exp->m_mayexport && exp->m_export.e_mountpoint && !is_mountpoint(exp->m_export.e_mountpoint[0]? exp->m_export.e_mountpoint: exp->m_export.e_path)) { printf("%s not exported as %s not a mountpoint.\n", exp->m_export.e_path, exp->m_export.e_mountpoint); exp->m_mayexport = 0; } if (exp->m_mayexport && ((exp->m_exported<1) || exp->m_changed)) { if (verbose) printf("%sexporting %s:%s to kernel\n", exp->m_exported ?"re":"", exp->m_client->m_hostname, exp->m_export.e_path); if (!export_export(exp)) error(exp, errno); } if (exp->m_exported && ! exp->m_mayexport) { if (verbose) printf("unexporting %s:%s from kernel\n", exp->m_client->m_hostname, exp->m_export.e_path); if (!export_unexport(exp)) error(exp, errno); } }
static struct nfs_fh_len * get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret, mountstat3 *error, int v3) { struct sockaddr_in *sin = nfs_getrpccaller_in(rqstp->rq_xprt); struct stat stb, estb; nfs_export *exp; struct nfs_fh_len *fh; char rpath[MAXPATHLEN+1]; char *p = *path; if (*p == '\0') p = "/"; /* Reload /var/lib/nfs/etab if necessary */ auth_reload(); /* Resolve symlinks */ if (realpath(p, rpath) != NULL) { rpath[sizeof (rpath) - 1] = '\0'; p = rpath; } /* Now authenticate the intruder... */ exp = auth_authenticate("mount", sin, p); if (!exp) { *error = NFSERR_ACCES; return NULL; } if (stat(p, &stb) < 0) { xlog(L_WARNING, "can't stat exported dir %s: %s", p, strerror(errno)); if (errno == ENOENT) *error = NFSERR_NOENT; else *error = NFSERR_ACCES; return NULL; } if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) { xlog(L_WARNING, "%s is not a directory or regular file", p); *error = NFSERR_NOTDIR; return NULL; } if (stat(exp->m_export.e_path, &estb) < 0) { xlog(L_WARNING, "can't stat export point %s: %s", p, strerror(errno)); *error = NFSERR_NOENT; return NULL; } if (estb.st_dev != stb.st_dev && (!new_cache || !(exp->m_export.e_flags & NFSEXP_CROSSMOUNT))) { xlog(L_WARNING, "request to export directory %s below nearest filesystem %s", p, exp->m_export.e_path); *error = NFSERR_ACCES; return NULL; } if (exp->m_export.e_mountpoint && !is_mountpoint(exp->m_export.e_mountpoint[0]? exp->m_export.e_mountpoint: exp->m_export.e_path)) { xlog(L_WARNING, "request to export an unmounted filesystem: %s", p); *error = NFSERR_NOENT; return NULL; } if (new_cache) { /* This will be a static private nfs_export with just one * address. We feed it to kernel then extract the filehandle, * */ if (cache_export(exp, p)) { *error = NFSERR_ACCES; return NULL; } fh = cache_get_filehandle(exp, v3?64:32, p); if (fh == NULL) { *error = NFSERR_ACCES; return NULL; } } else { int did_export = 0; retry: if (exp->m_exported<1) { export_export(exp); did_export = 1; } if (!exp->m_xtabent) xtab_append(exp); if (v3) fh = getfh_size ((struct sockaddr *) sin, p, 64); if (!v3 || (fh == NULL && errno == EINVAL)) { /* We first try the new nfs syscall. */ fh = getfh ((struct sockaddr *) sin, p); if (fh == NULL && errno == EINVAL) /* Let's try the old one. */ fh = getfh_old ((struct sockaddr *) sin, stb.st_dev, stb.st_ino); } if (fh == NULL && !did_export) { exp->m_exported = 0; goto retry; } if (fh == NULL) { xlog(L_WARNING, "getfh failed: %s", strerror(errno)); *error = NFSERR_ACCES; return NULL; } } *error = NFS_OK; mountlist_add(inet_ntoa(sin->sin_addr), p); if (expret) *expret = exp; return fh; }
int main(int argc, char *argv[]) { opt_type opts; int sig_number; #ifdef WITH_IPV6 int ipv4_only, ipv6_only; #endif unsigned char default_namespace = NAMESPACE_FILE; struct device_list *match_devices = NULL; struct unixsocket_list *unixsockets = NULL; struct mount_list *mounts = NULL; dev_t netdev; struct ip_connections *tcp_connection_list = NULL; struct ip_connections *udp_connection_list = NULL; #ifdef WITH_IPV6 struct ip6_connections *tcp6_connection_list = NULL; struct ip6_connections *udp6_connection_list = NULL; #endif struct inode_list *match_inodes = NULL; struct names *names_head, *this_name, *names_tail; int argc_cnt; char *current_argv, *option; char option_buf[3]; struct option *optr; char *nsptr; int skip_argv; struct option options[] = { {"all", 0, NULL, 'a'}, {"kill", 0, NULL, 'k'}, {"interactive", 0, NULL, 'i'}, {"list-signals", 0, NULL, 'l'}, {"mount", 0, NULL, 'm'}, {"ismountpoint", 0, NULL, 'M'}, {"namespace", 1, NULL, 'n'}, {"silent", 0, NULL, 's'}, {"user", 0, NULL, 'u'}, {"verbose", 0, NULL, 'v'}, {"version", 0, NULL, 'V'}, #ifdef WITH_IPV6 {"ipv4", 0, NULL, '4'}, {"ipv6", 0, NULL, '6'}, #endif { 0, 0, 0, 0 } }; #ifdef WITH_IPV6 ipv4_only = ipv6_only = 0; #endif names_head = this_name = names_tail = NULL; opts = 0; sig_number = SIGKILL; #ifdef ENABLE_NLS /* Set up the i18n */ setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif netdev = find_net_dev(); fill_unix_cache(&unixsockets); for (argc_cnt = 1; argc_cnt < argc; argc_cnt++) { current_argv = argv[argc_cnt]; if (current_argv[0] == '-') { /* its an option */ if (current_argv[1] == '-') { /* its a long option */ if (current_argv[2] == '\0') /* -- */ break; /* Parse the long options */ option = option_buf; for (optr = options; optr->name != NULL; optr++) { if (strcmp(current_argv+2,optr->name) == 0) { sprintf(option_buf, "-%c", (char)optr->val); break; } } if (optr->name == NULL) { fprintf(stderr, _("%s: Invalid option %s\n"), argv[0], current_argv); usage(NULL); } } else { option = current_argv; } skip_argv=0; while (*(++option) != '\0' && !skip_argv) { /* skips over the - */ switch (*option) { #ifdef WITH_IPV6 case '4': ipv4_only = 1; break; case '6': ipv6_only = 1; break; #endif /* WITH_IPV6 */ case 'a': opts |= OPT_ALLFILES; break; case 'c': opts |= OPT_MOUNTS; break; case 'f': /* ignored */ break; case 'h': usage(NULL); break; case 'i': opts |= OPT_INTERACTIVE; break; case 'k': opts |= OPT_KILL; break; case 'l': list_signals(); return 0; case 'm': opts |= OPT_MOUNTS; break; case 'M': opts |= OPT_ISMOUNTPOINT; read_proc_mounts(&mounts); break; case 'n': argc_cnt++; if (argc_cnt >= argc) { usage(_ ("Namespace option requires an argument.")); exit(1);; } skip_argv=1; //while(option != '\0') option++; if (strcmp(argv[argc_cnt], "tcp") == 0) default_namespace = NAMESPACE_TCP; else if (strcmp(argv[argc_cnt], "udp") == 0) default_namespace = NAMESPACE_UDP; else if (strcmp(argv[argc_cnt], "file") == 0) default_namespace = NAMESPACE_FILE; else usage(_("Invalid namespace name")); break; case 's': opts |= OPT_SILENT; break; case 'u': opts |= OPT_USER; break; case 'v': opts |= OPT_VERBOSE; break; case 'V': print_version(); return 0; default: if (isupper(*option) || isdigit(*option)) { sig_number = get_signal(current_argv+1, argv[0]); skip_argv=1; break; } fprintf(stderr, "%s: Invalid option %c\n", argv[0], *option); usage(NULL); exit(1); break; } /* switch */ } /* while option */ continue; } /* an option */ /* Not an option, must be a file specification */ if ((this_name = malloc(sizeof(struct names))) == NULL) continue; this_name->next = NULL; /* try to find namespace spec */ this_name->name_space = default_namespace; if (((nsptr = strchr(current_argv, '/')) != NULL) && (nsptr != current_argv)) { if (strcmp(nsptr + 1, "tcp") == 0) { this_name->name_space = NAMESPACE_TCP; *nsptr = '\0'; } else if (strcmp(nsptr + 1, "udp") == 0) { this_name->name_space = NAMESPACE_UDP; *nsptr = '\0'; } else if (strcmp(nsptr + 1, "file") == 0) { this_name->name_space = NAMESPACE_FILE; *nsptr = '\0'; } } this_name->matched_procs = NULL; if (opts & (OPT_MOUNTS|OPT_ISMOUNTPOINT) && this_name->name_space != NAMESPACE_FILE) usage(_ ("You can only use files with mountpoint options")); if (opts & OPT_ISMOUNTPOINT && !is_mountpoint(&mounts, current_argv)) { free(this_name); continue; } switch (this_name->name_space) { case NAMESPACE_TCP: if (asprintf(&(this_name->filename), "%s/tcp", current_argv) > 0) { #ifdef WITH_IPV6 parse_inet(this_name, ipv4_only, ipv6_only, &tcp_connection_list, &tcp6_connection_list); #else parse_inet(this_name, &tcp_connection_list); #endif } break; case NAMESPACE_UDP: if (asprintf(&(this_name->filename), "%s/udp", current_argv) > 0) { #ifdef WITH_IPV6 parse_inet(this_name, ipv4_only, ipv6_only, &udp_connection_list, &udp6_connection_list); #else parse_inet(this_name, &udp_connection_list); #endif } break; default: /* FILE */ this_name->filename = strdup(current_argv); if (parse_file(this_name, &match_inodes) == 0) { parse_unixsockets(this_name, &match_inodes, unixsockets); if (opts & OPT_MOUNTS) parse_mounts(this_name, &match_devices, opts); } break; } if (names_head == NULL) names_head = this_name; if (names_tail != NULL) names_tail->next = this_name; names_tail = this_name; } /* for across the argvs */ if (names_head == NULL) usage(_("No process specification given")); if (opts & OPT_SILENT) { opts &= ~OPT_VERBOSE; opts &= ~OPT_USER; if (opts & OPT_ALLFILES) usage(_ ("all option cannot be used with silent option.")); } #ifdef WITH_IPV6 if (ipv4_only && ipv6_only) usage(_ ("You cannot search for only IPv4 and only IPv6 sockets at the same time")); if (!ipv6_only) { #endif if (tcp_connection_list != NULL) find_net_sockets(&match_inodes, tcp_connection_list, "tcp", netdev); if (udp_connection_list != NULL) find_net_sockets(&match_inodes, udp_connection_list, "udp", netdev); #ifdef WITH_IPV6 } if (!ipv4_only) { if (tcp6_connection_list != NULL) find_net6_sockets(&match_inodes, tcp6_connection_list, "tcp", netdev); if (udp6_connection_list != NULL) find_net6_sockets(&match_inodes, udp6_connection_list, "udp", netdev); } #endif #ifdef DEBUG debug_match_lists(names_head, match_inodes, match_devices); #endif scan_procs(names_head, match_inodes, match_devices, unixsockets, netdev); scan_knfsd(names_head, match_inodes, match_devices); scan_mounts(names_head, match_inodes, match_devices); scan_swaps(names_head, match_inodes, match_devices); return print_matches(names_head, opts, sig_number); }