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

Collapse All | Expand All

(-)usr.sbin/mountd/mountd.c (-141 / +589 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-211 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);
235
static void	usr1handler(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 *);
211
static void	nextfield(char **, char **);
238
static void	nextfield(char **, char **);
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-265 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;
293
static struct grouplist *v4root_grp = NULL;
263
static int has_publicfh = 0;
294
static int has_publicfh = 0;
264
295
265
static struct pidfh *pfh = NULL;
296
static struct pidfh *pfh = NULL;
Lines 282-287 static void SYSLOG(int, const char *, .. Link Here
282
#else
313
#else
283
static int debug = 0;
314
static int debug = 0;
284
#endif
315
#endif
316
static int logdebug = 0;
317
#define	LOGDEBUG(format, ...)						\
318
    (logdebug ? syslog(LOG_DEBUG, format, ## __VA_ARGS__) : 0)
285
319
286
/*
320
/*
287
 * Similar to strsep(), but it allows for quoted strings
321
 * Similar to strsep(), but it allows for quoted strings
Lines 368-376 main(int argc, char **argv) Link Here
368
	in_port_t svcport;
402
	in_port_t svcport;
369
	int c, k, s;
403
	int c, k, s;
370
	int maxrec = RPC_MAXDATASIZE;
404
	int maxrec = RPC_MAXDATASIZE;
371
	int attempt_cnt, port_len, port_pos, ret;
405
	int attempt_cnt, passno, port_len, port_pos, ret;
372
	char **port_list;
406
	char **port_list;
373
407
408
	passno = 0;
374
	/* Check that another mountd isn't already running. */
409
	/* Check that another mountd isn't already running. */
375
	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
410
	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
376
	if (pfh == NULL) {
411
	if (pfh == NULL) {
Lines 385-391 main(int argc, char **argv) Link Here
385
	else
420
	else
386
		close(s);
421
		close(s);
387
422
388
	while ((c = getopt(argc, argv, "2deh:lnp:rS")) != -1)
423
	while ((c = getopt(argc, argv, "2deh:Ilnp:rS")) != -1)
389
		switch (c) {
424
		switch (c) {
390
		case '2':
425
		case '2':
391
			force_v2 = 1;
426
			force_v2 = 1;
Lines 437-442 main(int argc, char **argv) Link Here
437
		case 'S':
472
		case 'S':
438
			suspend_nfsd = 1;
473
			suspend_nfsd = 1;
439
			break;
474
			break;
475
		case 'I':
476
			passno = 1;
477
			break;
440
		default:
478
		default:
441
			usage();
479
			usage();
442
		}
480
		}
Lines 449-455 main(int argc, char **argv) Link Here
449
487
450
	argc -= optind;
488
	argc -= optind;
451
	argv += optind;
489
	argv += optind;
452
	grphead = (struct grouplist *)NULL;
453
	if (argc > 0)
490
	if (argc > 0)
454
		exnames = argv;
491
		exnames = argv;
455
	else
492
	else
Lines 457-463 main(int argc, char **argv) Link Here
457
	openlog("mountd", LOG_PID, LOG_DAEMON);
494
	openlog("mountd", LOG_PID, LOG_DAEMON);
458
	if (debug)
495
	if (debug)
459
		warnx("getting export list");
496
		warnx("getting export list");
460
	get_exportlist();
497
	get_exportlist(0);
461
	if (debug)
498
	if (debug)
462
		warnx("getting mount list");
499
		warnx("getting mount list");
463
	get_mountlist();
500
	get_mountlist();
Lines 469-474 main(int argc, char **argv) Link Here
469
		signal(SIGQUIT, SIG_IGN);
506
		signal(SIGQUIT, SIG_IGN);
470
	}
507
	}
471
	signal(SIGHUP, huphandler);
508
	signal(SIGHUP, huphandler);
509
	signal(SIGUSR1, usr1handler);
472
	signal(SIGTERM, terminate);
510
	signal(SIGTERM, terminate);
473
	signal(SIGPIPE, SIG_IGN);
511
	signal(SIGPIPE, SIG_IGN);
474
512
Lines 628-634 main(int argc, char **argv) Link Here
628
	/* Expand svc_run() here so that we can call get_exportlist(). */
666
	/* Expand svc_run() here so that we can call get_exportlist(). */
629
	for (;;) {
667
	for (;;) {
630
		if (got_sighup) {
668
		if (got_sighup) {
631
			get_exportlist();
669
			get_exportlist(passno);
632
			got_sighup = 0;
670
			got_sighup = 0;
633
		}
671
		}
634
		readfds = svc_fdset;
672
		readfds = svc_fdset;
Lines 1087-1093 mntsrv(struct svc_req *rqstp, SVCXPRT *t Link Here
1087
		if (bad)
1125
		if (bad)
1088
			ep = NULL;
1126
			ep = NULL;
1089
		else
1127
		else
1090
			ep = ex_search(&fsb.f_fsid);
1128
			ep = ex_search(&fsb.f_fsid, exphead);
1091
		hostset = defset = 0;
1129
		hostset = defset = 0;
1092
		if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
1130
		if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
1093
		    &numsecflavors, &secflavorsp) ||
1131
		    &numsecflavors, &secflavorsp) ||
Lines 1302-1322 xdr_explist_common(XDR *xdrsp, caddr_t c Link Here
1302
	int false = 0;
1340
	int false = 0;
1303
	int putdef;
1341
	int putdef;
1304
	sigset_t sighup_mask;
1342
	sigset_t sighup_mask;
1343
	int i;
1305
1344
1306
	sigemptyset(&sighup_mask);
1345
	sigemptyset(&sighup_mask);
1307
	sigaddset(&sighup_mask, SIGHUP);
1346
	sigaddset(&sighup_mask, SIGHUP);
1308
	sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
1347
	sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
1309
1348
1310
	SLIST_FOREACH(ep, &exphead, entries) {
1349
	for (i = 0; i < exphashsize; i++)
1311
		putdef = 0;
1350
		SLIST_FOREACH(ep, &exphead[i], entries) {
1312
		if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
1351
			putdef = 0;
1313
			       &putdef, brief))
1352
			if (put_exlist(ep->ex_dirl, xdrsp, ep->ex_defdir,
1314
			goto errout;
1353
				       &putdef, brief))
1315
		if (ep->ex_defdir && putdef == 0 &&
1354
				goto errout;
1316
			put_exlist(ep->ex_defdir, xdrsp, (struct dirlist *)NULL,
1355
			if (ep->ex_defdir && putdef == 0 &&
1317
			&putdef, brief))
1356
				put_exlist(ep->ex_defdir, xdrsp, NULL,
1318
			goto errout;
1357
				&putdef, brief))
1319
	}
1358
				goto errout;
1359
		}
1320
	sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
1360
	sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
1321
	if (!xdr_bool(xdrsp, &false))
1361
	if (!xdr_bool(xdrsp, &false))
1322
		return (0);
1362
		return (0);
Lines 1416-1422 static FILE *exp_file; Link Here
1416
 * Get the export list from one, currently open file
1456
 * Get the export list from one, currently open file
1417
 */
1457
 */
1418
static void
1458
static void
1419
get_exportlist_one(void)
1459
get_exportlist_one(int passno)
1420
{
1460
{
1421
	struct exportlist *ep;
1461
	struct exportlist *ep;
1422
	struct grouplist *grp, *tgrp;
1462
	struct grouplist *grp, *tgrp;
Lines 1540-1546 get_exportlist_one(void) Link Here
1540
					 * See if this directory is already
1580
					 * See if this directory is already
1541
					 * in the list.
1581
					 * in the list.
1542
					 */
1582
					 */
1543
					ep = ex_search(&fsb.f_fsid);
1583
					ep = ex_search(&fsb.f_fsid, exphead);
1544
					if (ep == (struct exportlist *)NULL) {
1584
					if (ep == (struct exportlist *)NULL) {
1545
					    ep = get_exp();
1585
					    ep = get_exp();
1546
					    ep->ex_fs = fsb.f_fsid;
1586
					    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.
1693
		 * Loop through hosts, pushing the exports into the kernel.
1654
		 * After loop, tgrp points to the start of the list and
1694
		 * After loop, tgrp points to the start of the list and
1655
		 * grp points to the last entry in the list.
1695
		 * grp points to the last entry in the list.
1696
		 * Do not do the do_mount() for passno == 1, since the
1697
		 * second pass will do it, as required.
1656
		 */
1698
		 */
1657
		grp = tgrp;
1699
		grp = tgrp;
1658
		do {
1700
		do {
1659
			if (do_mount(ep, grp, exflags, &anon, dirp, dirplen,
1701
			grp->gr_exflags = exflags;
1660
			    &fsb)) {
1702
			grp->gr_anon = anon;
1703
			if (passno != 1 && do_mount(ep, grp, exflags, &anon,
1704
			    dirp, dirplen, &fsb, ep->ex_numsecflavors,
1705
			    ep->ex_secflavors)) {
1661
				getexp_err(ep, tgrp, NULL);
1706
				getexp_err(ep, tgrp, NULL);
1662
				goto nextline;
1707
				goto nextline;
1663
			}
1708
			}
Lines 1668-1682 get_exportlist_one(void) Link Here
1668
		 */
1713
		 */
1669
		if (v4root_phase > 0 && v4root_phase <= 2) {
1714
		if (v4root_phase > 0 && v4root_phase <= 2) {
1670
			/*
1715
			/*
1671
			 * Since these structures aren't used by mountd,
1716
			 * These structures are used for the "-I" reload,
1717
			 * so save them for that case.  Otherwise, just
1672
			 * free them up now.
1718
			 * free them up now.
1673
			 */
1719
			 */
1674
			if (ep != NULL)
1720
			if (passno == 1) {
1675
				free_exp(ep);
1721
				if (v4root_ep != NULL) {
1676
			while (tgrp != NULL) {
1722
					getexp_err(ep, tgrp,
1677
				grp = tgrp;
1723
					    "multiple V4 lines");
1678
				tgrp = tgrp->gr_next;
1724
					goto nextline;
1679
				free_grp(grp);
1725
				}
1726
				v4root_ep = ep;
1727
				v4root_grp = tgrp;
1728
			} else {
1729
				if (ep != NULL)
1730
					free_exp(ep);
1731
				while (tgrp != NULL) {
1732
					grp = tgrp;
1733
					tgrp = tgrp->gr_next;
1734
					free_grp(grp);
1735
				}
1680
			}
1736
			}
1681
			goto nextline;
1737
			goto nextline;
1682
		}
1738
		}
Lines 1685-1701 get_exportlist_one(void) Link Here
1685
		 * Success. Update the data structures.
1741
		 * Success. Update the data structures.
1686
		 */
1742
		 */
1687
		if (has_host) {
1743
		if (has_host) {
1688
			hang_dirp(dirhead, tgrp, ep, opt_flags);
1744
			hang_dirp(dirhead, tgrp, ep, opt_flags, &anon, exflags);
1689
			grp->gr_next = grphead;
1745
			grp->gr_next = ep->ex_grphead;
1690
			grphead = tgrp;
1746
			ep->ex_grphead = tgrp;
1691
		} else {
1747
		} else {
1692
			hang_dirp(dirhead, (struct grouplist *)NULL, ep,
1748
			hang_dirp(dirhead, (struct grouplist *)NULL, ep,
1693
				opt_flags);
1749
				opt_flags, &anon, exflags);
1694
			free_grp(grp);
1750
			free_grp(grp);
1695
		}
1751
		}
1696
		dirhead = (struct dirlist *)NULL;
1752
		dirhead = (struct dirlist *)NULL;
1697
		if ((ep->ex_flag & EX_LINKED) == 0) {
1753
		if ((ep->ex_flag & EX_LINKED) == 0) {
1698
			SLIST_INSERT_HEAD(&exphead, ep, entries);
1754
			insert_exports(ep, exphead);
1699
1755
1700
			ep->ex_flag |= EX_LINKED;
1756
			ep->ex_flag |= EX_LINKED;
1701
		}
1757
		}
Lines 1712-1756 nextline: Link Here
1712
 * Get the export list from all specified files
1768
 * Get the export list from all specified files
1713
 */
1769
 */
1714
static void
1770
static void
1715
get_exportlist(void)
1771
get_exportlist(int passno)
1716
{
1772
{
1717
	struct exportlist *ep, *ep2;
1718
	struct grouplist *grp, *tgrp;
1719
	struct export_args export;
1773
	struct export_args export;
1720
	struct iovec *iov;
1774
	struct iovec *iov;
1721
	struct statfs *fsp, *mntbufp;
1775
	struct statfs *mntbufp;
1722
	struct xvfsconf vfc;
1723
	char errmsg[255];
1776
	char errmsg[255];
1724
	int num, i;
1777
	int num, i;
1725
	int iovlen;
1778
	int iovlen;
1726
	int done;
1727
	struct nfsex_args eargs;
1779
	struct nfsex_args eargs;
1728
1780
1729
	if (suspend_nfsd != 0)
1781
	LOGDEBUG("passno=%d", passno);
1730
		(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL);
1731
	v4root_dirpath[0] = '\0';
1782
	v4root_dirpath[0] = '\0';
1783
	free_v4rootexp();
1784
	if (passno == 1) {
1785
		/*
1786
		 * Save the current lists as old ones, so that the new lists
1787
		 * can be compared with the old ones in the 2nd pass.
1788
		 */
1789
		for (i = 0; i < exphashsize; i++) {
1790
			SLIST_FIRST(&oldexphead[i]) = SLIST_FIRST(&exphead[i]);
1791
			SLIST_INIT(&exphead[i]);
1792
		}
1793
1794
		/* Read the export file(s) and process them */
1795
		read_exportfile(passno);
1796
	} else {
1797
		/*
1798
		 * Just make the old lists empty.
1799
		 * exphashsize == 0 for the first call, before oldexphead
1800
		 * has been initialized-->loop won't be executed.
1801
		 */
1802
		for (i = 0; i < exphashsize; i++)
1803
			SLIST_INIT(&oldexphead[i]);
1804
	}
1805
1732
	bzero(&export, sizeof(export));
1806
	bzero(&export, sizeof(export));
1733
	export.ex_flags = MNT_DELEXPORT;
1807
	export.ex_flags = MNT_DELEXPORT;
1734
	iov = NULL;
1808
	iov = NULL;
1735
	iovlen = 0;
1809
	iovlen = 0;
1736
	bzero(errmsg, sizeof(errmsg));
1810
	bzero(errmsg, sizeof(errmsg));
1737
1811
1738
	/*
1812
	if (suspend_nfsd != 0)
1739
	 * First, get rid of the old list
1813
		(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
	/*
1814
	/*
1755
	 * and the old V4 root dir.
1815
	 * and the old V4 root dir.
1756
	 */
1816
	 */
Lines 1765-1826 get_exportlist(void) Link Here
1765
	 */
1825
	 */
1766
	has_publicfh = 0;
1826
	has_publicfh = 0;
1767
1827
1828
	build_iovec(&iov, &iovlen, "fstype", NULL, 0);
1829
	build_iovec(&iov, &iovlen, "fspath", NULL, 0);
1830
	build_iovec(&iov, &iovlen, "from", NULL, 0);
1831
	build_iovec(&iov, &iovlen, "update", NULL, 0);
1832
	build_iovec(&iov, &iovlen, "export", &export,
1833
	    sizeof(export));
1834
	build_iovec(&iov, &iovlen, "errmsg", errmsg,
1835
	    sizeof(errmsg));
1836
1768
	/*
1837
	/*
1769
	 * And delete exports that are in the kernel for all local
1838
	 * For passno == 1, compare the old and new lists updating the kernel
1770
	 * filesystems.
1839
	 * exports for any cases that have changed.
1771
	 * XXX: Should know how to handle all local exportable filesystems.
1840
	 * This call is doing the second pass through the lists.
1841
	 * If it fails, fall back on the bulk reload.
1772
	 */
1842
	 */
1773
	num = getmntinfo(&mntbufp, MNT_NOWAIT);
1843
	if (passno == 1 && compare_nmount_exportlist(iov, iovlen, errmsg) ==
1774
1844
	    0) {
1775
	if (num > 0) {
1845
		LOGDEBUG("compareok");
1776
		build_iovec(&iov, &iovlen, "fstype", NULL, 0);
1846
		/* Free up the old lists. */
1777
		build_iovec(&iov, &iovlen, "fspath", NULL, 0);
1847
		free_exports(oldexphead);
1778
		build_iovec(&iov, &iovlen, "from", NULL, 0);
1848
	} else {
1779
		build_iovec(&iov, &iovlen, "update", NULL, 0);
1849
		LOGDEBUG("doing passno=0");
1780
		build_iovec(&iov, &iovlen, "export", &export, sizeof(export));
1850
		/* exphead == NULL if not yet allocated (first call). */
1781
		build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
1851
		if (exphead != NULL) {
1782
	}
1852
			/*
1783
1853
			 * First, get rid of the old lists.
1784
	for (i = 0; i < num; i++) {
1854
			 */
1785
		fsp = &mntbufp[i];
1855
			free_exports(exphead);
1786
		if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
1856
			free_exports(oldexphead);
1787
			syslog(LOG_ERR, "getvfsbyname() failed for %s",
1788
			    fsp->f_fstypename);
1789
			continue;
1790
		}
1857
		}
1858
		free_v4rootexp();
1791
1859
1792
		/*
1860
		/*
1793
		 * We do not need to delete "export" flag from
1861
		 * And delete exports that are in the kernel for all local
1794
		 * filesystems that do not have it set.
1862
		 * filesystems.
1795
		 */
1863
		 * XXX: Should know how to handle all local exportable
1796
		if (!(fsp->f_flags & MNT_EXPORTED))
1864
		 * filesystems.
1797
		    continue;
1865
		 */
1798
		/*
1866
		num = getmntinfo(&mntbufp, MNT_NOWAIT);
1799
		 * Do not delete export for network filesystem by
1867
1800
		 * passing "export" arg to nmount().
1868
		/* Allocate hash tables, for first call. */
1801
		 * It only makes sense to do this for local filesystems.
1869
		if (exphead == NULL) {
1802
		 */
1870
			/* Target an average linked list length of 20. */
1803
		if (vfc.vfc_flags & VFCF_NETWORK)
1871
			exphashsize = num / 10;
1804
			continue;
1872
			if (exphashsize < 1)
1805
1873
				exphashsize = 1;
1806
		iov[1].iov_base = fsp->f_fstypename;
1874
			else if (exphashsize > 100000)
1807
		iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
1875
				exphashsize = 100000;
1808
		iov[3].iov_base = fsp->f_mntonname;
1876
			exphead = malloc(exphashsize * sizeof(*exphead));
1809
		iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
1877
			oldexphead = malloc(exphashsize * sizeof(*oldexphead));
1810
		iov[5].iov_base = fsp->f_mntfromname;
1878
			if (exphead == NULL || oldexphead == NULL)
1811
		iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
1879
				errx(1, "Can't malloc hash tables");
1812
		errmsg[0] = '\0';
1880
1813
1881
			for (i = 0; i < exphashsize; i++) {
1814
		/*
1882
				SLIST_INIT(&exphead[i]);
1815
		 * EXDEV is returned when path exists but is not a
1883
				SLIST_INIT(&oldexphead[i]);
1816
		 * mount point.  May happens if raced with unmount.
1884
			}
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
		}
1885
		}
1886
	
1887
		for (i = 0; i < num; i++)
1888
			delete_export(iov, iovlen, &mntbufp[i], errmsg);
1889
1890
1891
		/* Read the export file(s) and process them */
1892
		read_exportfile(0);
1824
	}
1893
	}
1825
1894
1826
	if (iov != NULL) {
1895
	if (iov != NULL) {
Lines 1838-1843 get_exportlist(void) Link Here
1838
	}
1907
	}
1839
1908
1840
	/*
1909
	/*
1910
	 * If there was no public fh, clear any previous one set.
1911
	 */
1912
	if (has_publicfh == 0)
1913
		(void) nfssvc(NFSSVC_NOPUBLICFH, NULL);
1914
1915
	/* Resume the nfsd. If they weren't suspended, this is harmless. */
1916
	(void)nfssvc(NFSSVC_RESUMENFSD, NULL);
1917
	LOGDEBUG("eo get_exportlist");
1918
}
1919
1920
/*
1921
 * Insert an export entry in the appropriate list.
1922
 */
1923
static void
1924
insert_exports(struct exportlist *ep, struct exportlisthead *exhp)
1925
{
1926
	uint32_t i;
1927
1928
	i = EXPHASH(&ep->ex_fs);
1929
	LOGDEBUG("fs=%s hash=%i", ep->ex_fsdir, i);
1930
	SLIST_INSERT_HEAD(&exhp[i], ep, entries);
1931
}
1932
1933
/*
1934
 * Free up the exports lists passed in as arguments.
1935
 */
1936
static void
1937
free_exports(struct exportlisthead *exhp)
1938
{
1939
	struct exportlist *ep, *ep2;
1940
	int i;
1941
1942
	for (i = 0; i < exphashsize; i++) {
1943
		SLIST_FOREACH_SAFE(ep, &exhp[i], entries, ep2) {
1944
			SLIST_REMOVE(&exhp[i], ep, exportlist, entries);
1945
			free_exp(ep);
1946
		}
1947
		SLIST_INIT(&exhp[i]);
1948
	}
1949
}
1950
1951
/*
1952
 * Read the exports file(s) and call get_exportlist_one() for each line.
1953
 */
1954
static void
1955
read_exportfile(int passno)
1956
{
1957
	int done, i;
1958
1959
	/*
1841
	 * Read in the exports file and build the list, calling
1960
	 * Read in the exports file and build the list, calling
1842
	 * nmount() as we go along to push the export rules into the kernel.
1961
	 * nmount() as we go along to push the export rules into the kernel.
1843
	 */
1962
	 */
Lines 1849-1855 get_exportlist(void) Link Here
1849
			syslog(LOG_WARNING, "can't open %s", exnames[i]);
1968
			syslog(LOG_WARNING, "can't open %s", exnames[i]);
1850
			continue;
1969
			continue;
1851
		}
1970
		}
1852
		get_exportlist_one();
1971
		get_exportlist_one(passno);
1853
		fclose(exp_file);
1972
		fclose(exp_file);
1854
		done++;
1973
		done++;
1855
	}
1974
	}
Lines 1857-1871 get_exportlist(void) Link Here
1857
		syslog(LOG_ERR, "can't open any exports file");
1976
		syslog(LOG_ERR, "can't open any exports file");
1858
		exit(2);
1977
		exit(2);
1859
	}
1978
	}
1979
}
1980
1981
/*
1982
 * Compare the export lists against the old ones and do nmount() operations
1983
 * for any cases that have changed.  This avoids doing nmount() for entries
1984
 * that have not changed.
1985
 * Return 0 upon success, 1 otherwise.
1986
 */
1987
static int
1988
compare_nmount_exportlist(struct iovec *iov, int iovlen, char *errmsg)
1989
{
1990
	struct exportlist *ep, *oep;
1991
	struct grouplist *grp;
1992
	struct statfs fs, ofs;
1993
	int i, ret;
1860
1994
1861
	/*
1995
	/*
1862
	 * If there was no public fh, clear any previous one set.
1996
	 * Loop through the current list and look for an entry in the old
1997
	 * list.
1998
	 * If found, check to see if it the same.
1999
	 *        If it is not the same, delete and re-export.
2000
	 *        Then mark it done on the old list.
2001
	 * else (not found)
2002
	 *        export it.
2003
	 * Any entries left in the old list after processing must have their
2004
	 * exports deleted.
1863
	 */
2005
	 */
1864
	if (has_publicfh == 0)
2006
	for (i = 0; i < exphashsize; i++)
1865
		(void) nfssvc(NFSSVC_NOPUBLICFH, NULL);
2007
		SLIST_FOREACH(ep, &exphead[i], entries) {
2008
			LOGDEBUG("foreach ep=%s", ep->ex_fsdir);
2009
			oep = ex_search(&ep->ex_fs, oldexphead);
2010
			if (oep != NULL) {
2011
				/*
2012
				 * Check the mount paths are the same.
2013
				 * If not, return 1 so that the reload of the
2014
				 * exports will be done in bulk, the
2015
				 * passno == 0 way.
2016
				 */
2017
				LOGDEBUG("found old exp");
2018
				if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0)
2019
					return (1);
2020
				LOGDEBUG("same fsdir");
2021
				/*
2022
				 * Test to see if the entry is the same.
2023
				 * If not the same delete exports and
2024
				 * re-export.
2025
				 */
2026
				if (compare_export(ep, oep) != 0) {
2027
					if (statfs(ep->ex_fsdir, &fs) < 0)
2028
						return (1);
2029
					delete_export(iov, iovlen, &fs, errmsg);
2030
					ret = do_export_mount(ep, &fs);
2031
					if (ret != 0)
2032
						return (ret);
2033
				}
2034
				oep->ex_flag |= EX_DONE;
2035
				LOGDEBUG("exdone");
2036
			} else {
2037
				LOGDEBUG("not found so export");
2038
				/* Not found, so do export. */
2039
				if (statfs(ep->ex_fsdir, &fs) < 0)
2040
					return (1);
2041
				ret = do_export_mount(ep, &fs);
2042
				if (ret != 0)
2043
					return (ret);
2044
			}
2045
		}
1866
2046
1867
	/* Resume the nfsd. If they weren't suspended, this is harmless. */
2047
	/* Delete exports not done. */
1868
	(void)nfssvc(NFSSVC_RESUMENFSD, NULL);
2048
	for (i = 0; i < exphashsize; i++)
2049
		SLIST_FOREACH(oep, &oldexphead[i], entries) {
2050
			if ((oep->ex_flag & EX_DONE) == 0) {
2051
				LOGDEBUG("not done delete=%s", oep->ex_fsdir);
2052
				if (statfs(oep->ex_fsdir, &ofs) >= 0 &&
2053
				    oep->ex_fs.val[0] == ofs.f_fsid.val[0] &&
2054
				    oep->ex_fs.val[1] == ofs.f_fsid.val[1]) {
2055
					LOGDEBUG("do delete");
2056
					delete_export(iov, iovlen, &ofs,
2057
					    errmsg);
2058
				}
2059
			}
2060
		}
2061
2062
	/* Do the V4 root exports, as required. */
2063
	grp = v4root_grp;
2064
	v4root_phase = 2;
2065
	while (v4root_ep != NULL && grp != NULL) {
2066
		LOGDEBUG("v4root expath=%s", v4root_dirpath);
2067
		ret = do_mount(v4root_ep, grp, grp->gr_exflags, &grp->gr_anon,
2068
		    v4root_dirpath, strlen(v4root_dirpath), &fs,
2069
		    v4root_ep->ex_numsecflavors, v4root_ep->ex_secflavors);
2070
		if (ret != 0) {
2071
			v4root_phase = 0;
2072
			return (ret);
2073
		}
2074
		grp = grp->gr_next;
2075
	}
2076
	v4root_phase = 0;
2077
	free_v4rootexp();
2078
	return (0);
2079
}
2080
2081
/*
2082
 * Compare old and current exportlist entries for the fsid and return 0
2083
 * if they are the same, 1 otherwise.
2084
 */
2085
static int
2086
compare_export(struct exportlist *ep, struct exportlist *oep)
2087
{
2088
	struct grouplist *grp, *ogrp;
2089
2090
	if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0)
2091
		return (1);
2092
	if ((ep->ex_flag & EX_DEFSET) != (oep->ex_flag & EX_DEFSET))
2093
		return (1);
2094
	if ((ep->ex_defdir != NULL && oep->ex_defdir == NULL) ||
2095
	    (ep->ex_defdir == NULL && oep->ex_defdir != NULL))
2096
		return (1);
2097
	if (ep->ex_defdir != NULL && (ep->ex_defdir->dp_flag & DP_DEFSET) !=
2098
	    (oep->ex_defdir->dp_flag & DP_DEFSET))
2099
		return (1);
2100
	if ((ep->ex_flag & EX_DEFSET) != 0 && (ep->ex_defnumsecflavors !=
2101
	    oep->ex_defnumsecflavors || ep->ex_defexflags !=
2102
	    oep->ex_defexflags || compare_cred(&ep->ex_defanon,
2103
	    &oep->ex_defanon) != 0 || compare_secflavor(ep->ex_defsecflavors,
2104
	    oep->ex_defsecflavors, ep->ex_defnumsecflavors) != 0))
2105
		return (1);
2106
2107
	/* Now, check all the groups. */
2108
	for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next)
2109
		ogrp->gr_flag = 0;
2110
	for (grp = ep->ex_grphead; grp != NULL; grp = grp->gr_next) {
2111
		for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp =
2112
		    ogrp->gr_next)
2113
			if ((ogrp->gr_flag & GR_FND) == 0 &&
2114
			    grp->gr_numsecflavors == ogrp->gr_numsecflavors &&
2115
			    grp->gr_exflags == ogrp->gr_exflags &&
2116
			    compare_cred(&grp->gr_anon, &ogrp->gr_anon) == 0 &&
2117
			    compare_secflavor(grp->gr_secflavors,
2118
			    ogrp->gr_secflavors, grp->gr_numsecflavors) == 0)
2119
				break;
2120
		if (ogrp != NULL)
2121
			ogrp->gr_flag |= GR_FND;
2122
		else
2123
			return (1);
2124
	}
2125
	for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next)
2126
		if ((ogrp->gr_flag & GR_FND) == 0)
2127
			return (1);
2128
	return (0);
2129
}
2130
2131
/*
2132
 * Compare to struct xucred's.  Return 0 if the same and 1 otherwise.
2133
 * This algorithm is O(N**2) but fortunately N is always small.
2134
 */
2135
static int
2136
compare_cred(struct xucred *cr0, struct xucred *cr1)
2137
{
2138
	int i, j;
2139
2140
	if (cr0->cr_uid != cr1->cr_uid || cr0->cr_ngroups != cr1->cr_ngroups)
2141
		return (1);
2142
	for (i = 0; i < cr0->cr_ngroups; i++) {
2143
		for (j = 0; j < cr0->cr_ngroups; j++)
2144
			if (cr0->cr_groups[i] == cr1->cr_groups[j])
2145
				break;
2146
		if (j == cr0->cr_ngroups)
2147
			return (1);
2148
	}
2149
	return (0);
2150
}
2151
2152
/*
2153
 * Compare two lists of security flavors.  Return 0 if the same and 1 otherwise.
2154
 * This algorithm is O(N**2) but fortunately N is always small.
2155
 */
2156
static int
2157
compare_secflavor(int *sec1, int *sec2, int nsec)
2158
{
2159
	int i, j;
2160
2161
	for (i = 0; i < nsec; i++) {
2162
		for (j = 0; j < nsec; j++)
2163
			if (sec1[i] == sec2[j])
2164
				break;
2165
		if (j == nsec)
2166
			return (1);
2167
	}
2168
	return (0);
2169
}
2170
2171
/*
2172
 * Delete an exports entry.
2173
 */
2174
static void
2175
delete_export(struct iovec *iov, int iovlen, struct statfs *fsp, char *errmsg)
2176
{
2177
	struct xvfsconf vfc;
2178
2179
	if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) {
2180
		syslog(LOG_ERR, "getvfsbyname() failed for %s",
2181
		    fsp->f_fstypename);
2182
		return;
2183
	}
2184
	
2185
	/*
2186
	 * We do not need to delete "export" flag from
2187
	 * filesystems that do not have it set.
2188
	 */
2189
	if (!(fsp->f_flags & MNT_EXPORTED))
2190
		return;
2191
	/*
2192
	 * Do not delete export for network filesystem by
2193
	 * passing "export" arg to nmount().
2194
	 * It only makes sense to do this for local filesystems.
2195
	 */
2196
	if (vfc.vfc_flags & VFCF_NETWORK)
2197
		return;
2198
	
2199
	iov[1].iov_base = fsp->f_fstypename;
2200
	iov[1].iov_len = strlen(fsp->f_fstypename) + 1;
2201
	iov[3].iov_base = fsp->f_mntonname;
2202
	iov[3].iov_len = strlen(fsp->f_mntonname) + 1;
2203
	iov[5].iov_base = fsp->f_mntfromname;
2204
	iov[5].iov_len = strlen(fsp->f_mntfromname) + 1;
2205
	errmsg[0] = '\0';
2206
	
2207
	/*
2208
	 * EXDEV is returned when path exists but is not a
2209
	 * mount point.  May happens if raced with unmount.
2210
	 */
2211
	if (nmount(iov, iovlen, fsp->f_flags) < 0 && errno != ENOENT &&
2212
	    errno != ENOTSUP && errno != EXDEV) {
2213
		syslog(LOG_ERR,
2214
		    "can't delete exports for %s: %m %s",
2215
		    fsp->f_mntonname, errmsg);
2216
	}
1869
}
2217
}
1870
2218
1871
/*
2219
/*
Lines 1924-1934 getexp_err(struct exportlist *ep, struct Link Here
1924
 * Search the export list for a matching fs.
2272
 * Search the export list for a matching fs.
1925
 */
2273
 */
1926
static struct exportlist *
2274
static struct exportlist *
1927
ex_search(fsid_t *fsid)
2275
ex_search(fsid_t *fsid, struct exportlisthead *exhp)
1928
{
2276
{
1929
	struct exportlist *ep;
2277
	struct exportlist *ep;
2278
	uint32_t i;
1930
2279
1931
	SLIST_FOREACH(ep, &exphead, entries) {
2280
	i = EXPHASH(fsid);
2281
	SLIST_FOREACH(ep, &exhp[i], entries) {
1932
		if (ep->ex_fs.val[0] == fsid->val[0] &&
2282
		if (ep->ex_fs.val[0] == fsid->val[0] &&
1933
		    ep->ex_fs.val[1] == fsid->val[1])
2283
		    ep->ex_fs.val[1] == fsid->val[1])
1934
			return (ep);
2284
			return (ep);
Lines 1965-1971 add_expdir(struct dirlist **dpp, char *c Link Here
1965
 */
2315
 */
1966
static void
2316
static void
1967
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
2317
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
1968
	int flags)
2318
	int flags, struct xucred *anoncrp, int exflags)
1969
{
2319
{
1970
	struct hostlist *hp;
2320
	struct hostlist *hp;
1971
	struct dirlist *dp2;
2321
	struct dirlist *dp2;
Lines 1976-1987 hang_dirp(struct dirlist *dp, struct gro Link Here
1976
		else
2326
		else
1977
			ep->ex_defdir = dp;
2327
			ep->ex_defdir = dp;
1978
		if (grp == (struct grouplist *)NULL) {
2328
		if (grp == (struct grouplist *)NULL) {
2329
			ep->ex_flag |= EX_DEFSET;
1979
			ep->ex_defdir->dp_flag |= DP_DEFSET;
2330
			ep->ex_defdir->dp_flag |= DP_DEFSET;
1980
			/* Save the default security flavors list. */
2331
			/* Save the default security flavors list. */
1981
			ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2332
			ep->ex_defnumsecflavors = ep->ex_numsecflavors;
1982
			if (ep->ex_numsecflavors > 0)
2333
			if (ep->ex_numsecflavors > 0)
1983
				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2334
				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
1984
				    sizeof(ep->ex_secflavors));
2335
				    sizeof(ep->ex_secflavors));
2336
			ep->ex_defanon = *anoncrp;
2337
			ep->ex_defexflags = exflags;
1985
		} else while (grp) {
2338
		} else while (grp) {
1986
			hp = get_ht();
2339
			hp = get_ht();
1987
			hp->ht_grp = grp;
2340
			hp->ht_grp = grp;
Lines 2001-2007 hang_dirp(struct dirlist *dp, struct gro Link Here
2001
		 */
2354
		 */
2002
		while (dp) {
2355
		while (dp) {
2003
			dp2 = dp->dp_left;
2356
			dp2 = dp->dp_left;
2004
			add_dlist(&ep->ex_dirl, dp, grp, flags, ep);
2357
			add_dlist(&ep->ex_dirl, dp, grp, flags, ep, anoncrp,
2358
			    exflags);
2005
			dp = dp2;
2359
			dp = dp2;
2006
		}
2360
		}
2007
	}
2361
	}
Lines 2013-2019 hang_dirp(struct dirlist *dp, struct gro Link Here
2013
 */
2367
 */
2014
static void
2368
static void
2015
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
2369
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
2016
	int flags, struct exportlist *ep)
2370
	int flags, struct exportlist *ep, struct xucred *anoncrp, int exflags)
2017
{
2371
{
2018
	struct dirlist *dp;
2372
	struct dirlist *dp;
2019
	struct hostlist *hp;
2373
	struct hostlist *hp;
Lines 2023-2032 add_dlist(struct dirlist **dpp, struct d Link Here
2023
	if (dp) {
2377
	if (dp) {
2024
		cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
2378
		cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
2025
		if (cmp > 0) {
2379
		if (cmp > 0) {
2026
			add_dlist(&dp->dp_left, newdp, grp, flags, ep);
2380
			add_dlist(&dp->dp_left, newdp, grp, flags, ep, anoncrp,
2381
			    exflags);
2027
			return;
2382
			return;
2028
		} else if (cmp < 0) {
2383
		} else if (cmp < 0) {
2029
			add_dlist(&dp->dp_right, newdp, grp, flags, ep);
2384
			add_dlist(&dp->dp_right, newdp, grp, flags, ep, anoncrp,
2385
			    exflags);
2030
			return;
2386
			return;
2031
		} else
2387
		} else
2032
			free((caddr_t)newdp);
2388
			free((caddr_t)newdp);
Lines 2053-2064 add_dlist(struct dirlist **dpp, struct d Link Here
2053
			grp = grp->gr_next;
2409
			grp = grp->gr_next;
2054
		} while (grp);
2410
		} while (grp);
2055
	} else {
2411
	} else {
2412
		ep->ex_flag |= EX_DEFSET;
2056
		dp->dp_flag |= DP_DEFSET;
2413
		dp->dp_flag |= DP_DEFSET;
2057
		/* Save the default security flavors list. */
2414
		/* Save the default security flavors list. */
2058
		ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2415
		ep->ex_defnumsecflavors = ep->ex_numsecflavors;
2059
		if (ep->ex_numsecflavors > 0)
2416
		if (ep->ex_numsecflavors > 0)
2060
			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2417
			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
2061
			    sizeof(ep->ex_secflavors));
2418
			    sizeof(ep->ex_secflavors));
2419
		ep->ex_defanon = *anoncrp;
2420
		ep->ex_defexflags = exflags;
2062
	}
2421
	}
2063
}
2422
}
2064
2423
Lines 2403-2408 get_host(char *cp, struct grouplist *grp Link Here
2403
static void
2762
static void
2404
free_exp(struct exportlist *ep)
2763
free_exp(struct exportlist *ep)
2405
{
2764
{
2765
	struct grouplist *grp, *tgrp;
2406
2766
2407
	if (ep->ex_defdir) {
2767
	if (ep->ex_defdir) {
2408
		free_host(ep->ex_defdir->dp_hosts);
2768
		free_host(ep->ex_defdir->dp_hosts);
Lines 2413-2422 free_exp(struct exportlist *ep) Link Here
2413
	if (ep->ex_indexfile)
2773
	if (ep->ex_indexfile)
2414
		free(ep->ex_indexfile);
2774
		free(ep->ex_indexfile);
2415
	free_dir(ep->ex_dirl);
2775
	free_dir(ep->ex_dirl);
2776
	grp = ep->ex_grphead;
2777
	while (grp) {
2778
		tgrp = grp;
2779
		grp = grp->gr_next;
2780
		free_grp(tgrp);
2781
	}
2416
	free((caddr_t)ep);
2782
	free((caddr_t)ep);
2417
}
2783
}
2418
2784
2419
/*
2785
/*
2786
 * Free up the v4root exports.
2787
 */
2788
static void
2789
free_v4rootexp(void)
2790
{
2791
	struct grouplist *grp, *tgrp;
2792
2793
	if (v4root_ep != NULL) {
2794
		free_exp(v4root_ep);
2795
		v4root_ep = NULL;
2796
	}
2797
	tgrp = v4root_grp;
2798
	v4root_grp = NULL;
2799
	while (tgrp != NULL) {
2800
		grp = tgrp;
2801
		tgrp = tgrp->gr_next;
2802
		free_grp(grp);
2803
	}
2804
}
2805
2806
/*
2420
 * Free hosts.
2807
 * Free hosts.
2421
 */
2808
 */
2422
static void
2809
static void
Lines 2456-2467 out_of_mem(void) Link Here
2456
}
2843
}
2457
2844
2458
/*
2845
/*
2846
 * Call do_mount() from the struct exportlist, for each case needed.
2847
 */
2848
static int
2849
do_export_mount(struct exportlist *ep, struct statfs *fsp)
2850
{
2851
	struct grouplist *grp, defgrp;
2852
	int ret;
2853
	size_t dirlen;
2854
2855
	LOGDEBUG("do_mount_export=%s", ep->ex_fsdir);
2856
	dirlen = strlen(ep->ex_fsdir);
2857
	if ((ep->ex_flag & EX_DEFSET) != 0) {
2858
		defgrp.gr_type = GT_DEFAULT;
2859
		defgrp.gr_next = NULL;
2860
		/* We have an entry for all other hosts/nets. */
2861
		LOGDEBUG("ex_defexflags=0x%x", ep->ex_defexflags);
2862
		ret = do_mount(ep, &defgrp, ep->ex_defexflags, &ep->ex_defanon,
2863
		    ep->ex_fsdir, dirlen, fsp, ep->ex_defnumsecflavors,
2864
		    ep->ex_defsecflavors);
2865
		if (ret != 0)
2866
			return (ret);
2867
	}
2868
2869
	/* Do a mount for each group. */
2870
	grp = ep->ex_grphead;
2871
	while (grp != NULL) {
2872
		LOGDEBUG("do mount gr_type=0x%x gr_exflags=0x%x",
2873
		    grp->gr_type, grp->gr_exflags);
2874
		ret = do_mount(ep, grp, grp->gr_exflags, &grp->gr_anon,
2875
		    ep->ex_fsdir, dirlen, fsp, grp->gr_numsecflavors,
2876
		    grp->gr_secflavors);
2877
		if (ret != 0)
2878
			return (ret);
2879
		grp = grp->gr_next;
2880
	}
2881
	return (0);
2882
}
2883
2884
/*
2459
 * Do the nmount() syscall with the update flag to push the export info into
2885
 * Do the nmount() syscall with the update flag to push the export info into
2460
 * the kernel.
2886
 * the kernel.
2461
 */
2887
 */
2462
static int
2888
static int
2463
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
2889
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
2464
    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb)
2890
    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb,
2891
    int numsecflavors, int *secflavors)
2465
{
2892
{
2466
	struct statfs fsb1;
2893
	struct statfs fsb1;
2467
	struct addrinfo *ai;
2894
	struct addrinfo *ai;
Lines 2487-2500 do_mount(struct exportlist *ep, struct g Link Here
2487
	bzero(errmsg, sizeof(errmsg));
2914
	bzero(errmsg, sizeof(errmsg));
2488
	eap->ex_flags = exflags;
2915
	eap->ex_flags = exflags;
2489
	eap->ex_anon = *anoncrp;
2916
	eap->ex_anon = *anoncrp;
2917
	LOGDEBUG("do_mount exflags=0x%x", exflags);
2490
	eap->ex_indexfile = ep->ex_indexfile;
2918
	eap->ex_indexfile = ep->ex_indexfile;
2491
	if (grp->gr_type == GT_HOST)
2919
	if (grp->gr_type == GT_HOST)
2492
		ai = grp->gr_ptr.gt_addrinfo;
2920
		ai = grp->gr_ptr.gt_addrinfo;
2493
	else
2921
	else
2494
		ai = NULL;
2922
		ai = NULL;
2495
	eap->ex_numsecflavors = ep->ex_numsecflavors;
2923
	eap->ex_numsecflavors = numsecflavors;
2924
	LOGDEBUG("do_mount numsec=%d", numsecflavors);
2496
	for (i = 0; i < eap->ex_numsecflavors; i++)
2925
	for (i = 0; i < eap->ex_numsecflavors; i++)
2497
		eap->ex_secflavors[i] = ep->ex_secflavors[i];
2926
		eap->ex_secflavors[i] = secflavors[i];
2498
	if (eap->ex_numsecflavors == 0) {
2927
	if (eap->ex_numsecflavors == 0) {
2499
		eap->ex_numsecflavors = 1;
2928
		eap->ex_numsecflavors = 1;
2500
		eap->ex_secflavors[0] = AUTH_SYS;
2929
		eap->ex_secflavors[0] = AUTH_SYS;
Lines 2824-2841 static void Link Here
2824
nextfield(char **cp, char **endcp)
3253
nextfield(char **cp, char **endcp)
2825
{
3254
{
2826
	char *p;
3255
	char *p;
3256
	char quot = 0;
2827
3257
2828
	p = *cp;
3258
	p = *cp;
2829
	while (*p == ' ' || *p == '\t')
3259
	while (*p == ' ' || *p == '\t')
2830
		p++;
3260
		p++;
2831
	if (*p == '\n' || *p == '\0')
3261
	*cp = p;
2832
		*cp = *endcp = p;
3262
	while (*p != '\0') {
2833
	else {
3263
		if (quot) {
2834
		*cp = p++;
3264
			if (*p == quot)
2835
		while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
3265
				quot = 0;
2836
			p++;
3266
		} else {
2837
		*endcp = p;
3267
			if (*p == '\\' && *(p + 1) != '\0')
2838
	}
3268
				p++;
3269
			else if (*p == '\'' || *p == '"')
3270
				quot = *p;
3271
			else if (*p == ' ' || *p == '\t')
3272
				break;
3273
		}
3274
		p++;
3275
	};
3276
	*endcp = p;
2839
}
3277
}
2840
3278
2841
/*
3279
/*
Lines 2907-2914 parsecred(char *namelist, struct xucred Link Here
2907
	/*
3345
	/*
2908
	 * Get the user's password table entry.
3346
	 * Get the user's password table entry.
2909
	 */
3347
	 */
2910
	names = strsep_quote(&namelist, " \t\n");
3348
	names = namelist;
2911
	name = strsep(&names, ":");
3349
	name = strsep_quote(&names, ":");
2912
	/* Bug?  name could be NULL here */
3350
	/* Bug?  name could be NULL here */
2913
	if (isdigit(*name) || *name == '-')
3351
	if (isdigit(*name) || *name == '-')
2914
		pw = getpwuid(atoi(name));
3352
		pw = getpwuid(atoi(name));
Lines 2952-2958 parsecred(char *namelist, struct xucred Link Here
2952
	}
3390
	}
2953
	cr->cr_ngroups = 0;
3391
	cr->cr_ngroups = 0;
2954
	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
3392
	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
2955
		name = strsep(&names, ":");
3393
		name = strsep_quote(&names, ":");
2956
		if (isdigit(*name) || *name == '-') {
3394
		if (isdigit(*name) || *name == '-') {
2957
			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
3395
			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
2958
		} else {
3396
		} else {
Lines 3277-3282 huphandler(int sig __unused) Link Here
3277
}
3715
}
3278
3716
3279
static void
3717
static void
3718
usr1handler(int sig __unused)
3719
{
3720
3721
	if (logdebug != 0)
3722
		logdebug = 0;
3723
	else
3724
		logdebug = 1;
3725
}
3726
3727
static void
3280
terminate(int sig __unused)
3728
terminate(int sig __unused)
3281
{
3729
{
3282
	pidfile_remove(pfh);
3730
	pidfile_remove(pfh);

Return to bug 237860