View | Details | Raw Unified | Return to bug 237860 | Differences between
and this patch

Collapse All | Expand All

(-)usr.sbin/mountd/mountd.c (-141 / +577 lines)
Lines 49-54 __FBSDID("$FreeBSD: head/usr.sbin/mountd Link Here
49
49
50
#include <sys/param.h>
50
#include <sys/param.h>
51
#include <sys/fcntl.h>
51
#include <sys/fcntl.h>
52
#include <sys/fnv_hash.h>
52
#include <sys/linker.h>
53
#include <sys/linker.h>
53
#include <sys/module.h>
54
#include <sys/module.h>
54
#include <sys/mount.h>
55
#include <sys/mount.h>
Lines 114-123 struct dirlist { Link Here
114
struct exportlist {
115
struct exportlist {
115
	struct dirlist	*ex_dirl;
116
	struct dirlist	*ex_dirl;
116
	struct dirlist	*ex_defdir;
117
	struct dirlist	*ex_defdir;
118
	struct grouplist *ex_grphead;
117
	int		ex_flag;
119
	int		ex_flag;
118
	fsid_t		ex_fs;
120
	fsid_t		ex_fs;
119
	char		*ex_fsdir;
121
	char		*ex_fsdir;
120
	char		*ex_indexfile;
122
	char		*ex_indexfile;
123
	struct xucred	ex_defanon;
124
	int		ex_defexflags;
121
	int		ex_numsecflavors;
125
	int		ex_numsecflavors;
122
	int		ex_secflavors[MAXSECFLAVORS];
126
	int		ex_secflavors[MAXSECFLAVORS];
123
	int		ex_defnumsecflavors;
127
	int		ex_defnumsecflavors;
Lines 127-132 struct exportlist { Link Here
127
};
131
};
128
/* ex_flag bits */
132
/* ex_flag bits */
129
#define	EX_LINKED	0x1
133
#define	EX_LINKED	0x1
134
#define	EX_DONE		0x2
135
#define	EX_DEFSET	0x4
136
137
SLIST_HEAD(exportlisthead, exportlist);
130
138
131
struct netmsk {
139
struct netmsk {
132
	struct sockaddr_storage nt_net;
140
	struct sockaddr_storage nt_net;
Lines 143-148 struct grouplist { Link Here
143
	int gr_type;
151
	int gr_type;
144
	union grouptypes gr_ptr;
152
	union grouptypes gr_ptr;
145
	struct grouplist *gr_next;
153
	struct grouplist *gr_next;
154
	struct xucred gr_anon;
155
	int gr_exflags;
156
	int gr_flag;
146
	int gr_numsecflavors;
157
	int gr_numsecflavors;
147
	int gr_secflavors[MAXSECFLAVORS];
158
	int gr_secflavors[MAXSECFLAVORS];
148
};
159
};
Lines 153-158 struct grouplist { Link Here
153
#define	GT_DEFAULT	0x3
164
#define	GT_DEFAULT	0x3
154
#define GT_IGNORE	0x5
165
#define GT_IGNORE	0x5
155
166
167
/* Group flags */
168
#define	GR_FND		0x1
169
156
struct hostlist {
170
struct hostlist {
157
	int		 ht_flag;	/* Uses DP_xx bits */
171
	int		 ht_flag;	/* Uses DP_xx bits */
158
	struct grouplist *ht_grp;
172
	struct grouplist *ht_grp;
Lines 172-178 struct fhreturn { Link Here
172
/* Global defs */
186
/* Global defs */
173
static char	*add_expdir(struct dirlist **, char *, int);
187
static char	*add_expdir(struct dirlist **, char *, int);
174
static void	add_dlist(struct dirlist **, struct dirlist *,
188
static void	add_dlist(struct dirlist **, struct dirlist *,
175
		    struct grouplist *, int, struct exportlist *);
189
		    struct grouplist *, int, struct exportlist *,
190
		    struct xucred *, int);
176
static void	add_mlist(char *, char *);
191
static void	add_mlist(char *, char *);
177
static int	check_dirpath(char *);
192
static int	check_dirpath(char *);
178
static int	check_options(struct dirlist *);
193
static int	check_options(struct dirlist *);
Lines 185-201 static void complete_service(struct netc Link Here
185
static void	clearout_service(void);
200
static void	clearout_service(void);
186
static void	del_mlist(char *hostp, char *dirp);
201
static void	del_mlist(char *hostp, char *dirp);
187
static struct dirlist	*dirp_search(struct dirlist *, char *);
202
static struct dirlist	*dirp_search(struct dirlist *, char *);
203
static int	do_export_mount(struct exportlist *, struct statfs *);
188
static int	do_mount(struct exportlist *, struct grouplist *, int,
204
static int	do_mount(struct exportlist *, struct grouplist *, int,
189
		    struct xucred *, char *, int, struct statfs *);
205
		    struct xucred *, char *, int, struct statfs *, int, int *);
190
static int	do_opt(char **, char **, struct exportlist *,
206
static int	do_opt(char **, char **, struct exportlist *,
191
		    struct grouplist *, int *, int *, struct xucred *);
207
		    struct grouplist *, int *, int *, struct xucred *);
192
static struct exportlist	*ex_search(fsid_t *);
208
static struct exportlist	*ex_search(fsid_t *, struct exportlisthead *);
193
static struct exportlist	*get_exp(void);
209
static struct exportlist	*get_exp(void);
194
static void	free_dir(struct dirlist *);
210
static void	free_dir(struct dirlist *);
195
static void	free_exp(struct exportlist *);
211
static void	free_exp(struct exportlist *);
196
static void	free_grp(struct grouplist *);
212
static void	free_grp(struct grouplist *);
197
static void	free_host(struct hostlist *);
213
static void	free_host(struct hostlist *);
198
static void	get_exportlist(void);
214
static void	free_v4rootexp(void);
215
static void	get_exportlist_one(int);
216
static void	get_exportlist(int);
217
static void	insert_exports(struct exportlist *, struct exportlisthead *);
218
static void	free_exports(struct exportlisthead *);
219
static void	read_exportfile(int);
220
static int	compare_nmount_exportlist(struct iovec *, int, char *);
221
static int	compare_export(struct exportlist *, struct exportlist *);
222
static int	compare_cred(struct xucred *, struct xucred *);
223
static int	compare_secflavor(int *, int *, int);
224
static void	delete_export(struct iovec *, int, struct statfs *, char *);
199
static int	get_host(char *, struct grouplist *, struct grouplist *);
225
static int	get_host(char *, struct grouplist *, struct grouplist *);
200
static struct hostlist *get_ht(void);
226
static struct hostlist *get_ht(void);
201
static int	get_line(void);
227
static int	get_line(void);
Lines 204-210 static int get_net(char *, struct netmsk Link Here
204
static void	getexp_err(struct exportlist *, struct grouplist *, const char *);
230
static void	getexp_err(struct exportlist *, struct grouplist *, const char *);
205
static struct grouplist	*get_grp(void);
231
static struct grouplist	*get_grp(void);
206
static void	hang_dirp(struct dirlist *, struct grouplist *,
232
static void	hang_dirp(struct dirlist *, struct grouplist *,
207
				struct exportlist *, int);
233
		    struct exportlist *, int, struct xucred *, int);
208
static void	huphandler(int sig);
234
static void	huphandler(int sig);
209
static int	makemask(struct sockaddr_storage *ssp, int bitlen);
235
static int	makemask(struct sockaddr_storage *ssp, int bitlen);
210
static void	mntsrv(struct svc_req *, SVCXPRT *);
236
static void	mntsrv(struct svc_req *, SVCXPRT *);
Lines 227-235 static int xdr_fhs(XDR *, caddr_t); Link Here
227
static int	xdr_mlist(XDR *, caddr_t);
253
static int	xdr_mlist(XDR *, caddr_t);
228
static void	terminate(int);
254
static void	terminate(int);
229
255
230
static SLIST_HEAD(, exportlist) exphead = SLIST_HEAD_INITIALIZER(exphead);
256
#define	EXPHASH(f)	(fnv_32_buf((f), sizeof(fsid_t), 0) % exphashsize)
231
static SLIST_HEAD(, mountlist) mlhead = SLIST_HEAD_INITIALIZER(mlhead);
257
static struct exportlisthead *exphead = NULL;
232
static struct grouplist *grphead;
258
static struct exportlisthead *oldexphead = NULL;
259
static int exphashsize = 0;
260
static SLIST_HEAD(, mountlist) mlhead = SLIST_HEAD_INITIALIZER(&mlhead);
233
static char *exnames_default[2] = { _PATH_EXPORTS, NULL };
261
static char *exnames_default[2] = { _PATH_EXPORTS, NULL };
234
static char **exnames;
262
static char **exnames;
235
static char **hosts = NULL;
263
static char **hosts = NULL;
Lines 260-265 static int have_v6 = 1; Link Here
260
288
261
static int v4root_phase = 0;
289
static int v4root_phase = 0;
262
static char v4root_dirpath[PATH_MAX + 1];
290
static char v4root_dirpath[PATH_MAX + 1];
291
static struct exportlist *v4root_ep = NULL;
292
static struct grouplist *v4root_grp = NULL;
263
static int has_publicfh = 0;
293
static int has_publicfh = 0;
264
294
265
static struct pidfh *pfh = NULL;
295
static struct pidfh *pfh = NULL;
Lines 368-376 main(int argc, char **argv) Link Here
368
	in_port_t svcport;
398
	in_port_t svcport;
369
	int c, k, s;
399
	int c, k, s;
370
	int maxrec = RPC_MAXDATASIZE;
400
	int maxrec = RPC_MAXDATASIZE;
371
	int attempt_cnt, port_len, port_pos, ret;
401
	int attempt_cnt, passno, port_len, port_pos, ret;
372
	char **port_list;
402
	char **port_list;
373
403
404
	passno = 0;
374
	/* Check that another mountd isn't already running. */
405
	/* Check that another mountd isn't already running. */
375
	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
406
	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
376
	if (pfh == NULL) {
407
	if (pfh == NULL) {
Lines 385-391 main(int argc, char **argv) Link Here
385
	else
416
	else
386
		close(s);
417
		close(s);
387
418
388
	while ((c = getopt(argc, argv, "2deh:lnp:rS")) != -1)
419
	while ((c = getopt(argc, argv, "2deh:Ilnp:rS")) != -1)
389
		switch (c) {
420
		switch (c) {
390
		case '2':
421
		case '2':
391
			force_v2 = 1;
422
			force_v2 = 1;
Lines 437-442 main(int argc, char **argv) Link Here
437
		case 'S':
468
		case 'S':
438
			suspend_nfsd = 1;
469
			suspend_nfsd = 1;
439
			break;
470
			break;
471
		case 'I':
472
			passno = 1;
473
			break;
440
		default:
474
		default:
441
			usage();
475
			usage();
442
		}
476
		}
Lines 449-455 main(int argc, char **argv) Link Here
449
483
450
	argc -= optind;
484
	argc -= optind;
451
	argv += optind;
485
	argv += optind;
452
	grphead = (struct grouplist *)NULL;
453
	if (argc > 0)
486
	if (argc > 0)
454
		exnames = argv;
487
		exnames = argv;
455
	else
488
	else
Lines 457-463 main(int argc, char **argv) Link Here
457
	openlog("mountd", LOG_PID, LOG_DAEMON);
490
	openlog("mountd", LOG_PID, LOG_DAEMON);
458
	if (debug)
491
	if (debug)
459
		warnx("getting export list");
492
		warnx("getting export list");
460
	get_exportlist();
493
	get_exportlist(0);
461
	if (debug)
494
	if (debug)
462
		warnx("getting mount list");
495
		warnx("getting mount list");
463
	get_mountlist();
496
	get_mountlist();
Lines 628-634 main(int argc, char **argv) Link Here
628
	/* Expand svc_run() here so that we can call get_exportlist(). */
661
	/* Expand svc_run() here so that we can call get_exportlist(). */
629
	for (;;) {
662
	for (;;) {
630
		if (got_sighup) {
663
		if (got_sighup) {
631
			get_exportlist();
664
			get_exportlist(passno);
632
			got_sighup = 0;
665
			got_sighup = 0;
633
		}
666
		}
634
		readfds = svc_fdset;
667
		readfds = svc_fdset;
Lines 1087-1093 mntsrv(struct svc_req *rqstp, SVCXPRT *t Link Here
1087
		if (bad)
1120
		if (bad)
1088
			ep = NULL;
1121
			ep = NULL;
1089
		else
1122
		else
1090
			ep = ex_search(&fsb.f_fsid);
1123
			ep = ex_search(&fsb.f_fsid, exphead);
1091
		hostset = defset = 0;
1124
		hostset = defset = 0;
1092
		if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
1125
		if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
1093
		    &numsecflavors, &secflavorsp) ||
1126
		    &numsecflavors, &secflavorsp) ||
Lines 1302-1322 xdr_explist_common(XDR *xdrsp, caddr_t c Link Here
1302
	int false = 0;
1335
	int false = 0;
1303
	int putdef;
1336
	int putdef;
1304
	sigset_t sighup_mask;
1337
	sigset_t sighup_mask;
1338
	int i;
1305
1339
1306
	sigemptyset(&sighup_mask);
1340
	sigemptyset(&sighup_mask);
1307
	sigaddset(&sighup_mask, SIGHUP);
1341
	sigaddset(&sighup_mask, SIGHUP);
1308
	sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
1342
	sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
1309
1343
1310
	SLIST_FOREACH(ep, &exphead, entries) {
1344
	for (i = 0; i < exphashsize; i++)
1311
		putdef = 0;
1345
		SLIST_FOREACH(ep, &exphead[i], entries) {
1312
		if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
1346
			putdef = 0;
1313
			       &putdef, brief))
1347
			if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
1314
			goto errout;
1348
				       &putdef, brief))
1315
		if (ep->ex_defdir && putdef == 0 &&
1349
				goto errout;
1316
			put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL,
1350
			if (ep->ex_defdir && putdef == 0 &&
1317
			&putdef, brief))
1351
				put_exlist(ep->ex_defdir, xdrsp, NULL,
1318
			goto errout;
1352
				&putdef, brief))
1319
	}
1353
				goto errout;
1354
		}
1320
	sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
1355
	sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
1321
	if (!xdr_bool(xdrsp, &false))
1356
	if (!xdr_bool(xdrsp, &false))
1322
		return (0);
1357
		return (0);
Lines 1416-1422 static FILE *exp_file; Link Here
1416
 * Get the export list from one, currently open file
1451
 * Get the export list from one, currently open file
1417
 */
1452
 */
1418
static void
1453
static void
1419
get_exportlist_one(void)
1454
get_exportlist_one(int passno)
1420
{
1455
{
1421
	struct exportlist *ep;
1456
	struct exportlist *ep;
1422
	struct grouplist *grp, *tgrp;
1457
	struct grouplist *grp, *tgrp;
Lines 1540-1546 get_exportlist_one(void) Link Here
1540
					 * See if this directory is already
1575
					 * See if this directory is already
1541
					 * in the list.
1576
					 * in the list.
1542
					 */
1577
					 */
1543
					ep = ex_search(&fsb.f_fsid);
1578
					ep = ex_search(&fsb.f_fsid, exphead);
1544
					if (ep == (struct exportlist *)NULL) {
1579
					if (ep == (struct exportlist *)NULL) {
1545
					    ep = get_exp();
1580
					    ep = get_exp();
1546
					    ep->ex_fs = fsb.f_fsid;
1581
					    ep->ex_fs = fsb.f_fsid;
Lines 1653-1663 get_exportlist_one(void) Link Here
1653
		 * Loop through hosts, pushing the exports into the kernel.
1688
		 * Loop through hosts, pushing the exports into the kernel.
1654
		 * After loop, tgrp points to the start of the list and
1689
		 * After loop, tgrp points to the start of the list and
1655
		 * grp points to the last entry in the list.
1690
		 * grp points to the last entry in the list.
1691
		 * Do not do the do_mount() for passno == 1, since the
1692
		 * second pass will do it, as required.
1656
		 */
1693
		 */
1657
		grp = tgrp;
1694
		grp = tgrp;
1658
		do {
1695
		do {
1659
			if (do_mount(ep, grp, exflags, &anon, dirp, dirplen,
1696
			grp->gr_exflags = exflags;
1660
			    &fsb)) {
1697
			grp->gr_anon = anon;
1698
			if (passno != 1 && do_mount(ep, grp, exflags, &anon,
1699
			    dirp, dirplen, &fsb, ep->ex_numsecflavors,
1700
			    ep->ex_secflavors)) {
1661
				getexp_err(ep, tgrp, NULL);
1701
				getexp_err(ep, tgrp, NULL);
1662
				goto nextline;
1702
				goto nextline;
1663
			}
1703
			}
Lines 1668-1682 get_exportlist_one(void) Link Here
1668
		 */
1708
		 */
1669
		if (v4root_phase > 0 && v4root_phase <= 2) {
1709
		if (v4root_phase > 0 && v4root_phase <= 2) {
1670
			/*
1710
			/*
1671
			 * Since these structures aren't used by mountd,
1711
			 * These structures are used for the "-I" reload,
1712
			 * so save them for that case.  Otherwise, just
1672
			 * free them up now.
1713
			 * free them up now.
1673
			 */
1714
			 */
1674
			if (ep != NULL)
1715
			if (passno == 1) {
1675
				free_exp(ep);
1716
				if (v4root_ep != NULL) {
1676
			while (tgrp != NULL) {
1717
					getexp_err(ep, tgrp,
1677
				grp = tgrp;
1718
					    "multiple V4 lines");
1678
				tgrp = tgrp->gr_next;
1719
					goto nextline;
1679
				free_grp(grp);
1720
				}
1721
				v4root_ep = ep;
1722
				v4root_grp = tgrp;
1723
			} else {
1724
				if (ep != NULL)
1725
					free_exp(ep);
1726
				while (tgrp != NULL) {
1727
					grp = tgrp;
1728
					tgrp = tgrp->gr_next;
1729
					free_grp(grp);
1730
				}
1680
			}
1731
			}
1681
			goto nextline;
1732
			goto nextline;
1682
		}
1733
		}
Lines 1685-1701 get_exportlist_one(void) Link Here
1685
		 * Success. Update the data structures.
1736
		 * Success. Update the data structures.
1686
		 */
1737
		 */
1687
		if (has_host) {
1738
		if (has_host) {
1688
			hang_dirp(dirhead, tgrp, ep, opt_flags);
1739
			hang_dirp(dirhead, tgrp, ep, opt_flags, &anon, exflags);
1689
			grp->gr_next = grphead;
1740
			grp->gr_next = ep->ex_grphead;
1690
			grphead = tgrp;
1741
			ep->ex_grphead = tgrp;
1691
		} else {
1742
		} else {
1692
			hang_dirp(dirhead, (struct grouplist *)NULL, ep,
1743
			hang_dirp(dirhead, (struct grouplist *)NULL, ep,
1693
				opt_flags);
1744
				opt_flags, &anon, exflags);
1694
			free_grp(grp);
1745
			free_grp(grp);
1695
		}
1746
		}
1696
		dirhead = (struct dirlist *)NULL;
1747
		dirhead = (struct dirlist *)NULL;
1697
		if ((ep->ex_flag & EX_LINKED) == 0) {
1748
		if ((ep->ex_flag & EX_LINKED) == 0) {
1698
			SLIST_INSERT_HEAD(&exphead, ep, entries);
1749
			insert_exports(ep, exphead);
1699
1750
1700
			ep->ex_flag |= EX_LINKED;
1751
			ep->ex_flag |= EX_LINKED;
1701
		}
1752
		}
Lines 1712-1756 nextline: Link Here
1712
 * Get the export list from all specified files
1763
 * Get the export list from all specified files
1713
 */
1764
 */
1714
static void
1765
static void
1715
get_exportlist(void)
1766
get_exportlist(int passno)
1716
{
1767
{
1717
	struct exportlist *ep, *ep2;
1718
	struct grouplist *grp, *tgrp;
1719
	struct export_args export;
1768
	struct export_args export;
1720
	struct iovec *iov;
1769
	struct iovec *iov;
1721
	struct statfs *fsp, *mntbufp;
1770
	struct statfs *mntbufp;
1722
	struct xvfsconf vfc;
1723
	char errmsg[255];
1771
	char errmsg[255];
1724
	int num, i;
1772
	int num, i;
1725
	int iovlen;
1773
	int iovlen;
1726
	int done;
1727
	struct nfsex_args eargs;
1774
	struct nfsex_args eargs;
1728
1775
1729
	if (suspend_nfsd != 0)
1776
syslog(LOG_ERR, "passno=%d", passno);
1730
		(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL);
1731
	v4root_dirpath[0] = '\0';
1777
	v4root_dirpath[0] = '\0';
1778
	free_v4rootexp();
1779
	if (passno == 1) {
1780
		/*
1781
		 * Save the current lists as old ones, so that the new lists
1782
		 * can be compared with the old ones in the 2nd pass.
1783
		 */
1784
		for (i = 0; i < exphashsize; i++) {
1785
			SLIST_FIRST(&oldexphead[i]) = SLIST_FIRST(&exphead[i]);
1786
			SLIST_INIT(&exphead[i]);
1787
		}
1788
1789
		/* Read the export file(s) and process them */
1790
		read_exportfile(passno);
1791
syslog(LOG_ERR, "readexp1");
1792
	} else {
1793
		/*
1794
		 * Just make the old lists empty.
1795
		 * exphashsize == 0 for the first call, before oldexphead
1796
		 * has been initialized-->loop won't be executed.
1797
		 */
1798
		for (i = 0; i < exphashsize; i++)
1799
			SLIST_INIT(&oldexphead[i]);
1800
	}
1801
1732
	bzero(&export, sizeof(export));
1802
	bzero(&export, sizeof(export));
1733
	export.ex_flags = MNT_DELEXPORT;
1803
	export.ex_flags = MNT_DELEXPORT;
1734
	iov = NULL;
1804
	iov = NULL;
1735
	iovlen = 0;
1805
	iovlen = 0;
1736
	bzero(errmsg, sizeof(errmsg));
1806
	bzero(errmsg, sizeof(errmsg));
1737
1807
1738
	/*
1808
	if (suspend_nfsd != 0)
1739
	 * First, get rid of the old list
1809
		(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL);
1740
	 */
1741
	SLIST_FOREACH_SAFE(ep, &exphead, entries, ep2) {
1742
		SLIST_REMOVE(&exphead, ep, exportlist, entries);
1743
		free_exp(ep);
1744
	}
1745
1746
	grp = grphead;
1747
	while (grp) {
1748
		tgrp = grp;
1749
		grp = grp->gr_next;
1750
		free_grp(tgrp);
1751
	}
1752
	grphead = (struct grouplist *)NULL;
1753
1754
	/*
1810
	/*
1755
	 * and the old V4 root dir.
1811
	 * and the old V4 root dir.
1756
	 */
1812
	 */
Lines 1765-1826 get_exportlist(void) Link Here
1765
	 */
1821
	 */
1766
	has_publicfh = 0;
1822
	has_publicfh = 0;
1767
1823
1824
	build_iovec(&iov, &iovlen, "fstype", NULL, 0);
1825
	build_iovec(&iov, &iovlen, "fspath", NULL, 0);
1826
	build_iovec(&iov, &iovlen, "from", NULL, 0);
1827
	build_iovec(&iov, &iovlen, "update", NULL, 0);
1828
	build_iovec(&iov, &iovlen, "export", &export,
1829
	    sizeof(export));
1830
	build_iovec(&iov, &iovlen, "errmsg", errmsg,
1831
	    sizeof(errmsg));
1832
1768
	/*
1833
	/*
1769
	 * And delete exports that are in the kernel for all local
1834
	 * For passno == 1, compare the old and new lists updating the kernel
1770
	 * filesystems.
1835
	 * exports for any cases that have changed.
1771
	 * XXX: Should know how to handle all local exportable filesystems.
1836
	 * This call is doing the second pass through the lists.
1837
	 * If it fails, fall back on the bulk reload.
1772
	 */
1838
	 */
1773
	num = getmntinfo(&mntbufp, MNT_NOWAIT);
1839
	if (passno == 1 && compare_nmount_exportlist(iov, iovlen, errmsg) ==
1774
1840
	    0) {
1775
	if (num > 0) {
1841
syslog(LOG_ERR, "compareok");
1776
		build_iovec(&iov, &iovlen, "fstype", NULL, 0);
1842
		/* Free up the old lists. */
1777
		build_iovec(&iov, &iovlen, "fspath", NULL, 0);
1843
		free_exports(oldexphead);
1778
		build_iovec(&iov, &iovlen, "from", NULL, 0);
1844
	} else {
1779
		build_iovec(&iov, &iovlen, "update", NULL, 0);
1845
syslog(LOG_ERR, "doin passno=0");
1780
		build_iovec(&iov, &iovlen, "export", &export, sizeof(export));
1846
		/* exphead == NULL if not yet allocated (first call). */
1781
		build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
1847
		if (exphead != NULL) {
1782
	}
1848
			/*
1783
1849
			 * First, get rid of the old lists.
1784
	for (i = 0; i < num; i++) {
1850
			 */
1785
		fsp = &mntbufp[i];
1851
			free_exports(exphead);
1786
		if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
1852
			free_exports(oldexphead);
1787
			syslog(LOG_ERR, "getvfsbyname() failed for %s",
1788
			    fsp->f_fstypename);
1789
			continue;
1790
		}
1853
		}
1854
		free_v4rootexp();
1791
1855
1792
		/*
1856
		/*
1793
		 * We do not need to delete "export" flag from
1857
		 * And delete exports that are in the kernel for all local
1794
		 * filesystems that do not have it set.
1858
		 * filesystems.
1795
		 */
1859
		 * XXX: Should know how to handle all local exportable
1796
		if (!(fsp->f_flags & MNT_EXPORTED))
1860
		 * filesystems.
1797
		    continue;
1861
		 */
1798
		/*
1862
		num = getmntinfo(&mntbufp, MNT_NOWAIT);
1799
		 * Do not delete export for network filesystem by
1863
1800
		 * passing "export" arg to nmount().
1864
		/* Allocate hash tables, for first call. */
1801
		 * It only makes sense to do this for local filesystems.
1865
		if (exphead == NULL) {
1802
		 */
1866
			/* Target an average linked list length of 20. */
1803
		if (vfc.vfc_flags & VFCF_NETWORK)
1867
			exphashsize = num / 10;
1804
			continue;
1868
			if (exphashsize < 1)
1805
1869
				exphashsize = 1;
1806
		iov[1].iov_base = fsp->f_fstypename;
1870
			else if (exphashsize > 100000)
1807
		iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
1871
				exphashsize = 100000;
1808
		iov[3].iov_base = fsp->f_mntonname;
1872
			exphead = malloc(exphashsize * sizeof(*exphead));
1809
		iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
1873
			oldexphead = malloc(exphashsize * sizeof(*oldexphead));
1810
		iov[5].iov_base = fsp->f_mntfromname;
1874
			if (exphead == NULL || oldexphead == NULL)
1811
		iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
1875
				errx(1, "Can't malloc hash tables");
1812
		errmsg[0] = '\0';
1876
1813
1877
			for (i = 0; i < exphashsize; i++) {
1814
		/*
1878
				SLIST_INIT(&exphead[i]);
1815
		 * EXDEV is returned when path exists but is not a
1879
				SLIST_INIT(&oldexphead[i]);
1816
		 * mount point.  May happens if raced with unmount.
1880
			}
1817
		 */
1818
		if (nmount(iov, iovlen, fsp->f_flags) < 0 &&
1819
		    errno != ENOENT && errno != ENOTSUP && errno != EXDEV) {
1820
			syslog(LOG_ERR,
1821
			    "can't delete exports for %s: %m %s",
1822
			    fsp->f_mntonname, errmsg);
1823
		}
1881
		}
1882
	
1883
		for (i = 0; i < num; i++)
1884
			delete_export(iov, iovlen, &mntbufp[i], errmsg);
1885
1886
1887
		/* Read the export file(s) and process them */
1888
		read_exportfile(0);
1889
syslog(LOG_ERR, "readexp0");
1824
	}
1890
	}
1825
1891
1826
	if (iov != NULL) {
1892
	if (iov != NULL) {
Lines 1838-1843 get_exportlist(void) Link Here
1838
	}
1904
	}
1839
1905
1840
	/*
1906
	/*
1907
	 * If there was no public fh, clear any previous one set.
1908
	 */
1909
	if (has_publicfh == 0)
1910
		(void) nfssvc(NFSSVC_NOPUBLICFH, NULL);
1911
1912
	/* Resume the nfsd. If they weren't suspended, this is harmless. */
1913
	(void)nfssvc(NFSSVC_RESUMENFSD, NULL);
1914
syslog(LOG_ERR, "eo get_exportlist");
1915
}
1916
1917
/*
1918
 * Insert an export entry in the appropriate list.
1919
 */
1920
static void
1921
insert_exports(struct exportlist *ep, struct exportlisthead *exhp)
1922
{
1923
	uint32_t i;
1924
1925
	i = EXPHASH(&ep->ex_fs);
1926
syslog(LOG_ERR, "fs=%s hash=%i", ep->ex_fsdir, i);
1927
	SLIST_INSERT_HEAD(&exhp[i], ep, entries);
1928
}
1929
1930
/*
1931
 * Free up the exports lists passed in as arguments.
1932
 */
1933
static void
1934
free_exports(struct exportlisthead *exhp)
1935
{
1936
	struct exportlist *ep, *ep2;
1937
	int i;
1938
1939
	for (i = 0; i < exphashsize; i++) {
1940
		SLIST_FOREACH_SAFE(ep, &exhp[i], entries, ep2) {
1941
			SLIST_REMOVE(&exhp[i], ep, exportlist, entries);
1942
			free_exp(ep);
1943
		}
1944
		SLIST_INIT(&exhp[i]);
1945
	}
1946
}
1947
1948
/*
1949
 * Read the exports file(s) and call get_exportlist_one() for each line.
1950
 */
1951
static void
1952
read_exportfile(int passno)
1953
{
1954
	int done, i;
1955
1956
	/*
1841
	 * Read in the exports file and build the list, calling
1957
	 * Read in the exports file and build the list, calling
1842
	 * nmount() as we go along to push the export rules into the kernel.
1958
	 * nmount() as we go along to push the export rules into the kernel.
1843
	 */
1959
	 */
Lines 1849-1855 get_exportlist(void) Link Here
1849
			syslog(LOG_WARNING, "can't open %s", exnames[i]);
1965
			syslog(LOG_WARNING, "can't open %s", exnames[i]);
1850
			continue;
1966
			continue;
1851
		}
1967
		}
1852
		get_exportlist_one();
1968
		get_exportlist_one(passno);
1853
		fclose(exp_file);
1969
		fclose(exp_file);
1854
		done++;
1970
		done++;
1855
	}
1971
	}
Lines 1857-1871 get_exportlist(void) Link Here
1857
		syslog(LOG_ERR, "can't open any exports file");
1973
		syslog(LOG_ERR, "can't open any exports file");
1858
		exit(2);
1974
		exit(2);
1859
	}
1975
	}
1976
}
1977
1978
/*
1979
 * Compare the export lists against the old ones and do nmount() operations
1980
 * for any cases that have changed.  This avoids doing nmount() for entries
1981
 * that have not changed.
1982
 * Return 0 upon success, 1 otherwise.
1983
 */
1984
static int
1985
compare_nmount_exportlist(struct iovec *iov, int iovlen, char *errmsg)
1986
{
1987
	struct exportlist *ep, *oep;
1988
	struct grouplist *grp;
1989
	struct statfs fs, ofs;
1990
	int i, ret;
1860
1991
1861
	/*
1992
	/*
1862
	 * If there was no public fh, clear any previous one set.
1993
	 * Loop through the current list and look for an entry in the old
1994
	 * list.
1995
	 * If found, check to see if it the same.
1996
	 *        If it is not the same, delete and re-export.
1997
	 *        Then mark it done on the old list.
1998
	 * else (not found)
1999
	 *        export it.
2000
	 * Any entries left in the old list after processing must have their
2001
	 * exports deleted.
1863
	 */
2002
	 */
1864
	if (has_publicfh == 0)
2003
	for (i = 0; i < exphashsize; i++)
1865
		(void) nfssvc(NFSSVC_NOPUBLICFH, NULL);
2004
		SLIST_FOREACH(ep, &exphead[i], entries) {
2005
syslog(LOG_ERR, "foreach ep");
2006
			oep = ex_search(&ep->ex_fs, oldexphead);
2007
			if (oep != NULL) {
2008
				/*
2009
				 * Check the mount paths are the same.
2010
				 * If not, return 1 so that the reload of the
2011
				 * exports will be done in bulk, the
2012
				 * passno == 0 way.
2013
				 */
2014
syslog(LOG_ERR, "fnd ex");
2015
				if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0)
2016
					return (1);
2017
				/*
2018
				 * Test to see if the entry is the same.
2019
				 * If not the same delete exports and
2020
				 * re-export.
2021
				 */
2022
syslog(LOG_ERR, "at compare");
2023
				if (compare_export(ep, oep) != 0) {
2024
					if (statfs(ep->ex_fsdir, &fs) < 0)
2025
						return (1);
2026
syslog(LOG_ERR, "changed fsv0=%d fsv1=%d", fs.f_fsid.val[0], fs.f_fsid.val[1]);
2027
					delete_export(iov, iovlen, &fs, errmsg);
2028
					ret = do_export_mount(ep, &fs);
2029
					if (ret != 0)
2030
						return (ret);
2031
				}
2032
				oep->ex_flag |= EX_DONE;
2033
syslog(LOG_ERR, "exdone");
2034
			} else {
2035
syslog(LOG_ERR, "not fnd so ex");
2036
				/* Not found, so do export. */
2037
				if (statfs(ep->ex_fsdir, &fs) < 0)
2038
					return (1);
2039
syslog(LOG_ERR, "not fnd fsv0=%d fsv1=%d", fs.f_fsid.val[0], fs.f_fsid.val[1]);
2040
				ret = do_export_mount(ep, &fs);
2041
				if (ret != 0)
2042
					return (ret);
2043
			}
2044
		}
1866
2045
1867
	/* Resume the nfsd. If they weren't suspended, this is harmless. */
2046
	/* Delete exports not done. */
1868
	(void)nfssvc(NFSSVC_RESUMENFSD, NULL);
2047
	for (i = 0; i < exphashsize; i++)
2048
		SLIST_FOREACH(oep, &oldexphead[i], entries) {
2049
			if ((oep->ex_flag & EX_DONE) == 0) {
2050
syslog(LOG_ERR, "not done delete");
2051
				if (statfs(oep->ex_fsdir, &ofs) >= 0 &&
2052
				    oep->ex_fs.val[0] == ofs.f_fsid.val[0] &&
2053
				    oep->ex_fs.val[1] == ofs.f_fsid.val[1]) {
2054
syslog(LOG_ERR, "do delete");
2055
					delete_export(iov, iovlen, &ofs, errmsg);
2056
				}
2057
			}
2058
		}
2059
2060
	/* Do the V4 root exports, as required. */
2061
	grp = v4root_grp;
2062
	v4root_phase = 2;
2063
	while (v4root_ep != NULL && grp != NULL) {
2064
syslog(LOG_ERR, "v4ex path=%s gr_type=0x%x gr_exflags=0x%x", v4root_dirpath, grp->gr_type, grp->gr_exflags);
2065
syslog(LOG_ERR, "v4rootd=%s", v4root_dirpath);
2066
		ret = do_mount(v4root_ep, grp, grp->gr_exflags, &grp->gr_anon,
2067
		    v4root_dirpath, strlen(v4root_dirpath), &fs,
2068
		    v4root_ep->ex_numsecflavors, v4root_ep->ex_secflavors);
2069
		if (ret != 0) {
2070
			v4root_phase = 0;
2071
			return (ret);
2072
		}
2073
		grp = grp->gr_next;
2074
	}
2075
	v4root_phase = 0;
2076
	free_v4rootexp();
2077
	return (0);
2078
}
2079
2080
/*
2081
 * Compare old and current exportlist entries for the fsid and return 0
2082
 * if they are the same, 1 otherwise.
2083
 */
2084
static int
2085
compare_export(struct exportlist *ep, struct exportlist *oep)
2086
{
2087
	struct grouplist *grp, *ogrp;
2088
2089
	if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0)
2090
		return (1);
2091
	if ((ep->ex_flag & EX_DEFSET) != (oep->ex_flag & EX_DEFSET))
2092
		return (1);
2093
	if ((ep->ex_defdir != NULL && oep->ex_defdir == NULL) ||
2094
	    (ep->ex_defdir == NULL && oep->ex_defdir != NULL))
2095
		return (1);
2096
	if (ep->ex_defdir != NULL && (ep->ex_defdir->dp_flag & DP_DEFSET) !=
2097
	    (oep->ex_defdir->dp_flag & DP_DEFSET))
2098
		return (1);
2099
	if ((ep->ex_flag & EX_DEFSET) != 0 && (ep->ex_defnumsecflavors !=
2100
	    oep->ex_defnumsecflavors || ep->ex_defexflags !=
2101
	    oep->ex_defexflags || compare_cred(&ep->ex_defanon,
2102
	    &oep->ex_defanon) != 0 || compare_secflavor(ep->ex_defsecflavors,
2103
	    oep->ex_defsecflavors, ep->ex_defnumsecflavors) != 0))
2104
		return (1);
2105
2106
	/* Now, check all the groups. */
2107
	for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next)
2108
		ogrp->gr_flag = 0;
2109
	for (grp = ep->ex_grphead; grp != NULL; grp = grp->gr_next) {
2110
		for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp =
2111
		    ogrp->gr_next)
2112
			if ((ogrp->gr_flag & GR_FND) == 0 &&
2113
			    grp->gr_numsecflavors == ogrp->gr_numsecflavors &&
2114
			    grp->gr_exflags == ogrp->gr_exflags &&
2115
			    compare_cred(&grp->gr_anon, &ogrp->gr_anon) == 0 &&
2116
			    compare_secflavor(grp->gr_secflavors,
2117
			    ogrp->gr_secflavors, grp->gr_numsecflavors) == 0)
2118
				break;
2119
		if (ogrp != NULL)
2120
			ogrp->gr_flag |= GR_FND;
2121
		else
2122
			return (1);
2123
	}
2124
	for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next)
2125
		if ((ogrp->gr_flag & GR_FND) == 0)
2126
			return (1);
2127
	return (0);
2128
}
2129
2130
/*
2131
 * Compare to struct xucred's.  Return 0 if the same and 1 otherwise.
2132
 * This algorithm is O(N**2) but fortunately N is always small.
2133
 */
2134
static int
2135
compare_cred(struct xucred *cr0, struct xucred *cr1)
2136
{
2137
	int i, j;
2138
2139
	if (cr0->cr_uid != cr1->cr_uid || cr0->cr_ngroups != cr1->cr_ngroups)
2140
		return (1);
2141
	for (i = 0; i < cr0->cr_ngroups; i++) {
2142
		for (j = 0; j < cr0->cr_ngroups; j++)
2143
			if (cr0->cr_groups[i] == cr1->cr_groups[j])
2144
				break;
2145
		if (j == cr0->cr_ngroups)
2146
			return (1);
2147
	}
2148
	return (0);
2149
}
2150
2151
/*
2152
 * Compare two lists of security flavors.  Return 0 if the same and 1 otherwise.
2153
 * This algorithm is O(N**2) but fortunately N is always small.
2154
 */
2155
static int
2156
compare_secflavor(int *sec1, int *sec2, int nsec)
2157
{
2158
	int i, j;
2159
2160
	for (i = 0; i < nsec; i++) {
2161
		for (j = 0; j < nsec; j++)
2162
			if (sec1[i] == sec2[j])
2163
				break;
2164
		if (j == nsec)
2165
			return (1);
2166
	}
2167
	return (0);
2168
}
2169
2170
/*
2171
 * Delete an exports entry.
2172
 */
2173
static void
2174
delete_export(struct iovec *iov, int iovlen, struct statfs *fsp, char *errmsg)
2175
{
2176
	struct xvfsconf vfc;
2177
2178
	if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
2179
		syslog(LOG_ERR, "getvfsbyname() failed for %s",
2180
		    fsp->f_fstypename);
2181
		return;
2182
	}
2183
	
2184
	/*
2185
	 * We do not need to delete "export" flag from
2186
	 * filesystems that do not have it set.
2187
	 */
2188
	if (!(fsp->f_flags & MNT_EXPORTED))
2189
		return;
2190
	/*
2191
	 * Do not delete export for network filesystem by
2192
	 * passing "export" arg to nmount().
2193
	 * It only makes sense to do this for local filesystems.
2194
	 */
2195
	if (vfc.vfc_flags & VFCF_NETWORK)
2196
		return;
2197
	
2198
	iov[1].iov_base = fsp->f_fstypename;
2199
	iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
2200
	iov[3].iov_base = fsp->f_mntonname;
2201
	iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
2202
	iov[5].iov_base = fsp->f_mntfromname;
2203
	iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
2204
	errmsg[0] = '\0';
2205
	
2206
	/*
2207
	 * EXDEV is returned when path exists but is not a
2208
	 * mount point.  May happens if raced with unmount.
2209
	 */
2210
	if (nmount(iov, iovlen, fsp->f_flags) < 0 && errno != ENOENT &&
2211
	    errno != ENOTSUP && errno != EXDEV) {
2212
		syslog(LOG_ERR,
2213
		    "can't delete exports for %s: %m %s",
2214
		    fsp->f_mntonname, errmsg);
2215
	}
1869
}
2216
}
1870
2217
1871
/*
2218
/*
Lines 1924-1934 getexp_err(struct exportlist *ep, struct Link Here
1924
 * Search the export list for a matching fs.
2271
 * Search the export list for a matching fs.
1925
 */
2272
 */
1926
static struct exportlist *
2273
static struct exportlist *
1927
ex_search(fsid_t *fsid)
2274
ex_search(fsid_t *fsid, struct exportlisthead *exhp)
1928
{
2275
{
1929
	struct exportlist *ep;
2276
	struct exportlist *ep;
2277
	uint32_t i;
1930
2278
1931
	SLIST_FOREACH(ep, &exphead, entries) {
2279
	i = EXPHASH(fsid);
2280
	SLIST_FOREACH(ep, &exhp[i], entries) {
1932
		if (ep->ex_fs.val[0] == fsid->val[0] &&
2281
		if (ep->ex_fs.val[0] == fsid->val[0] &&
1933
		    ep->ex_fs.val[1] == fsid->val[1])
2282
		    ep->ex_fs.val[1] == fsid->val[1])
1934
			return (ep);
2283
			return (ep);
Lines 1965-1971 add_expdir(struct dirlist **dpp, char *c Link Here
1965
 */
2314
 */
1966
static void
2315
static void
1967
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
2316
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
1968
	int flags)
2317
	int flags, struct xucred *anoncrp, int exflags)
1969
{
2318
{
1970
	struct hostlist *hp;
2319
	struct hostlist *hp;
1971
	struct dirlist *dp2;
2320
	struct dirlist *dp2;
Lines 1976-1987 hang_dirp(struct dirlist *dp, struct gro Link Here
1976
		else
2325
		else
1977
			ep->ex_defdir = dp;
2326
			ep->ex_defdir = dp;
1978
		if (grp == (struct grouplist *)NULL) {
2327
		if (grp == (struct grouplist *)NULL) {
2328
			ep->ex_flag |= EX_DEFSET;
1979
			ep->ex_defdir->dp_flag |= DP_DEFSET;
2329
			ep->ex_defdir->dp_flag |= DP_DEFSET;
1980
			/* Save the default security flavors list. */
2330
			/* Save the default security flavors list. */
1981
			ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2331
			ep->ex_defnumsecflavors = ep->ex_numsecflavors;
1982
			if (ep->ex_numsecflavors > 0)
2332
			if (ep->ex_numsecflavors > 0)
1983
				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2333
				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
1984
				    sizeof(ep->ex_secflavors));
2334
				    sizeof(ep->ex_secflavors));
2335
			ep->ex_defanon = *anoncrp;
2336
			ep->ex_defexflags = exflags;
1985
		} else while (grp) {
2337
		} else while (grp) {
1986
			hp = get_ht();
2338
			hp = get_ht();
1987
			hp->ht_grp = grp;
2339
			hp->ht_grp = grp;
Lines 2001-2007 hang_dirp(struct dirlist *dp, struct gro Link Here
2001
		 */
2353
		 */
2002
		while (dp) {
2354
		while (dp) {
2003
			dp2 = dp->dp_left;
2355
			dp2 = dp->dp_left;
2004
			add_dlist(&ep->ex_dirl, dp, grp, flags, ep);
2356
			add_dlist(&ep->ex_dirl, dp, grp, flags, ep, anoncrp,
2357
			    exflags);
2005
			dp = dp2;
2358
			dp = dp2;
2006
		}
2359
		}
2007
	}
2360
	}
Lines 2013-2019 hang_dirp(struct dirlist *dp, struct gro Link Here
2013
 */
2366
 */
2014
static void
2367
static void
2015
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
2368
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
2016
	int flags, struct exportlist *ep)
2369
	int flags, struct exportlist *ep, struct xucred *anoncrp, int exflags)
2017
{
2370
{
2018
	struct dirlist *dp;
2371
	struct dirlist *dp;
2019
	struct hostlist *hp;
2372
	struct hostlist *hp;
Lines 2023-2032 add_dlist(struct dirlist **dpp, struct d Link Here
2023
	if (dp) {
2376
	if (dp) {
2024
		cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
2377
		cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
2025
		if (cmp > 0) {
2378
		if (cmp > 0) {
2026
			add_dlist(&dp->dp_left, newdp, grp, flags, ep);
2379
			add_dlist(&dp->dp_left, newdp, grp, flags, ep, anoncrp,
2380
			    exflags);
2027
			return;
2381
			return;
2028
		} else if (cmp < 0) {
2382
		} else if (cmp < 0) {
2029
			add_dlist(&dp->dp_right, newdp, grp, flags, ep);
2383
			add_dlist(&dp->dp_right, newdp, grp, flags, ep, anoncrp,
2384
			    exflags);
2030
			return;
2385
			return;
2031
		} else
2386
		} else
2032
			free((caddr_t)newdp);
2387
			free((caddr_t)newdp);
Lines 2053-2064 add_dlist(struct dirlist **dpp, struct d Link Here
2053
			grp = grp->gr_next;
2408
			grp = grp->gr_next;
2054
		} while (grp);
2409
		} while (grp);
2055
	} else {
2410
	} else {
2411
		ep->ex_flag |= EX_DEFSET;
2056
		dp->dp_flag |= DP_DEFSET;
2412
		dp->dp_flag |= DP_DEFSET;
2057
		/* Save the default security flavors list. */
2413
		/* Save the default security flavors list. */
2058
		ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2414
		ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2059
		if (ep->ex_numsecflavors > 0)
2415
		if (ep->ex_numsecflavors > 0)
2060
			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2416
			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2061
			    sizeof(ep->ex_secflavors));
2417
			    sizeof(ep->ex_secflavors));
2418
		ep->ex_defanon = *anoncrp;
2419
		ep->ex_defexflags = exflags;
2062
	}
2420
	}
2063
}
2421
}
2064
2422
Lines 2403-2408 get_host(char *cp, struct grouplist *grp Link Here
2403
static void
2761
static void
2404
free_exp(struct exportlist *ep)
2762
free_exp(struct exportlist *ep)
2405
{
2763
{
2764
	struct grouplist *grp, *tgrp;
2406
2765
2407
	if (ep->ex_defdir) {
2766
	if (ep->ex_defdir) {
2408
		free_host(ep->ex_defdir->dp_hosts);
2767
		free_host(ep->ex_defdir->dp_hosts);
Lines 2413-2422 free_exp(struct exportlist *ep) Link Here
2413
	if (ep->ex_indexfile)
2772
	if (ep->ex_indexfile)
2414
		free(ep->ex_indexfile);
2773
		free(ep->ex_indexfile);
2415
	free_dir(ep->ex_dirl);
2774
	free_dir(ep->ex_dirl);
2775
	grp = ep->ex_grphead;
2776
	while (grp) {
2777
		tgrp = grp;
2778
		grp = grp->gr_next;
2779
		free_grp(tgrp);
2780
	}
2416
	free((caddr_t)ep);
2781
	free((caddr_t)ep);
2417
}
2782
}
2418
2783
2419
/*
2784
/*
2785
 * Free up the v4root exports.
2786
 */
2787
static void
2788
free_v4rootexp(void)
2789
{
2790
	struct grouplist *grp, *tgrp;
2791
2792
	if (v4root_ep != NULL) {
2793
		free_exp(v4root_ep);
2794
		v4root_ep = NULL;
2795
	}
2796
	tgrp = v4root_grp;
2797
	v4root_grp = NULL;
2798
	while (tgrp != NULL) {
2799
		grp = tgrp;
2800
		tgrp = tgrp->gr_next;
2801
		free_grp(grp);
2802
	}
2803
}
2804
2805
/*
2420
 * Free hosts.
2806
 * Free hosts.
2421
 */
2807
 */
2422
static void
2808
static void
Lines 2456-2467 out_of_mem(void) Link Here
2456
}
2842
}
2457
2843
2458
/*
2844
/*
2845
 * Call do_mount() from the struct exportlist, for each case needed.
2846
 */
2847
static int
2848
do_export_mount(struct exportlist *ep, struct statfs *fsp)
2849
{
2850
	struct grouplist *grp, defgrp;
2851
	int ret;
2852
	size_t dirlen;
2853
2854
syslog(LOG_ERR, "do_mount_export=%s", ep->ex_fsdir);
2855
	dirlen = strlen(ep->ex_fsdir);
2856
	if ((ep->ex_flag & EX_DEFSET) != 0) {
2857
		defgrp.gr_type = GT_DEFAULT;
2858
		defgrp.gr_next = NULL;
2859
		/* We have an entry for all other hosts/nets. */
2860
syslog(LOG_ERR, "ex_defexflags=0x%x", ep->ex_defexflags);
2861
		ret = do_mount(ep, &defgrp, ep->ex_defexflags, &ep->ex_defanon,
2862
		    ep->ex_fsdir, dirlen, fsp, ep->ex_defnumsecflavors,
2863
		    ep->ex_defsecflavors);
2864
		if (ret != 0)
2865
			return (ret);
2866
	}
2867
2868
	/* Do a mount for each group. */
2869
	grp = ep->ex_grphead;
2870
	while (grp != NULL) {
2871
syslog(LOG_ERR, "do mount gr_type=0x%x gr_exflags=0x%x", grp->gr_type, grp->gr_exflags);
2872
		ret = do_mount(ep, grp, grp->gr_exflags, &grp->gr_anon,
2873
		    ep->ex_fsdir, dirlen, fsp, grp->gr_numsecflavors,
2874
		    grp->gr_secflavors);
2875
		if (ret != 0)
2876
			return (ret);
2877
		grp = grp->gr_next;
2878
	}
2879
	return (0);
2880
}
2881
2882
/*
2459
 * Do the nmount() syscall with the update flag to push the export info into
2883
 * Do the nmount() syscall with the update flag to push the export info into
2460
 * the kernel.
2884
 * the kernel.
2461
 */
2885
 */
2462
static int
2886
static int
2463
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
2887
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
2464
    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb)
2888
    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb,
2889
    int numsecflavors, int *secflavors)
2465
{
2890
{
2466
	struct statfs fsb1;
2891
	struct statfs fsb1;
2467
	struct addrinfo *ai;
2892
	struct addrinfo *ai;
Lines 2487-2500 do_mount(struct exportlist *ep, struct g Link Here
2487
	bzero(errmsg, sizeof(errmsg));
2912
	bzero(errmsg, sizeof(errmsg));
2488
	eap->ex_flags = exflags;
2913
	eap->ex_flags = exflags;
2489
	eap->ex_anon = *anoncrp;
2914
	eap->ex_anon = *anoncrp;
2915
syslog(LOG_ERR, "do_exflags=0x%x", exflags);
2490
	eap->ex_indexfile = ep->ex_indexfile;
2916
	eap->ex_indexfile = ep->ex_indexfile;
2491
	if (grp->gr_type == GT_HOST)
2917
	if (grp->gr_type == GT_HOST)
2492
		ai = grp->gr_ptr.gt_addrinfo;
2918
		ai = grp->gr_ptr.gt_addrinfo;
2493
	else
2919
	else
2494
		ai = NULL;
2920
		ai = NULL;
2495
	eap->ex_numsecflavors = ep->ex_numsecflavors;
2921
	eap->ex_numsecflavors = numsecflavors;
2922
syslog(LOG_ERR, "do_numsec=%d", numsecflavors);
2496
	for (i = 0; i < eap->ex_numsecflavors; i++)
2923
	for (i = 0; i < eap->ex_numsecflavors; i++)
2497
		eap->ex_secflavors[i] = ep->ex_secflavors[i];
2924
		eap->ex_secflavors[i] = secflavors[i];
2498
	if (eap->ex_numsecflavors == 0) {
2925
	if (eap->ex_numsecflavors == 0) {
2499
		eap->ex_numsecflavors = 1;
2926
		eap->ex_numsecflavors = 1;
2500
		eap->ex_secflavors[0] = AUTH_SYS;
2927
		eap->ex_secflavors[0] = AUTH_SYS;
Lines 2824-2841 static void Link Here
2824
nextfield(char **cp, char **endcp)
3251
nextfield(char **cp, char **endcp)
2825
{
3252
{
2826
	char *p;
3253
	char *p;
3254
	char quot = 0;
2827
3255
2828
	p = *cp;
3256
	p = *cp;
2829
	while (*p == ' ' || *p == '\t')
3257
	while (*p == ' ' || *p == '\t')
2830
		p++;
3258
		p++;
2831
	if (*p == '\n' || *p == '\0')
3259
	*cp = p;
2832
		*cp = *endcp = p;
3260
	while (*p != '\0') {
2833
	else {
3261
		if (quot) {
2834
		*cp = p++;
3262
			if (*p == quot)
2835
		while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
3263
				quot = 0;
2836
			p++;
3264
		} else {
2837
		*endcp = p;
3265
			if (*p == '\\' && *(p + 1) != '\0')
2838
	}
3266
				p++;
3267
			else if (*p == '\'' || *p == '"')
3268
				quot = *p;
3269
			else if (*p == ' ' || *p == '\t')
3270
				break;
3271
		}
3272
		p++;
3273
	};
3274
	*endcp = p;
2839
}
3275
}
2840
3276
2841
/*
3277
/*
Lines 2907-2914 parsecred(char *namelist, struct xucred Link Here
2907
	/*
3343
	/*
2908
	 * Get the user's password table entry.
3344
	 * Get the user's password table entry.
2909
	 */
3345
	 */
2910
	names = strsep_quote(&namelist, " \t\n");
3346
	names = namelist;
2911
	name = strsep(&names, ":");
3347
	name = strsep_quote(&names, ":");
2912
	/* Bug?  name could be NULL here */
3348
	/* Bug?  name could be NULL here */
2913
	if (isdigit(*name) || *name == '-')
3349
	if (isdigit(*name) || *name == '-')
2914
		pw = getpwuid(atoi(name));
3350
		pw = getpwuid(atoi(name));
Lines 2952-2958 parsecred(char *namelist, struct xucred Link Here
2952
	}
3388
	}
2953
	cr->cr_ngroups = 0;
3389
	cr->cr_ngroups = 0;
2954
	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
3390
	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
2955
		name = strsep(&names, ":");
3391
		name = strsep_quote(&names, ":");
2956
		if (isdigit(*name) || *name == '-') {
3392
		if (isdigit(*name) || *name == '-') {
2957
			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
3393
			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
2958
		} else {
3394
		} else {

Return to bug 237860