Beispiel #1
0
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);
	}
}
Beispiel #2
0
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);
}