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

Collapse All | Expand All

(-)usr.sbin/mountd/mountd.c (-146 / +622 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
#define	EX_PUBLICFH	0x8
137
138
SLIST_HEAD(exportlisthead, exportlist);
130
139
131
struct netmsk {
140
struct netmsk {
132
	struct sockaddr_storage nt_net;
141
	struct sockaddr_storage nt_net;
Lines 143-148 struct grouplist { Link Here
143
	int gr_type;
152
	int gr_type;
144
	union grouptypes gr_ptr;
153
	union grouptypes gr_ptr;
145
	struct grouplist *gr_next;
154
	struct grouplist *gr_next;
155
	struct xucred gr_anon;
156
	int gr_exflags;
157
	int gr_flag;
146
	int gr_numsecflavors;
158
	int gr_numsecflavors;
147
	int gr_secflavors[MAXSECFLAVORS];
159
	int gr_secflavors[MAXSECFLAVORS];
148
};
160
};
Lines 153-158 struct grouplist { Link Here
153
#define	GT_DEFAULT	0x3
165
#define	GT_DEFAULT	0x3
154
#define GT_IGNORE	0x5
166
#define GT_IGNORE	0x5
155
167
168
/* Group flags */
169
#define	GR_FND		0x1
170
156
struct hostlist {
171
struct hostlist {
157
	int		 ht_flag;	/* Uses DP_xx bits */
172
	int		 ht_flag;	/* Uses DP_xx bits */
158
	struct grouplist *ht_grp;
173
	struct grouplist *ht_grp;
Lines 172-178 struct fhreturn { Link Here
172
/* Global defs */
187
/* Global defs */
173
static char	*add_expdir(struct dirlist **, char *, int);
188
static char	*add_expdir(struct dirlist **, char *, int);
174
static void	add_dlist(struct dirlist **, struct dirlist *,
189
static void	add_dlist(struct dirlist **, struct dirlist *,
175
		    struct grouplist *, int, struct exportlist *);
190
		    struct grouplist *, int, struct exportlist *,
191
		    struct xucred *, int);
176
static void	add_mlist(char *, char *);
192
static void	add_mlist(char *, char *);
177
static int	check_dirpath(char *);
193
static int	check_dirpath(char *);
178
static int	check_options(struct dirlist *);
194
static int	check_options(struct dirlist *);
Lines 185-201 static void complete_service(struct netc Link Here
185
static void	clearout_service(void);
201
static void	clearout_service(void);
186
static void	del_mlist(char *hostp, char *dirp);
202
static void	del_mlist(char *hostp, char *dirp);
187
static struct dirlist	*dirp_search(struct dirlist *, char *);
203
static struct dirlist	*dirp_search(struct dirlist *, char *);
204
static int	do_export_mount(struct exportlist *, struct statfs *);
188
static int	do_mount(struct exportlist *, struct grouplist *, int,
205
static int	do_mount(struct exportlist *, struct grouplist *, int,
189
		    struct xucred *, char *, int, struct statfs *);
206
		    struct xucred *, char *, int, struct statfs *, int, int *);
190
static int	do_opt(char **, char **, struct exportlist *,
207
static int	do_opt(char **, char **, struct exportlist *,
191
		    struct grouplist *, int *, int *, struct xucred *);
208
		    struct grouplist *, int *, int *, struct xucred *);
192
static struct exportlist	*ex_search(fsid_t *);
209
static struct exportlist	*ex_search(fsid_t *, struct exportlisthead *);
193
static struct exportlist	*get_exp(void);
210
static struct exportlist	*get_exp(void);
194
static void	free_dir(struct dirlist *);
211
static void	free_dir(struct dirlist *);
195
static void	free_exp(struct exportlist *);
212
static void	free_exp(struct exportlist *);
196
static void	free_grp(struct grouplist *);
213
static void	free_grp(struct grouplist *);
197
static void	free_host(struct hostlist *);
214
static void	free_host(struct hostlist *);
198
static void	get_exportlist(void);
215
static void	free_v4rootexp(void);
216
static void	get_exportlist_one(int);
217
static void	get_exportlist(int);
218
static void	insert_exports(struct exportlist *, struct exportlisthead *);
219
static void	free_exports(struct exportlisthead *);
220
static void	read_exportfile(int);
221
static int	compare_nmount_exportlist(struct iovec *, int, char *);
222
static int	compare_export(struct exportlist *, struct exportlist *);
223
static int	compare_cred(struct xucred *, struct xucred *);
224
static int	compare_secflavor(int *, int *, int);
225
static void	delete_export(struct iovec *, int, struct statfs *, char *);
199
static int	get_host(char *, struct grouplist *, struct grouplist *);
226
static int	get_host(char *, struct grouplist *, struct grouplist *);
200
static struct hostlist *get_ht(void);
227
static struct hostlist *get_ht(void);
201
static int	get_line(void);
228
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 *);
231
static void	getexp_err(struct exportlist *, struct grouplist *, const char *);
205
static struct grouplist	*get_grp(void);
232
static struct grouplist	*get_grp(void);
206
static void	hang_dirp(struct dirlist *, struct grouplist *,
233
static void	hang_dirp(struct dirlist *, struct grouplist *,
207
				struct exportlist *, int);
234
		    struct exportlist *, int, struct xucred *, int);
208
static void	huphandler(int sig);
235
static void	huphandler(int sig);
209
static int	makemask(struct sockaddr_storage *ssp, int bitlen);
236
static int	makemask(struct sockaddr_storage *ssp, int bitlen);
210
static void	mntsrv(struct svc_req *, SVCXPRT *);
237
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);
254
static int	xdr_mlist(XDR *, caddr_t);
228
static void	terminate(int);
255
static void	terminate(int);
229
256
230
static SLIST_HEAD(, exportlist) exphead = SLIST_HEAD_INITIALIZER(exphead);
257
#define	EXPHASH(f)	(fnv_32_buf((f), sizeof(fsid_t), 0) % exphashsize)
231
static SLIST_HEAD(, mountlist) mlhead = SLIST_HEAD_INITIALIZER(mlhead);
258
static struct exportlisthead *exphead = NULL;
232
static struct grouplist *grphead;
259
static struct exportlisthead *oldexphead = NULL;
260
static int exphashsize = 0;
261
static SLIST_HEAD(, mountlist) mlhead = SLIST_HEAD_INITIALIZER(&mlhead);
233
static char *exnames_default[2] = { _PATH_EXPORTS, NULL };
262
static char *exnames_default[2] = { _PATH_EXPORTS, NULL };
234
static char **exnames;
263
static char **exnames;
235
static char **hosts = NULL;
264
static char **hosts = NULL;
Lines 260-266 static int have_v6 = 1; Link Here
260
289
261
static int v4root_phase = 0;
290
static int v4root_phase = 0;
262
static char v4root_dirpath[PATH_MAX + 1];
291
static char v4root_dirpath[PATH_MAX + 1];
292
static struct exportlist *v4root_ep = NULL;
263
static int has_publicfh = 0;
293
static int has_publicfh = 0;
294
static int has_set_publicfh = 0;
264
295
265
static struct pidfh *pfh = NULL;
296
static struct pidfh *pfh = NULL;
266
/* Bits for opt_flags above */
297
/* Bits for opt_flags above */
Lines 284-289 static int debug = 0; Link Here
284
#endif
315
#endif
285
316
286
/*
317
/*
318
 * The LOGDEBUG() syslog() calls are always compiled into the daemon.
319
 * To enable them, create a file at _PATH_MOUNTDDEBUG. This file can be empty.
320
 * To disable the logging, just delete the file at _PATH_MOUNTDDEBUG.
321
 */
322
static int logdebug = 0;
323
#define	LOGDEBUG(format, ...)						\
324
    (logdebug ? syslog(LOG_DEBUG, format, ## __VA_ARGS__) : 0)
325
326
/*
287
 * Similar to strsep(), but it allows for quoted strings
327
 * Similar to strsep(), but it allows for quoted strings
288
 * and escaped characters.
328
 * and escaped characters.
289
 *
329
 *
Lines 368-376 main(int argc, char **argv) Link Here
368
	in_port_t svcport;
408
	in_port_t svcport;
369
	int c, k, s;
409
	int c, k, s;
370
	int maxrec = RPC_MAXDATASIZE;
410
	int maxrec = RPC_MAXDATASIZE;
371
	int attempt_cnt, port_len, port_pos, ret;
411
	int attempt_cnt, passno, port_len, port_pos, ret;
372
	char **port_list;
412
	char **port_list;
373
413
414
	passno = 0;
374
	/* Check that another mountd isn't already running. */
415
	/* Check that another mountd isn't already running. */
375
	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
416
	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
376
	if (pfh == NULL) {
417
	if (pfh == NULL) {
Lines 385-391 main(int argc, char **argv) Link Here
385
	else
426
	else
386
		close(s);
427
		close(s);
387
428
388
	while ((c = getopt(argc, argv, "2deh:lnp:rS")) != -1)
429
	while ((c = getopt(argc, argv, "2deh:Ilnp:rS")) != -1)
389
		switch (c) {
430
		switch (c) {
390
		case '2':
431
		case '2':
391
			force_v2 = 1;
432
			force_v2 = 1;
Lines 437-442 main(int argc, char **argv) Link Here
437
		case 'S':
478
		case 'S':
438
			suspend_nfsd = 1;
479
			suspend_nfsd = 1;
439
			break;
480
			break;
481
		case 'I':
482
			passno = 1;
483
			break;
440
		default:
484
		default:
441
			usage();
485
			usage();
442
		}
486
		}
Lines 449-455 main(int argc, char **argv) Link Here
449
493
450
	argc -= optind;
494
	argc -= optind;
451
	argv += optind;
495
	argv += optind;
452
	grphead = (struct grouplist *)NULL;
453
	if (argc > 0)
496
	if (argc > 0)
454
		exnames = argv;
497
		exnames = argv;
455
	else
498
	else
Lines 457-463 main(int argc, char **argv) Link Here
457
	openlog("mountd", LOG_PID, LOG_DAEMON);
500
	openlog("mountd", LOG_PID, LOG_DAEMON);
458
	if (debug)
501
	if (debug)
459
		warnx("getting export list");
502
		warnx("getting export list");
460
	get_exportlist();
503
	get_exportlist(0);
461
	if (debug)
504
	if (debug)
462
		warnx("getting mount list");
505
		warnx("getting mount list");
463
	get_mountlist();
506
	get_mountlist();
Lines 628-634 main(int argc, char **argv) Link Here
628
	/* Expand svc_run() here so that we can call get_exportlist(). */
671
	/* Expand svc_run() here so that we can call get_exportlist(). */
629
	for (;;) {
672
	for (;;) {
630
		if (got_sighup) {
673
		if (got_sighup) {
631
			get_exportlist();
674
			get_exportlist(passno);
632
			got_sighup = 0;
675
			got_sighup = 0;
633
		}
676
		}
634
		readfds = svc_fdset;
677
		readfds = svc_fdset;
Lines 1087-1093 mntsrv(struct svc_req *rqstp, SVCXPRT *t Link Here
1087
		if (bad)
1130
		if (bad)
1088
			ep = NULL;
1131
			ep = NULL;
1089
		else
1132
		else
1090
			ep = ex_search(&fsb.f_fsid);
1133
			ep = ex_search(&fsb.f_fsid, exphead);
1091
		hostset = defset = 0;
1134
		hostset = defset = 0;
1092
		if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
1135
		if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
1093
		    &numsecflavors, &secflavorsp) ||
1136
		    &numsecflavors, &secflavorsp) ||
Lines 1302-1322 xdr_explist_common(XDR *xdrsp, caddr_t c Link Here
1302
	int false = 0;
1345
	int false = 0;
1303
	int putdef;
1346
	int putdef;
1304
	sigset_t sighup_mask;
1347
	sigset_t sighup_mask;
1348
	int i;
1305
1349
1306
	sigemptyset(&sighup_mask);
1350
	sigemptyset(&sighup_mask);
1307
	sigaddset(&sighup_mask, SIGHUP);
1351
	sigaddset(&sighup_mask, SIGHUP);
1308
	sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
1352
	sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
1309
1353
1310
	SLIST_FOREACH(ep, &exphead, entries) {
1354
	for (i = 0; i < exphashsize; i++)
1311
		putdef = 0;
1355
		SLIST_FOREACH(ep, &exphead[i], entries) {
1312
		if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
1356
			putdef = 0;
1313
			       &putdef, brief))
1357
			if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
1314
			goto errout;
1358
				       &putdef, brief))
1315
		if (ep->ex_defdir && putdef == 0 &&
1359
				goto errout;
1316
			put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL,
1360
			if (ep->ex_defdir && putdef == 0 &&
1317
			&putdef, brief))
1361
				put_exlist(ep->ex_defdir, xdrsp, NULL,
1318
			goto errout;
1362
				&putdef, brief))
1319
	}
1363
				goto errout;
1364
		}
1320
	sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
1365
	sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
1321
	if (!xdr_bool(xdrsp, &false))
1366
	if (!xdr_bool(xdrsp, &false))
1322
		return (0);
1367
		return (0);
Lines 1416-1425 static FILE *exp_file; Link Here
1416
 * Get the export list from one, currently open file
1461
 * Get the export list from one, currently open file
1417
 */
1462
 */
1418
static void
1463
static void
1419
get_exportlist_one(void)
1464
get_exportlist_one(int passno)
1420
{
1465
{
1421
	struct exportlist *ep;
1466
	struct exportlist *ep;
1422
	struct grouplist *grp, *tgrp;
1467
	struct grouplist *grp, *tgrp, *savgrp;
1423
	struct dirlist *dirhead;
1468
	struct dirlist *dirhead;
1424
	struct statfs fsb;
1469
	struct statfs fsb;
1425
	struct xucred anon;
1470
	struct xucred anon;
Lines 1540-1546 get_exportlist_one(void) Link Here
1540
					 * See if this directory is already
1585
					 * See if this directory is already
1541
					 * in the list.
1586
					 * in the list.
1542
					 */
1587
					 */
1543
					ep = ex_search(&fsb.f_fsid);
1588
					ep = ex_search(&fsb.f_fsid, exphead);
1544
					if (ep == (struct exportlist *)NULL) {
1589
					if (ep == (struct exportlist *)NULL) {
1545
					    ep = get_exp();
1590
					    ep = get_exp();
1546
					    ep->ex_fs = fsb.f_fsid;
1591
					    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.
1698
		 * Loop through hosts, pushing the exports into the kernel.
1654
		 * After loop, tgrp points to the start of the list and
1699
		 * After loop, tgrp points to the start of the list and
1655
		 * grp points to the last entry in the list.
1700
		 * grp points to the last entry in the list.
1701
		 * Do not do the do_mount() for passno == 1, since the
1702
		 * second pass will do it, as required.
1656
		 */
1703
		 */
1657
		grp = tgrp;
1704
		grp = tgrp;
1658
		do {
1705
		do {
1659
			if (do_mount(ep, grp, exflags, &anon, dirp, dirplen,
1706
			grp->gr_exflags = exflags;
1660
			    &fsb)) {
1707
			grp->gr_anon = anon;
1708
			if (v4root_phase == 2 && passno != 1)
1709
				LOGDEBUG("do_mount v4root");
1710
			if (passno != 1 && do_mount(ep, grp, exflags, &anon,
1711
			    dirp, dirplen, &fsb, ep->ex_numsecflavors,
1712
			    ep->ex_secflavors)) {
1661
				getexp_err(ep, tgrp, NULL);
1713
				getexp_err(ep, tgrp, NULL);
1662
				goto nextline;
1714
				goto nextline;
1663
			}
1715
			}
Lines 1668-1682 get_exportlist_one(void) Link Here
1668
		 */
1720
		 */
1669
		if (v4root_phase > 0 && v4root_phase <= 2) {
1721
		if (v4root_phase > 0 && v4root_phase <= 2) {
1670
			/*
1722
			/*
1671
			 * Since these structures aren't used by mountd,
1723
			 * These structures are used for the "-I" reload,
1724
			 * so save them for that case.  Otherwise, just
1672
			 * free them up now.
1725
			 * free them up now.
1673
			 */
1726
			 */
1674
			if (ep != NULL)
1727
			if (passno != 0 && ep != NULL) {
1728
				savgrp = tgrp;
1729
				while (tgrp != NULL) {
1730
					/*
1731
					 * Save the security flavors and exflags
1732
					 * for this host set in the groups.
1733
					 */
1734
					tgrp->gr_numsecflavors =
1735
					    ep->ex_numsecflavors;
1736
					if (ep->ex_numsecflavors > 0)
1737
						memcpy(tgrp->gr_secflavors,
1738
						    ep->ex_secflavors,
1739
						    sizeof(ep->ex_secflavors));
1740
					tgrp->gr_exflags = exflags;
1741
					tgrp = tgrp->gr_next;
1742
				}
1743
				if (v4root_ep == NULL) {
1744
					v4root_ep = ep;
1745
					ep = NULL;
1746
				}
1747
				grp->gr_next = v4root_ep->ex_grphead;
1748
				v4root_ep->ex_grphead = savgrp;
1749
			}
1750
			if (ep != NULL) {
1751
				if (tgrp != NULL) {
1752
					grp->gr_next = ep->ex_grphead;
1753
					ep->ex_grphead = tgrp;
1754
				}
1675
				free_exp(ep);
1755
				free_exp(ep);
1676
			while (tgrp != NULL) {
1677
				grp = tgrp;
1678
				tgrp = tgrp->gr_next;
1679
				free_grp(grp);
1680
			}
1756
			}
1681
			goto nextline;
1757
			goto nextline;
1682
		}
1758
		}
Lines 1685-1701 get_exportlist_one(void) Link Here
1685
		 * Success. Update the data structures.
1761
		 * Success. Update the data structures.
1686
		 */
1762
		 */
1687
		if (has_host) {
1763
		if (has_host) {
1688
			hang_dirp(dirhead, tgrp, ep, opt_flags);
1764
			hang_dirp(dirhead, tgrp, ep, opt_flags, &anon, exflags);
1689
			grp->gr_next = grphead;
1765
			grp->gr_next = ep->ex_grphead;
1690
			grphead = tgrp;
1766
			ep->ex_grphead = tgrp;
1691
		} else {
1767
		} else {
1692
			hang_dirp(dirhead, (struct grouplist *)NULL, ep,
1768
			hang_dirp(dirhead, (struct grouplist *)NULL, ep,
1693
				opt_flags);
1769
				opt_flags, &anon, exflags);
1694
			free_grp(grp);
1770
			free_grp(grp);
1695
		}
1771
		}
1696
		dirhead = (struct dirlist *)NULL;
1772
		dirhead = (struct dirlist *)NULL;
1697
		if ((ep->ex_flag & EX_LINKED) == 0) {
1773
		if ((ep->ex_flag & EX_LINKED) == 0) {
1698
			SLIST_INSERT_HEAD(&exphead, ep, entries);
1774
			insert_exports(ep, exphead);
1699
1775
1700
			ep->ex_flag |= EX_LINKED;
1776
			ep->ex_flag |= EX_LINKED;
1701
		}
1777
		}
Lines 1712-1758 nextline: Link Here
1712
 * Get the export list from all specified files
1788
 * Get the export list from all specified files
1713
 */
1789
 */
1714
static void
1790
static void
1715
get_exportlist(void)
1791
get_exportlist(int passno)
1716
{
1792
{
1717
	struct exportlist *ep, *ep2;
1718
	struct grouplist *grp, *tgrp;
1719
	struct export_args export;
1793
	struct export_args export;
1720
	struct iovec *iov;
1794
	struct iovec *iov;
1721
	struct statfs *fsp, *mntbufp;
1795
	struct statfs *mntbufp;
1722
	struct xvfsconf vfc;
1723
	char errmsg[255];
1796
	char errmsg[255];
1724
	int num, i;
1797
	int num, i;
1725
	int iovlen;
1798
	int iovlen;
1726
	int done;
1727
	struct nfsex_args eargs;
1799
	struct nfsex_args eargs;
1800
	FILE *debug_file;
1728
1801
1729
	if (suspend_nfsd != 0)
1802
	if ((debug_file = fopen(_PATH_MOUNTDDEBUG, "r")) != NULL) {
1730
		(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL);
1803
		fclose(debug_file);
1804
		logdebug = 1;
1805
	} else
1806
		logdebug = 0;
1807
	LOGDEBUG("passno=%d", passno);
1731
	v4root_dirpath[0] = '\0';
1808
	v4root_dirpath[0] = '\0';
1809
	free_v4rootexp();
1810
	if (passno == 1) {
1811
		/*
1812
		 * Save the current lists as old ones, so that the new lists
1813
		 * can be compared with the old ones in the 2nd pass.
1814
		 */
1815
		for (i = 0; i < exphashsize; i++) {
1816
			SLIST_FIRST(&oldexphead[i]) = SLIST_FIRST(&exphead[i]);
1817
			SLIST_INIT(&exphead[i]);
1818
		}
1819
1820
		/* Note that the public fh has not yet been set. */
1821
		has_set_publicfh = 0;
1822
1823
		/* Read the export file(s) and process them */
1824
		read_exportfile(passno);
1825
	} else {
1826
		/*
1827
		 * Just make the old lists empty.
1828
		 * exphashsize == 0 for the first call, before oldexphead
1829
		 * has been initialized-->loop won't be executed.
1830
		 */
1831
		for (i = 0; i < exphashsize; i++)
1832
			SLIST_INIT(&oldexphead[i]);
1833
	}
1834
1732
	bzero(&export, sizeof(export));
1835
	bzero(&export, sizeof(export));
1733
	export.ex_flags = MNT_DELEXPORT;
1836
	export.ex_flags = MNT_DELEXPORT;
1734
	iov = NULL;
1837
	iov = NULL;
1735
	iovlen = 0;
1838
	iovlen = 0;
1736
	bzero(errmsg, sizeof(errmsg));
1839
	bzero(errmsg, sizeof(errmsg));
1737
1840
1841
	if (suspend_nfsd != 0)
1842
		(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL);
1738
	/*
1843
	/*
1739
	 * First, get rid of the old list
1844
	 * Delete the old V4 root dir.
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
	/*
1755
	 * and the old V4 root dir.
1756
	 */
1845
	 */
1757
	bzero(&eargs, sizeof (eargs));
1846
	bzero(&eargs, sizeof (eargs));
1758
	eargs.export.ex_flags = MNT_DELEXPORT;
1847
	eargs.export.ex_flags = MNT_DELEXPORT;
Lines 1760-1826 get_exportlist(void) Link Here
1760
	    errno != ENOENT)
1849
	    errno != ENOENT)
1761
		syslog(LOG_ERR, "Can't delete exports for V4:");
1850
		syslog(LOG_ERR, "Can't delete exports for V4:");
1762
1851
1763
	/*
1852
	build_iovec(&iov, &iovlen, "fstype", NULL, 0);
1764
	 * and clear flag that notes if a public fh has been exported.
1853
	build_iovec(&iov, &iovlen, "fspath", NULL, 0);
1765
	 */
1854
	build_iovec(&iov, &iovlen, "from", NULL, 0);
1766
	has_publicfh = 0;
1855
	build_iovec(&iov, &iovlen, "update", NULL, 0);
1856
	build_iovec(&iov, &iovlen, "export", &export,
1857
	    sizeof(export));
1858
	build_iovec(&iov, &iovlen, "errmsg", errmsg,
1859
	    sizeof(errmsg));
1767
1860
1768
	/*
1861
	/*
1769
	 * And delete exports that are in the kernel for all local
1862
	 * For passno == 1, compare the old and new lists updating the kernel
1770
	 * filesystems.
1863
	 * exports for any cases that have changed.
1771
	 * XXX: Should know how to handle all local exportable filesystems.
1864
	 * This call is doing the second pass through the lists.
1865
	 * If it fails, fall back on the bulk reload.
1772
	 */
1866
	 */
1773
	num = getmntinfo(&mntbufp, MNT_NOWAIT);
1867
	if (passno == 1 && compare_nmount_exportlist(iov, iovlen, errmsg) ==
1774
1868
	    0) {
1775
	if (num > 0) {
1869
		LOGDEBUG("compareok");
1776
		build_iovec(&iov, &iovlen, "fstype", NULL, 0);
1870
		/* Free up the old lists. */
1777
		build_iovec(&iov, &iovlen, "fspath", NULL, 0);
1871
		free_exports(oldexphead);
1778
		build_iovec(&iov, &iovlen, "from", NULL, 0);
1872
	} else {
1779
		build_iovec(&iov, &iovlen, "update", NULL, 0);
1873
		LOGDEBUG("doing passno=0");
1780
		build_iovec(&iov, &iovlen, "export", &export, sizeof(export));
1874
		/*
1781
		build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
1875
		 * Clear flag that notes if a public fh has been exported.
1782
	}
1876
		 * It is set by do_mount() if MNT_EXPUBLIC is set for the entry.
1877
		 */
1878
		has_publicfh = 0;
1783
1879
1784
	for (i = 0; i < num; i++) {
1880
		/* exphead == NULL if not yet allocated (first call). */
1785
		fsp = &mntbufp[i];
1881
		if (exphead != NULL) {
1786
		if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
1882
			/*
1787
			syslog(LOG_ERR, "getvfsbyname() failed for %s",
1883
			 * First, get rid of the old lists.
1788
			    fsp->f_fstypename);
1884
			 */
1789
			continue;
1885
			free_exports(exphead);
1886
			free_exports(oldexphead);
1790
		}
1887
		}
1791
1888
1792
		/*
1889
		/*
1793
		 * We do not need to delete "export" flag from
1890
		 * And delete exports that are in the kernel for all local
1794
		 * filesystems that do not have it set.
1891
		 * filesystems.
1795
		 */
1892
		 * XXX: Should know how to handle all local exportable
1796
		if (!(fsp->f_flags & MNT_EXPORTED))
1893
		 * filesystems.
1797
		    continue;
1894
		 */
1798
		/*
1895
		num = getmntinfo(&mntbufp, MNT_NOWAIT);
1799
		 * Do not delete export for network filesystem by
1896
1800
		 * passing "export" arg to nmount().
1897
		/* Allocate hash tables, for first call. */
1801
		 * It only makes sense to do this for local filesystems.
1898
		if (exphead == NULL) {
1802
		 */
1899
			/* Target an average linked list length of 20. */
1803
		if (vfc.vfc_flags & VFCF_NETWORK)
1900
			exphashsize = num / 10;
1804
			continue;
1901
			if (exphashsize < 1)
1805
1902
				exphashsize = 1;
1806
		iov[1].iov_base = fsp->f_fstypename;
1903
			else if (exphashsize > 100000)
1807
		iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
1904
				exphashsize = 100000;
1808
		iov[3].iov_base = fsp->f_mntonname;
1905
			exphead = malloc(exphashsize * sizeof(*exphead));
1809
		iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
1906
			oldexphead = malloc(exphashsize * sizeof(*oldexphead));
1810
		iov[5].iov_base = fsp->f_mntfromname;
1907
			if (exphead == NULL || oldexphead == NULL)
1811
		iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
1908
				errx(1, "Can't malloc hash tables");
1812
		errmsg[0] = '\0';
1909
1813
1910
			for (i = 0; i < exphashsize; i++) {
1814
		/*
1911
				SLIST_INIT(&exphead[i]);
1815
		 * EXDEV is returned when path exists but is not a
1912
				SLIST_INIT(&oldexphead[i]);
1816
		 * mount point.  May happens if raced with unmount.
1913
			}
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
		}
1914
		}
1915
	
1916
		for (i = 0; i < num; i++)
1917
			delete_export(iov, iovlen, &mntbufp[i], errmsg);
1918
1919
1920
		/* Read the export file(s) and process them */
1921
		read_exportfile(0);
1824
	}
1922
	}
1825
1923
1826
	if (iov != NULL) {
1924
	if (iov != NULL) {
Lines 1838-1843 get_exportlist(void) Link Here
1838
	}
1936
	}
1839
1937
1840
	/*
1938
	/*
1939
	 * If there was no public fh, clear any previous one set.
1940
	 */
1941
	if (has_publicfh == 0)
1942
		(void) nfssvc(NFSSVC_NOPUBLICFH, NULL);
1943
1944
	/* Resume the nfsd. If they weren't suspended, this is harmless. */
1945
	(void)nfssvc(NFSSVC_RESUMENFSD, NULL);
1946
	LOGDEBUG("eo get_exportlist");
1947
}
1948
1949
/*
1950
 * Insert an export entry in the appropriate list.
1951
 */
1952
static void
1953
insert_exports(struct exportlist *ep, struct exportlisthead *exhp)
1954
{
1955
	uint32_t i;
1956
1957
	i = EXPHASH(&ep->ex_fs);
1958
	LOGDEBUG("fs=%s hash=%i", ep->ex_fsdir, i);
1959
	SLIST_INSERT_HEAD(&exhp[i], ep, entries);
1960
}
1961
1962
/*
1963
 * Free up the exports lists passed in as arguments.
1964
 */
1965
static void
1966
free_exports(struct exportlisthead *exhp)
1967
{
1968
	struct exportlist *ep, *ep2;
1969
	int i;
1970
1971
	for (i = 0; i < exphashsize; i++) {
1972
		SLIST_FOREACH_SAFE(ep, &exhp[i], entries, ep2) {
1973
			SLIST_REMOVE(&exhp[i], ep, exportlist, entries);
1974
			free_exp(ep);
1975
		}
1976
		SLIST_INIT(&exhp[i]);
1977
	}
1978
}
1979
1980
/*
1981
 * Read the exports file(s) and call get_exportlist_one() for each line.
1982
 */
1983
static void
1984
read_exportfile(int passno)
1985
{
1986
	int done, i;
1987
1988
	/*
1841
	 * Read in the exports file and build the list, calling
1989
	 * Read in the exports file and build the list, calling
1842
	 * nmount() as we go along to push the export rules into the kernel.
1990
	 * nmount() as we go along to push the export rules into the kernel.
1843
	 */
1991
	 */
Lines 1849-1855 get_exportlist(void) Link Here
1849
			syslog(LOG_WARNING, "can't open %s", exnames[i]);
1997
			syslog(LOG_WARNING, "can't open %s", exnames[i]);
1850
			continue;
1998
			continue;
1851
		}
1999
		}
1852
		get_exportlist_one();
2000
		get_exportlist_one(passno);
1853
		fclose(exp_file);
2001
		fclose(exp_file);
1854
		done++;
2002
		done++;
1855
	}
2003
	}
Lines 1857-1871 get_exportlist(void) Link Here
1857
		syslog(LOG_ERR, "can't open any exports file");
2005
		syslog(LOG_ERR, "can't open any exports file");
1858
		exit(2);
2006
		exit(2);
1859
	}
2007
	}
2008
}
2009
2010
/*
2011
 * Compare the export lists against the old ones and do nmount() operations
2012
 * for any cases that have changed.  This avoids doing nmount() for entries
2013
 * that have not changed.
2014
 * Return 0 upon success, 1 otherwise.
2015
 */
2016
static int
2017
compare_nmount_exportlist(struct iovec *iov, int iovlen, char *errmsg)
2018
{
2019
	struct exportlist *ep, *oep;
2020
	struct grouplist *grp;
2021
	struct statfs fs, ofs;
2022
	int i, ret;
1860
2023
1861
	/*
2024
	/*
1862
	 * If there was no public fh, clear any previous one set.
2025
	 * Loop through the current list and look for an entry in the old
2026
	 * list.
2027
	 * If found, check to see if it the same.
2028
	 *        If it is not the same, delete and re-export.
2029
	 *        Then mark it done on the old list.
2030
	 * else (not found)
2031
	 *        export it.
2032
	 * Any entries left in the old list after processing must have their
2033
	 * exports deleted.
1863
	 */
2034
	 */
1864
	if (has_publicfh == 0)
2035
	for (i = 0; i < exphashsize; i++)
1865
		(void) nfssvc(NFSSVC_NOPUBLICFH, NULL);
2036
		SLIST_FOREACH(ep, &exphead[i], entries) {
2037
			LOGDEBUG("foreach ep=%s", ep->ex_fsdir);
2038
			oep = ex_search(&ep->ex_fs, oldexphead);
2039
			if (oep != NULL) {
2040
				/*
2041
				 * Check the mount paths are the same.
2042
				 * If not, return 1 so that the reload of the
2043
				 * exports will be done in bulk, the
2044
				 * passno == 0 way.
2045
				 */
2046
				LOGDEBUG("found old exp");
2047
				if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0)
2048
					return (1);
2049
				LOGDEBUG("same fsdir");
2050
				/*
2051
				 * Test to see if the entry is the same.
2052
				 * If not the same delete exports and
2053
				 * re-export.
2054
				 */
2055
				if (compare_export(ep, oep) != 0) {
2056
					/*
2057
					 * Clear has_publicfh if if was set
2058
					 * in the old exports, but only if it
2059
					 * has not been set during processing of
2060
					 * the exports for this pass, as
2061
					 * indicated by has_set_publicfh.
2062
					 */
2063
					if (has_set_publicfh == 0 &&
2064
					    (oep->ex_flag & EX_PUBLICFH) != 0)
2065
						has_publicfh = 0;
1866
2066
1867
	/* Resume the nfsd. If they weren't suspended, this is harmless. */
2067
					/* Delete and re-export. */
1868
	(void)nfssvc(NFSSVC_RESUMENFSD, NULL);
2068
					if (statfs(ep->ex_fsdir, &fs) < 0)
2069
						return (1);
2070
					delete_export(iov, iovlen, &fs, errmsg);
2071
					ret = do_export_mount(ep, &fs);
2072
					if (ret != 0)
2073
						return (ret);
2074
				}
2075
				oep->ex_flag |= EX_DONE;
2076
				LOGDEBUG("exdone");
2077
			} else {
2078
				LOGDEBUG("not found so export");
2079
				/* Not found, so do export. */
2080
				if (statfs(ep->ex_fsdir, &fs) < 0)
2081
					return (1);
2082
				ret = do_export_mount(ep, &fs);
2083
				if (ret != 0)
2084
					return (ret);
2085
			}
2086
		}
2087
2088
	/* Delete exports not done. */
2089
	for (i = 0; i < exphashsize; i++)
2090
		SLIST_FOREACH(oep, &oldexphead[i], entries) {
2091
			if ((oep->ex_flag & EX_DONE) == 0) {
2092
				LOGDEBUG("not done delete=%s", oep->ex_fsdir);
2093
				if (statfs(oep->ex_fsdir, &ofs) >= 0 &&
2094
				    oep->ex_fs.val[0] == ofs.f_fsid.val[0] &&
2095
				    oep->ex_fs.val[1] == ofs.f_fsid.val[1]) {
2096
					LOGDEBUG("do delete");
2097
					delete_export(iov, iovlen, &ofs,
2098
					    errmsg);
2099
				}
2100
			}
2101
		}
2102
2103
	/* Do the V4 root exports, as required. */
2104
	grp = NULL;
2105
	if (v4root_ep != NULL)
2106
		grp = v4root_ep->ex_grphead;
2107
	v4root_phase = 2;
2108
	while (v4root_ep != NULL && grp != NULL) {
2109
		LOGDEBUG("v4root expath=%s", v4root_dirpath);
2110
		ret = do_mount(v4root_ep, grp, grp->gr_exflags, &grp->gr_anon,
2111
		    v4root_dirpath, strlen(v4root_dirpath), &fs,
2112
		    grp->gr_numsecflavors, grp->gr_secflavors);
2113
		if (ret != 0) {
2114
			v4root_phase = 0;
2115
			return (ret);
2116
		}
2117
		grp = grp->gr_next;
2118
	}
2119
	v4root_phase = 0;
2120
	free_v4rootexp();
2121
	return (0);
2122
}
2123
2124
/*
2125
 * Compare old and current exportlist entries for the fsid and return 0
2126
 * if they are the same, 1 otherwise.
2127
 */
2128
static int
2129
compare_export(struct exportlist *ep, struct exportlist *oep)
2130
{
2131
	struct grouplist *grp, *ogrp;
2132
2133
	if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0)
2134
		return (1);
2135
	if ((ep->ex_flag & EX_DEFSET) != (oep->ex_flag & EX_DEFSET))
2136
		return (1);
2137
	if ((ep->ex_defdir != NULL && oep->ex_defdir == NULL) ||
2138
	    (ep->ex_defdir == NULL && oep->ex_defdir != NULL))
2139
		return (1);
2140
	if (ep->ex_defdir != NULL && (ep->ex_defdir->dp_flag & DP_DEFSET) !=
2141
	    (oep->ex_defdir->dp_flag & DP_DEFSET))
2142
		return (1);
2143
	if ((ep->ex_flag & EX_DEFSET) != 0 && (ep->ex_defnumsecflavors !=
2144
	    oep->ex_defnumsecflavors || ep->ex_defexflags !=
2145
	    oep->ex_defexflags || compare_cred(&ep->ex_defanon,
2146
	    &oep->ex_defanon) != 0 || compare_secflavor(ep->ex_defsecflavors,
2147
	    oep->ex_defsecflavors, ep->ex_defnumsecflavors) != 0))
2148
		return (1);
2149
2150
	/* Now, check all the groups. */
2151
	for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next)
2152
		ogrp->gr_flag = 0;
2153
	for (grp = ep->ex_grphead; grp != NULL; grp = grp->gr_next) {
2154
		for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp =
2155
		    ogrp->gr_next)
2156
			if ((ogrp->gr_flag & GR_FND) == 0 &&
2157
			    grp->gr_numsecflavors == ogrp->gr_numsecflavors &&
2158
			    grp->gr_exflags == ogrp->gr_exflags &&
2159
			    compare_cred(&grp->gr_anon, &ogrp->gr_anon) == 0 &&
2160
			    compare_secflavor(grp->gr_secflavors,
2161
			    ogrp->gr_secflavors, grp->gr_numsecflavors) == 0)
2162
				break;
2163
		if (ogrp != NULL)
2164
			ogrp->gr_flag |= GR_FND;
2165
		else
2166
			return (1);
2167
	}
2168
	for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next)
2169
		if ((ogrp->gr_flag & GR_FND) == 0)
2170
			return (1);
2171
	return (0);
2172
}
2173
2174
/*
2175
 * Compare to struct xucred's.  Return 0 if the same and 1 otherwise.
2176
 * This algorithm is O(N**2) but fortunately N is always small.
2177
 */
2178
static int
2179
compare_cred(struct xucred *cr0, struct xucred *cr1)
2180
{
2181
	int i, j;
2182
2183
	if (cr0->cr_uid != cr1->cr_uid || cr0->cr_ngroups != cr1->cr_ngroups)
2184
		return (1);
2185
	for (i = 0; i < cr0->cr_ngroups; i++) {
2186
		for (j = 0; j < cr0->cr_ngroups; j++)
2187
			if (cr0->cr_groups[i] == cr1->cr_groups[j])
2188
				break;
2189
		if (j == cr0->cr_ngroups)
2190
			return (1);
2191
	}
2192
	return (0);
2193
}
2194
2195
/*
2196
 * Compare two lists of security flavors.  Return 0 if the same and 1 otherwise.
2197
 * This algorithm is O(N**2) but fortunately N is always small.
2198
 */
2199
static int
2200
compare_secflavor(int *sec1, int *sec2, int nsec)
2201
{
2202
	int i, j;
2203
2204
	for (i = 0; i < nsec; i++) {
2205
		for (j = 0; j < nsec; j++)
2206
			if (sec1[i] == sec2[j])
2207
				break;
2208
		if (j == nsec)
2209
			return (1);
2210
	}
2211
	return (0);
2212
}
2213
2214
/*
2215
 * Delete an exports entry.
2216
 */
2217
static void
2218
delete_export(struct iovec *iov, int iovlen, struct statfs *fsp, char *errmsg)
2219
{
2220
	struct xvfsconf vfc;
2221
2222
	if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
2223
		syslog(LOG_ERR, "getvfsbyname() failed for %s",
2224
		    fsp->f_fstypename);
2225
		return;
2226
	}
2227
	
2228
	/*
2229
	 * We do not need to delete "export" flag from
2230
	 * filesystems that do not have it set.
2231
	 */
2232
	if (!(fsp->f_flags & MNT_EXPORTED))
2233
		return;
2234
	/*
2235
	 * Do not delete export for network filesystem by
2236
	 * passing "export" arg to nmount().
2237
	 * It only makes sense to do this for local filesystems.
2238
	 */
2239
	if (vfc.vfc_flags & VFCF_NETWORK)
2240
		return;
2241
	
2242
	iov[1].iov_base = fsp->f_fstypename;
2243
	iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
2244
	iov[3].iov_base = fsp->f_mntonname;
2245
	iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
2246
	iov[5].iov_base = fsp->f_mntfromname;
2247
	iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
2248
	errmsg[0] = '\0';
2249
	
2250
	/*
2251
	 * EXDEV is returned when path exists but is not a
2252
	 * mount point.  May happens if raced with unmount.
2253
	 */
2254
	if (nmount(iov, iovlen, fsp->f_flags) < 0 && errno != ENOENT &&
2255
	    errno != ENOTSUP && errno != EXDEV) {
2256
		syslog(LOG_ERR,
2257
		    "can't delete exports for %s: %m %s",
2258
		    fsp->f_mntonname, errmsg);
2259
	}
1869
}
2260
}
1870
2261
1871
/*
2262
/*
Lines 1924-1934 getexp_err(struct exportlist *ep, struct Link Here
1924
 * Search the export list for a matching fs.
2315
 * Search the export list for a matching fs.
1925
 */
2316
 */
1926
static struct exportlist *
2317
static struct exportlist *
1927
ex_search(fsid_t *fsid)
2318
ex_search(fsid_t *fsid, struct exportlisthead *exhp)
1928
{
2319
{
1929
	struct exportlist *ep;
2320
	struct exportlist *ep;
2321
	uint32_t i;
1930
2322
1931
	SLIST_FOREACH(ep, &exphead, entries) {
2323
	i = EXPHASH(fsid);
2324
	SLIST_FOREACH(ep, &exhp[i], entries) {
1932
		if (ep->ex_fs.val[0] == fsid->val[0] &&
2325
		if (ep->ex_fs.val[0] == fsid->val[0] &&
1933
		    ep->ex_fs.val[1] == fsid->val[1])
2326
		    ep->ex_fs.val[1] == fsid->val[1])
1934
			return (ep);
2327
			return (ep);
Lines 1965-1971 add_expdir(struct dirlist **dpp, char *c Link Here
1965
 */
2358
 */
1966
static void
2359
static void
1967
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
2360
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
1968
	int flags)
2361
	int flags, struct xucred *anoncrp, int exflags)
1969
{
2362
{
1970
	struct hostlist *hp;
2363
	struct hostlist *hp;
1971
	struct dirlist *dp2;
2364
	struct dirlist *dp2;
Lines 1976-1987 hang_dirp(struct dirlist *dp, struct gro Link Here
1976
		else
2369
		else
1977
			ep->ex_defdir = dp;
2370
			ep->ex_defdir = dp;
1978
		if (grp == (struct grouplist *)NULL) {
2371
		if (grp == (struct grouplist *)NULL) {
2372
			ep->ex_flag |= EX_DEFSET;
1979
			ep->ex_defdir->dp_flag |= DP_DEFSET;
2373
			ep->ex_defdir->dp_flag |= DP_DEFSET;
1980
			/* Save the default security flavors list. */
2374
			/* Save the default security flavors list. */
1981
			ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2375
			ep->ex_defnumsecflavors = ep->ex_numsecflavors;
1982
			if (ep->ex_numsecflavors > 0)
2376
			if (ep->ex_numsecflavors > 0)
1983
				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2377
				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
1984
				    sizeof(ep->ex_secflavors));
2378
				    sizeof(ep->ex_secflavors));
2379
			ep->ex_defanon = *anoncrp;
2380
			ep->ex_defexflags = exflags;
1985
		} else while (grp) {
2381
		} else while (grp) {
1986
			hp = get_ht();
2382
			hp = get_ht();
1987
			hp->ht_grp = grp;
2383
			hp->ht_grp = grp;
Lines 2001-2007 hang_dirp(struct dirlist *dp, struct gro Link Here
2001
		 */
2397
		 */
2002
		while (dp) {
2398
		while (dp) {
2003
			dp2 = dp->dp_left;
2399
			dp2 = dp->dp_left;
2004
			add_dlist(&ep->ex_dirl, dp, grp, flags, ep);
2400
			add_dlist(&ep->ex_dirl, dp, grp, flags, ep, anoncrp,
2401
			    exflags);
2005
			dp = dp2;
2402
			dp = dp2;
2006
		}
2403
		}
2007
	}
2404
	}
Lines 2013-2019 hang_dirp(struct dirlist *dp, struct gro Link Here
2013
 */
2410
 */
2014
static void
2411
static void
2015
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
2412
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
2016
	int flags, struct exportlist *ep)
2413
	int flags, struct exportlist *ep, struct xucred *anoncrp, int exflags)
2017
{
2414
{
2018
	struct dirlist *dp;
2415
	struct dirlist *dp;
2019
	struct hostlist *hp;
2416
	struct hostlist *hp;
Lines 2023-2032 add_dlist(struct dirlist **dpp, struct d Link Here
2023
	if (dp) {
2420
	if (dp) {
2024
		cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
2421
		cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
2025
		if (cmp > 0) {
2422
		if (cmp > 0) {
2026
			add_dlist(&dp->dp_left, newdp, grp, flags, ep);
2423
			add_dlist(&dp->dp_left, newdp, grp, flags, ep, anoncrp,
2424
			    exflags);
2027
			return;
2425
			return;
2028
		} else if (cmp < 0) {
2426
		} else if (cmp < 0) {
2029
			add_dlist(&dp->dp_right, newdp, grp, flags, ep);
2427
			add_dlist(&dp->dp_right, newdp, grp, flags, ep, anoncrp,
2428
			    exflags);
2030
			return;
2429
			return;
2031
		} else
2430
		} else
2032
			free((caddr_t)newdp);
2431
			free((caddr_t)newdp);
Lines 2053-2064 add_dlist(struct dirlist **dpp, struct d Link Here
2053
			grp = grp->gr_next;
2452
			grp = grp->gr_next;
2054
		} while (grp);
2453
		} while (grp);
2055
	} else {
2454
	} else {
2455
		ep->ex_flag |= EX_DEFSET;
2056
		dp->dp_flag |= DP_DEFSET;
2456
		dp->dp_flag |= DP_DEFSET;
2057
		/* Save the default security flavors list. */
2457
		/* Save the default security flavors list. */
2058
		ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2458
		ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2059
		if (ep->ex_numsecflavors > 0)
2459
		if (ep->ex_numsecflavors > 0)
2060
			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2460
			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2061
			    sizeof(ep->ex_secflavors));
2461
			    sizeof(ep->ex_secflavors));
2462
		ep->ex_defanon = *anoncrp;
2463
		ep->ex_defexflags = exflags;
2062
	}
2464
	}
2063
}
2465
}
2064
2466
Lines 2403-2408 get_host(char *cp, struct grouplist *grp Link Here
2403
static void
2805
static void
2404
free_exp(struct exportlist *ep)
2806
free_exp(struct exportlist *ep)
2405
{
2807
{
2808
	struct grouplist *grp, *tgrp;
2406
2809
2407
	if (ep->ex_defdir) {
2810
	if (ep->ex_defdir) {
2408
		free_host(ep->ex_defdir->dp_hosts);
2811
		free_host(ep->ex_defdir->dp_hosts);
Lines 2413-2422 free_exp(struct exportlist *ep) Link Here
2413
	if (ep->ex_indexfile)
2816
	if (ep->ex_indexfile)
2414
		free(ep->ex_indexfile);
2817
		free(ep->ex_indexfile);
2415
	free_dir(ep->ex_dirl);
2818
	free_dir(ep->ex_dirl);
2819
	grp = ep->ex_grphead;
2820
	while (grp) {
2821
		tgrp = grp;
2822
		grp = grp->gr_next;
2823
		free_grp(tgrp);
2824
	}
2416
	free((caddr_t)ep);
2825
	free((caddr_t)ep);
2417
}
2826
}
2418
2827
2419
/*
2828
/*
2829
 * Free up the v4root exports.
2830
 */
2831
static void
2832
free_v4rootexp(void)
2833
{
2834
2835
	if (v4root_ep != NULL) {
2836
		free_exp(v4root_ep);
2837
		v4root_ep = NULL;
2838
	}
2839
}
2840
2841
/*
2420
 * Free hosts.
2842
 * Free hosts.
2421
 */
2843
 */
2422
static void
2844
static void
Lines 2456-2467 out_of_mem(void) Link Here
2456
}
2878
}
2457
2879
2458
/*
2880
/*
2881
 * Call do_mount() from the struct exportlist, for each case needed.
2882
 */
2883
static int
2884
do_export_mount(struct exportlist *ep, struct statfs *fsp)
2885
{
2886
	struct grouplist *grp, defgrp;
2887
	int ret;
2888
	size_t dirlen;
2889
2890
	LOGDEBUG("do_export_mount=%s", ep->ex_fsdir);
2891
	dirlen = strlen(ep->ex_fsdir);
2892
	if ((ep->ex_flag & EX_DEFSET) != 0) {
2893
		defgrp.gr_type = GT_DEFAULT;
2894
		defgrp.gr_next = NULL;
2895
		/* We have an entry for all other hosts/nets. */
2896
		LOGDEBUG("ex_defexflags=0x%x", ep->ex_defexflags);
2897
		ret = do_mount(ep, &defgrp, ep->ex_defexflags, &ep->ex_defanon,
2898
		    ep->ex_fsdir, dirlen, fsp, ep->ex_defnumsecflavors,
2899
		    ep->ex_defsecflavors);
2900
		if (ret != 0)
2901
			return (ret);
2902
	}
2903
2904
	/* Do a mount for each group. */
2905
	grp = ep->ex_grphead;
2906
	while (grp != NULL) {
2907
		LOGDEBUG("do mount gr_type=0x%x gr_exflags=0x%x",
2908
		    grp->gr_type, grp->gr_exflags);
2909
		ret = do_mount(ep, grp, grp->gr_exflags, &grp->gr_anon,
2910
		    ep->ex_fsdir, dirlen, fsp, grp->gr_numsecflavors,
2911
		    grp->gr_secflavors);
2912
		if (ret != 0)
2913
			return (ret);
2914
		grp = grp->gr_next;
2915
	}
2916
	return (0);
2917
}
2918
2919
/*
2459
 * Do the nmount() syscall with the update flag to push the export info into
2920
 * Do the nmount() syscall with the update flag to push the export info into
2460
 * the kernel.
2921
 * the kernel.
2461
 */
2922
 */
2462
static int
2923
static int
2463
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
2924
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
2464
    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb)
2925
    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb,
2926
    int numsecflavors, int *secflavors)
2465
{
2927
{
2466
	struct statfs fsb1;
2928
	struct statfs fsb1;
2467
	struct addrinfo *ai;
2929
	struct addrinfo *ai;
Lines 2487-2500 do_mount(struct exportlist *ep, struct g Link Here
2487
	bzero(errmsg, sizeof(errmsg));
2949
	bzero(errmsg, sizeof(errmsg));
2488
	eap->ex_flags = exflags;
2950
	eap->ex_flags = exflags;
2489
	eap->ex_anon = *anoncrp;
2951
	eap->ex_anon = *anoncrp;
2952
	LOGDEBUG("do_mount exflags=0x%x", exflags);
2490
	eap->ex_indexfile = ep->ex_indexfile;
2953
	eap->ex_indexfile = ep->ex_indexfile;
2491
	if (grp->gr_type == GT_HOST)
2954
	if (grp->gr_type == GT_HOST)
2492
		ai = grp->gr_ptr.gt_addrinfo;
2955
		ai = grp->gr_ptr.gt_addrinfo;
2493
	else
2956
	else
2494
		ai = NULL;
2957
		ai = NULL;
2495
	eap->ex_numsecflavors = ep->ex_numsecflavors;
2958
	eap->ex_numsecflavors = numsecflavors;
2959
	LOGDEBUG("do_mount numsec=%d", numsecflavors);
2496
	for (i = 0; i < eap->ex_numsecflavors; i++)
2960
	for (i = 0; i < eap->ex_numsecflavors; i++)
2497
		eap->ex_secflavors[i] = ep->ex_secflavors[i];
2961
		eap->ex_secflavors[i] = secflavors[i];
2498
	if (eap->ex_numsecflavors == 0) {
2962
	if (eap->ex_numsecflavors == 0) {
2499
		eap->ex_numsecflavors = 1;
2963
		eap->ex_numsecflavors = 1;
2500
		eap->ex_secflavors[0] = AUTH_SYS;
2964
		eap->ex_secflavors[0] = AUTH_SYS;
Lines 2658-2665 do_mount(struct exportlist *ep, struct g Link Here
2658
			else if (nfssvc(NFSSVC_PUBLICFH, (caddr_t)&fh) < 0)
3122
			else if (nfssvc(NFSSVC_PUBLICFH, (caddr_t)&fh) < 0)
2659
				syslog(LOG_ERR,
3123
				syslog(LOG_ERR,
2660
				    "Can't set public fh for %s", public_name);
3124
				    "Can't set public fh for %s", public_name);
2661
			else
3125
			else {
2662
				has_publicfh = 1;
3126
				has_publicfh = 1;
3127
				has_set_publicfh = 1;
3128
				ep->ex_flag |= EX_PUBLICFH;
3129
			}
2663
		}
3130
		}
2664
skip:
3131
skip:
2665
		if (ai != NULL)
3132
		if (ai != NULL)
Lines 2824-2841 static void Link Here
2824
nextfield(char **cp, char **endcp)
3291
nextfield(char **cp, char **endcp)
2825
{
3292
{
2826
	char *p;
3293
	char *p;
3294
	char quot = 0;
2827
3295
2828
	p = *cp;
3296
	p = *cp;
2829
	while (*p == ' ' || *p == '\t')
3297
	while (*p == ' ' || *p == '\t')
2830
		p++;
3298
		p++;
2831
	if (*p == '\n' || *p == '\0')
3299
	*cp = p;
2832
		*cp = *endcp = p;
3300
	while (*p != '\0') {
2833
	else {
3301
		if (quot) {
2834
		*cp = p++;
3302
			if (*p == quot)
2835
		while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
3303
				quot = 0;
2836
			p++;
3304
		} else {
2837
		*endcp = p;
3305
			if (*p == '\\' && *(p + 1) != '\0')
2838
	}
3306
				p++;
3307
			else if (*p == '\'' || *p == '"')
3308
				quot = *p;
3309
			else if (*p == ' ' || *p == '\t')
3310
				break;
3311
		}
3312
		p++;
3313
	};
3314
	*endcp = p;
2839
}
3315
}
2840
3316
2841
/*
3317
/*
Lines 2907-2914 parsecred(char *namelist, struct xucred Link Here
2907
	/*
3383
	/*
2908
	 * Get the user's password table entry.
3384
	 * Get the user's password table entry.
2909
	 */
3385
	 */
2910
	names = strsep_quote(&namelist, " \t\n");
3386
	names = namelist;
2911
	name = strsep(&names, ":");
3387
	name = strsep_quote(&names, ":");
2912
	/* Bug?  name could be NULL here */
3388
	/* Bug?  name could be NULL here */
2913
	if (isdigit(*name) || *name == '-')
3389
	if (isdigit(*name) || *name == '-')
2914
		pw = getpwuid(atoi(name));
3390
		pw = getpwuid(atoi(name));
Lines 2952-2958 parsecred(char *namelist, struct xucred Link Here
2952
	}
3428
	}
2953
	cr->cr_ngroups = 0;
3429
	cr->cr_ngroups = 0;
2954
	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
3430
	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
2955
		name = strsep(&names, ":");
3431
		name = strsep_quote(&names, ":");
2956
		if (isdigit(*name) || *name == '-') {
3432
		if (isdigit(*name) || *name == '-') {
2957
			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
3433
			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
2958
		} else {
3434
		} else {
(-)usr.sbin/mountd/pathnames.h (+1 lines)
Lines 36-38 Link Here
36
#define	_PATH_EXPORTS		"/etc/exports"
36
#define	_PATH_EXPORTS		"/etc/exports"
37
#define	_PATH_RMOUNTLIST	"/var/db/mountdtab"
37
#define	_PATH_RMOUNTLIST	"/var/db/mountdtab"
38
#define _PATH_MOUNTDPID		"/var/run/mountd.pid"
38
#define _PATH_MOUNTDPID		"/var/run/mountd.pid"
39
#define	_PATH_MOUNTDDEBUG	"/var/log/mountd.debug"

Return to bug 237860