1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Herb Hasler and Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 29 unchanged lines hidden (view full) --- 38 39#if 0 40#ifndef lint 41static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; 42#endif /*not lint*/ 43#endif 44 45#include <sys/cdefs.h> |
46__FBSDID("$FreeBSD: head/usr.sbin/mountd/mountd.c 158857 2006-05-23 17:10:17Z rodrigc $"); |
47 48#include <sys/param.h> 49#include <sys/mount.h> 50#include <sys/fcntl.h> 51#include <sys/stat.h> 52#include <sys/syslog.h> 53#include <sys/sysctl.h> 54#include <sys/linker.h> 55#include <sys/module.h> 56 57#include <rpc/rpc.h> 58#include <rpc/rpc_com.h> 59#include <rpc/pmap_clnt.h> 60#include <rpc/pmap_prot.h> 61#include <rpcsvc/mount.h> 62#include <nfs/rpcv2.h> 63#include <nfs/nfsproto.h> 64#include <nfsserver/nfs.h> |
65 66#include <arpa/inet.h> 67 68#include <ctype.h> 69#include <err.h> 70#include <errno.h> 71#include <grp.h> 72#include <libutil.h> 73#include <limits.h> 74#include <netdb.h> 75#include <pwd.h> 76#include <signal.h> 77#include <stdio.h> 78#include <stdlib.h> 79#include <string.h> 80#include <unistd.h> 81#include "pathnames.h" |
82#include "mntopts.h" |
83 84#ifdef DEBUG 85#include <stdarg.h> 86#endif 87 88/* 89 * Structures for keeping the mount list and export list 90 */ --- 864 unchanged lines hidden (view full) --- 955 * Get the export list 956 */ 957void 958get_exportlist() 959{ 960 struct exportlist *ep, *ep2; 961 struct grouplist *grp, *tgrp; 962 struct exportlist **epp; |
963 struct export_args export; |
964 struct dirlist *dirhead; |
965 struct iovec *iov; |
966 struct statfs fsb, *fsp; 967 struct xucred anon; 968 char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc; |
969 char errmsg[255]; |
970 int len, has_host, exflags, got_nondir, dirplen, num, i, netgrp; |
971 int iovlen; |
972 |
973 bzero(&export, sizeof(export)); 974 export.ex_flags = MNT_DELEXPORT; |
975 dirp = NULL; 976 dirplen = 0; |
977 iov = NULL; 978 iovlen = 0; 979 bzero(errmsg, sizeof(errmsg)); |
980 981 /* 982 * First, get rid of the old list 983 */ 984 ep = exphead; 985 while (ep) { 986 ep2 = ep; 987 ep = ep->ex_next; --- 11 unchanged lines hidden (view full) --- 999 1000 /* 1001 * And delete exports that are in the kernel for all local 1002 * filesystems. 1003 * XXX: Should know how to handle all local exportable filesystems 1004 * instead of just "ufs". 1005 */ 1006 num = getmntinfo(&fsp, MNT_NOWAIT); |
1007 1008 if (num > 0) { 1009 build_iovec(&iov, &iovlen, "fstype", NULL, 0); 1010 build_iovec(&iov, &iovlen, "fspath", NULL, 0); 1011 build_iovec(&iov, &iovlen, "from", NULL, 0); 1012 build_iovec(&iov, &iovlen, "update", NULL, 0); 1013 build_iovec(&iov, &iovlen, "export", &export, sizeof(export)); 1014 build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); 1015 } 1016 |
1017 for (i = 0; i < num; i++) { |
1018 1019 if (!strcmp(fsp->f_fstypename, "ufs") || 1020 !strcmp(fsp->f_fstypename, "msdosfs") || 1021 !strcmp(fsp->f_fstypename, "ntfs") || 1022 !strcmp(fsp->f_fstypename, "cd9660")) { |
1023 iov[1].iov_base = fsp->f_fstypename; 1024 iov[1].iov_len = strlen(fsp->f_fstypename) + 1; 1025 iov[3].iov_base = fsp->f_mntonname; 1026 iov[3].iov_len = strlen(fsp->f_mntonname) + 1; 1027 iov[5].iov_base = fsp->f_mntfromname; 1028 iov[5].iov_len = strlen(fsp->f_mntfromname) + 1; 1029 1030 /* 1031 * Kick out MNT_ROOTFS. It should not be passed from 1032 * userland to kernel. It should only be used 1033 * internally in the kernel. 1034 */ 1035 if (fsp->f_flags & MNT_ROOTFS) { 1036 fsp->f_flags &= ~MNT_ROOTFS; 1037 } 1038 1039 if (nmount(iov, iovlen, fsp->f_flags) < 0 && 1040 errno != ENOENT) { |
1041 syslog(LOG_ERR, |
1042 "can't delete exports for %s: %m %s", 1043 fsp->f_mntonname, errmsg); 1044 } |
1045 } 1046 fsp++; 1047 } 1048 |
1049 if (iov != NULL) { 1050 /* Free strings allocated by strdup() in getmntopts.c */ 1051 free(iov[0].iov_base); /* fstype */ 1052 free(iov[2].iov_base); /* fspath */ 1053 free(iov[4].iov_base); /* from */ 1054 free(iov[6].iov_base); /* update */ 1055 free(iov[8].iov_base); /* export */ 1056 free(iov[10].iov_base); /* errmsg */ 1057 1058 /* free iov, allocated by realloc() */ 1059 free(iov); 1060 iovlen = 0; 1061 } 1062 |
1063 /* 1064 * Read in the exports file and build the list, calling |
1065 * nmount() as we go along to push the export rules into the kernel. |
1066 */ 1067 if ((exp_file = fopen(exname, "r")) == NULL) { 1068 syslog(LOG_ERR, "can't open %s", exname); 1069 exit(2); 1070 } 1071 dirhead = (struct dirlist *)NULL; 1072 while (get_line()) { 1073 if (debug) --- 736 unchanged lines hidden (view full) --- 1810out_of_mem() 1811{ 1812 1813 syslog(LOG_ERR, "out of memory"); 1814 exit(2); 1815} 1816 1817/* |
1818 * Do the nmount() syscall with the update flag to push the export info into |
1819 * the kernel. 1820 */ 1821int |
1822do_mount(struct exportlist *ep, struct grouplist *grp, int exflags, 1823 struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb) |
1824{ 1825 struct statfs fsb1; 1826 struct addrinfo *ai; |
1827 struct export_args eap; 1828 char errmsg[255]; 1829 char *cp; |
1830 int done; |
1831 char savedc; 1832 struct iovec *iov; 1833 int iovlen; 1834 int ret; |
1835 |
1836 cp = NULL; 1837 savedc = '\0'; 1838 iov = NULL; 1839 iovlen = 0; 1840 ret = 0; |
1841 |
1842 bzero(&eap, sizeof(eap)); 1843 bzero(errmsg, sizeof(errmsg)); 1844 eap.ex_flags = exflags; 1845 eap.ex_anon = *anoncrp; 1846 eap.ex_indexfile = ep->ex_indexfile; |
1847 if (grp->gr_type == GT_HOST) 1848 ai = grp->gr_ptr.gt_addrinfo; 1849 else 1850 ai = NULL; 1851 done = FALSE; |
1852 1853 build_iovec(&iov, &iovlen, "fstype", NULL, 0); 1854 build_iovec(&iov, &iovlen, "fspath", NULL, 0); 1855 build_iovec(&iov, &iovlen, "from", NULL, 0); 1856 build_iovec(&iov, &iovlen, "update", NULL, 0); 1857 build_iovec(&iov, &iovlen, "export", &eap, sizeof(eap)); 1858 build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); 1859 |
1860 while (!done) { 1861 switch (grp->gr_type) { 1862 case GT_HOST: 1863 if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) 1864 goto skip; |
1865 eap.ex_addr = ai->ai_addr; 1866 eap.ex_addrlen = ai->ai_addrlen; 1867 eap.ex_masklen = 0; |
1868 break; 1869 case GT_NET: 1870 if (grp->gr_ptr.gt_net.nt_net.ss_family == AF_INET6 && 1871 have_v6 == 0) 1872 goto skip; |
1873 eap.ex_addr = |
1874 (struct sockaddr *)&grp->gr_ptr.gt_net.nt_net; |
1875 eap.ex_addrlen = 1876 ((struct sockaddr *)&grp->gr_ptr.gt_net.nt_net)->sa_len; 1877 eap.ex_mask = |
1878 (struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask; |
1879 eap.ex_masklen = ((struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask)->sa_len; |
1880 break; 1881 case GT_DEFAULT: |
1882 eap.ex_addr = NULL; 1883 eap.ex_addrlen = 0; 1884 eap.ex_mask = NULL; 1885 eap.ex_masklen = 0; |
1886 break; 1887 case GT_IGNORE: |
1888 ret = 0; 1889 goto error_exit; |
1890 break; 1891 default: 1892 syslog(LOG_ERR, "bad grouptype"); 1893 if (cp) 1894 *cp = savedc; |
1895 ret = 1; 1896 goto error_exit; |
1897 }; 1898 1899 /* 1900 * XXX: 1901 * Maybe I should just use the fsb->f_mntonname path instead 1902 * of looping back up the dirp to the mount point?? 1903 * Also, needs to know how to export all types of local 1904 * exportable filesystems and not just "ufs". 1905 */ |
1906 iov[1].iov_base = fsb->f_fstypename; /* "fstype" */ 1907 iov[1].iov_len = strlen(fsb->f_fstypename) + 1; 1908 iov[3].iov_base = fsb->f_mntonname; /* "fspath" */ 1909 iov[3].iov_len = strlen(fsb->f_mntonname) + 1; 1910 iov[5].iov_base = fsb->f_mntfromname; /* "from" */ 1911 iov[5].iov_len = strlen(fsb->f_mntfromname) + 1; 1912 1913 while (nmount(iov, iovlen, 0) < 0) { |
1914 if (cp) 1915 *cp-- = savedc; 1916 else 1917 cp = dirp + dirplen - 1; |
1918 if (opt_flags & OP_QUIET) { 1919 ret = 1; 1920 goto error_exit; 1921 } |
1922 if (errno == EPERM) { 1923 if (debug) 1924 warnx("can't change attributes for %s", 1925 dirp); 1926 syslog(LOG_ERR, 1927 "can't change attributes for %s", dirp); |
1928 ret = 1; 1929 goto error_exit; |
1930 } 1931 if (opt_flags & OP_ALLDIRS) { 1932 if (errno == EINVAL) 1933 syslog(LOG_ERR, 1934 "-alldirs requested but %s is not a filesystem mountpoint", 1935 dirp); 1936 else 1937 syslog(LOG_ERR, 1938 "could not remount %s: %m", 1939 dirp); |
1940 ret = 1; 1941 goto error_exit; |
1942 } 1943 /* back up over the last component */ 1944 while (*cp == '/' && cp > dirp) 1945 cp--; 1946 while (*(cp - 1) != '/' && cp > dirp) 1947 cp--; 1948 if (cp == dirp) { 1949 if (debug) 1950 warnx("mnt unsucc"); 1951 syslog(LOG_ERR, "can't export %s", dirp); |
1952 ret = 1; 1953 goto error_exit; |
1954 } 1955 savedc = *cp; 1956 *cp = '\0'; 1957 /* Check that we're still on the same filesystem. */ 1958 if (statfs(dirp, &fsb1) != 0 || bcmp(&fsb1.f_fsid, 1959 &fsb->f_fsid, sizeof(fsb1.f_fsid)) != 0) { 1960 *cp = savedc; 1961 syslog(LOG_ERR, "can't export %s", dirp); |
1962 ret = 1; 1963 goto error_exit; |
1964 } 1965 } 1966skip: 1967 if (ai != NULL) 1968 ai = ai->ai_next; 1969 if (ai == NULL) 1970 done = TRUE; 1971 } 1972 if (cp) 1973 *cp = savedc; |
1974error_exit: 1975 /* free strings allocated by strdup() in getmntopts.c */ 1976 if (iov != NULL) { 1977 free(iov[0].iov_base); /* fstype */ 1978 free(iov[2].iov_base); /* fspath */ 1979 free(iov[4].iov_base); /* from */ 1980 free(iov[6].iov_base); /* update */ 1981 free(iov[8].iov_base); /* export */ 1982 free(iov[10].iov_base); /* errmsg */ 1983 1984 /* free iov, allocated by realloc() */ 1985 free(iov); 1986 } 1987 return (ret); |
1988} 1989 1990/* 1991 * Translate a net address. 1992 * 1993 * If `maskflg' is nonzero, then `cp' is a netmask, not a network address. 1994 */ 1995int --- 608 unchanged lines hidden --- |