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

Collapse All | Expand All

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

Return to bug 237860