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 == 0) |
1709 |
LOGDEBUG("do_mount v4root"); |
1710 |
if (passno == 0 && 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-1676
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 |
*/ |
|
|
1727 |
if (passno == 1 && 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 = tgrp->gr_next; |
1741 |
} |
1742 |
if (v4root_ep == NULL) { |
1743 |
v4root_ep = ep; |
1744 |
ep = NULL; /* Don't free below. */ |
1745 |
} |
1746 |
grp->gr_next = v4root_ep->ex_grphead; |
1747 |
v4root_ep->ex_grphead = savgrp; |
1748 |
} |
1674 |
if (ep != NULL) |
1749 |
if (ep != NULL) |
1675 |
free_exp(ep); |
1750 |
free_exp(ep); |
1676 |
while (tgrp != NULL) { |
1751 |
while (tgrp != NULL) { |
Lines 1685-1701
get_exportlist_one(void)
Link Here
|
1685 |
* Success. Update the data structures. |
1760 |
* Success. Update the data structures. |
1686 |
*/ |
1761 |
*/ |
1687 |
if (has_host) { |
1762 |
if (has_host) { |
1688 |
hang_dirp(dirhead, tgrp, ep, opt_flags); |
1763 |
hang_dirp(dirhead, tgrp, ep, opt_flags, &anon, exflags); |
1689 |
grp->gr_next = grphead; |
1764 |
grp->gr_next = ep->ex_grphead; |
1690 |
grphead = tgrp; |
1765 |
ep->ex_grphead = tgrp; |
1691 |
} else { |
1766 |
} else { |
1692 |
hang_dirp(dirhead, (struct grouplist *)NULL, ep, |
1767 |
hang_dirp(dirhead, (struct grouplist *)NULL, ep, |
1693 |
opt_flags); |
1768 |
opt_flags, &anon, exflags); |
1694 |
free_grp(grp); |
1769 |
free_grp(grp); |
1695 |
} |
1770 |
} |
1696 |
dirhead = (struct dirlist *)NULL; |
1771 |
dirhead = (struct dirlist *)NULL; |
1697 |
if ((ep->ex_flag & EX_LINKED) == 0) { |
1772 |
if ((ep->ex_flag & EX_LINKED) == 0) { |
1698 |
SLIST_INSERT_HEAD(&exphead, ep, entries); |
1773 |
insert_exports(ep, exphead); |
1699 |
|
1774 |
|
1700 |
ep->ex_flag |= EX_LINKED; |
1775 |
ep->ex_flag |= EX_LINKED; |
1701 |
} |
1776 |
} |
Lines 1712-1758
nextline:
Link Here
|
1712 |
* Get the export list from all specified files |
1787 |
* Get the export list from all specified files |
1713 |
*/ |
1788 |
*/ |
1714 |
static void |
1789 |
static void |
1715 |
get_exportlist(void) |
1790 |
get_exportlist(int passno) |
1716 |
{ |
1791 |
{ |
1717 |
struct exportlist *ep, *ep2; |
|
|
1718 |
struct grouplist *grp, *tgrp; |
1719 |
struct export_args export; |
1792 |
struct export_args export; |
1720 |
struct iovec *iov; |
1793 |
struct iovec *iov; |
1721 |
struct statfs *fsp, *mntbufp; |
1794 |
struct statfs *mntbufp; |
1722 |
struct xvfsconf vfc; |
|
|
1723 |
char errmsg[255]; |
1795 |
char errmsg[255]; |
1724 |
int num, i; |
1796 |
int num, i; |
1725 |
int iovlen; |
1797 |
int iovlen; |
1726 |
int done; |
|
|
1727 |
struct nfsex_args eargs; |
1798 |
struct nfsex_args eargs; |
|
|
1799 |
FILE *debug_file; |
1728 |
|
1800 |
|
1729 |
if (suspend_nfsd != 0) |
1801 |
if ((debug_file = fopen(_PATH_MOUNTDDEBUG, "r")) != NULL) { |
1730 |
(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL); |
1802 |
fclose(debug_file); |
|
|
1803 |
logdebug = 1; |
1804 |
} else |
1805 |
logdebug = 0; |
1806 |
LOGDEBUG("passno=%d", passno); |
1731 |
v4root_dirpath[0] = '\0'; |
1807 |
v4root_dirpath[0] = '\0'; |
|
|
1808 |
free_v4rootexp(); |
1809 |
if (passno == 1) { |
1810 |
/* |
1811 |
* Save the current lists as old ones, so that the new lists |
1812 |
* can be compared with the old ones in the 2nd pass. |
1813 |
*/ |
1814 |
for (i = 0; i < exphashsize; i++) { |
1815 |
SLIST_FIRST(&oldexphead[i]) = SLIST_FIRST(&exphead[i]); |
1816 |
SLIST_INIT(&exphead[i]); |
1817 |
} |
1818 |
|
1819 |
/* Note that the public fh has not yet been set. */ |
1820 |
has_set_publicfh = 0; |
1821 |
|
1822 |
/* Read the export file(s) and process them */ |
1823 |
read_exportfile(passno); |
1824 |
} else { |
1825 |
/* |
1826 |
* Just make the old lists empty. |
1827 |
* exphashsize == 0 for the first call, before oldexphead |
1828 |
* has been initialized-->loop won't be executed. |
1829 |
*/ |
1830 |
for (i = 0; i < exphashsize; i++) |
1831 |
SLIST_INIT(&oldexphead[i]); |
1832 |
} |
1833 |
|
1732 |
bzero(&export, sizeof(export)); |
1834 |
bzero(&export, sizeof(export)); |
1733 |
export.ex_flags = MNT_DELEXPORT; |
1835 |
export.ex_flags = MNT_DELEXPORT; |
1734 |
iov = NULL; |
1836 |
iov = NULL; |
1735 |
iovlen = 0; |
1837 |
iovlen = 0; |
1736 |
bzero(errmsg, sizeof(errmsg)); |
1838 |
bzero(errmsg, sizeof(errmsg)); |
1737 |
|
1839 |
|
|
|
1840 |
if (suspend_nfsd != 0) |
1841 |
(void)nfssvc(NFSSVC_SUSPENDNFSD, NULL); |
1738 |
/* |
1842 |
/* |
1739 |
* First, get rid of the old list |
1843 |
* 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 |
*/ |
1844 |
*/ |
1757 |
bzero(&eargs, sizeof (eargs)); |
1845 |
bzero(&eargs, sizeof (eargs)); |
1758 |
eargs.export.ex_flags = MNT_DELEXPORT; |
1846 |
eargs.export.ex_flags = MNT_DELEXPORT; |
Lines 1760-1826
get_exportlist(void)
Link Here
|
1760 |
errno != ENOENT) |
1848 |
errno != ENOENT) |
1761 |
syslog(LOG_ERR, "Can't delete exports for V4:"); |
1849 |
syslog(LOG_ERR, "Can't delete exports for V4:"); |
1762 |
|
1850 |
|
1763 |
/* |
1851 |
build_iovec(&iov, &iovlen, "fstype", NULL, 0); |
1764 |
* and clear flag that notes if a public fh has been exported. |
1852 |
build_iovec(&iov, &iovlen, "fspath", NULL, 0); |
1765 |
*/ |
1853 |
build_iovec(&iov, &iovlen, "from", NULL, 0); |
1766 |
has_publicfh = 0; |
1854 |
build_iovec(&iov, &iovlen, "update", NULL, 0); |
|
|
1855 |
build_iovec(&iov, &iovlen, "export", &export, |
1856 |
sizeof(export)); |
1857 |
build_iovec(&iov, &iovlen, "errmsg", errmsg, |
1858 |
sizeof(errmsg)); |
1767 |
|
1859 |
|
1768 |
/* |
1860 |
/* |
1769 |
* And delete exports that are in the kernel for all local |
1861 |
* For passno == 1, compare the old and new lists updating the kernel |
1770 |
* filesystems. |
1862 |
* exports for any cases that have changed. |
1771 |
* XXX: Should know how to handle all local exportable filesystems. |
1863 |
* This call is doing the second pass through the lists. |
|
|
1864 |
* If it fails, fall back on the bulk reload. |
1772 |
*/ |
1865 |
*/ |
1773 |
num = getmntinfo(&mntbufp, MNT_NOWAIT); |
1866 |
if (passno == 1 && compare_nmount_exportlist(iov, iovlen, errmsg) == |
1774 |
|
1867 |
0) { |
1775 |
if (num > 0) { |
1868 |
LOGDEBUG("compareok"); |
1776 |
build_iovec(&iov, &iovlen, "fstype", NULL, 0); |
1869 |
/* Free up the old lists. */ |
1777 |
build_iovec(&iov, &iovlen, "fspath", NULL, 0); |
1870 |
free_exports(oldexphead); |
1778 |
build_iovec(&iov, &iovlen, "from", NULL, 0); |
1871 |
} else { |
1779 |
build_iovec(&iov, &iovlen, "update", NULL, 0); |
1872 |
LOGDEBUG("doing passno=0"); |
1780 |
build_iovec(&iov, &iovlen, "export", &export, sizeof(export)); |
1873 |
/* |
1781 |
build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); |
1874 |
* Clear flag that notes if a public fh has been exported. |
1782 |
} |
1875 |
* It is set by do_mount() if MNT_EXPUBLIC is set for the entry. |
|
|
1876 |
*/ |
1877 |
has_publicfh = 0; |
1783 |
|
1878 |
|
1784 |
for (i = 0; i < num; i++) { |
1879 |
/* exphead == NULL if not yet allocated (first call). */ |
1785 |
fsp = &mntbufp[i]; |
1880 |
if (exphead != NULL) { |
1786 |
if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) { |
1881 |
/* |
1787 |
syslog(LOG_ERR, "getvfsbyname() failed for %s", |
1882 |
* First, get rid of the old lists. |
1788 |
fsp->f_fstypename); |
1883 |
*/ |
1789 |
continue; |
1884 |
free_exports(exphead); |
|
|
1885 |
free_exports(oldexphead); |
1790 |
} |
1886 |
} |
1791 |
|
1887 |
|
1792 |
/* |
1888 |
/* |
1793 |
* We do not need to delete "export" flag from |
1889 |
* And delete exports that are in the kernel for all local |
1794 |
* filesystems that do not have it set. |
1890 |
* filesystems. |
1795 |
*/ |
1891 |
* XXX: Should know how to handle all local exportable |
1796 |
if (!(fsp->f_flags & MNT_EXPORTED)) |
1892 |
* filesystems. |
1797 |
continue; |
1893 |
*/ |
1798 |
/* |
1894 |
num = getmntinfo(&mntbufp, MNT_NOWAIT); |
1799 |
* Do not delete export for network filesystem by |
1895 |
|
1800 |
* passing "export" arg to nmount(). |
1896 |
/* Allocate hash tables, for first call. */ |
1801 |
* It only makes sense to do this for local filesystems. |
1897 |
if (exphead == NULL) { |
1802 |
*/ |
1898 |
/* Target an average linked list length of 10. */ |
1803 |
if (vfc.vfc_flags & VFCF_NETWORK) |
1899 |
exphashsize = num / 10; |
1804 |
continue; |
1900 |
if (exphashsize < 1) |
1805 |
|
1901 |
exphashsize = 1; |
1806 |
iov[1].iov_base = fsp->f_fstypename; |
1902 |
else if (exphashsize > 100000) |
1807 |
iov[1].iov_len = strlen(fsp->f_fstypename) + 1; |
1903 |
exphashsize = 100000; |
1808 |
iov[3].iov_base = fsp->f_mntonname; |
1904 |
exphead = malloc(exphashsize * sizeof(*exphead)); |
1809 |
iov[3].iov_len = strlen(fsp->f_mntonname) + 1; |
1905 |
oldexphead = malloc(exphashsize * sizeof(*oldexphead)); |
1810 |
iov[5].iov_base = fsp->f_mntfromname; |
1906 |
if (exphead == NULL || oldexphead == NULL) |
1811 |
iov[5].iov_len = strlen(fsp->f_mntfromname) + 1; |
1907 |
errx(1, "Can't malloc hash tables"); |
1812 |
errmsg[0] = '\0'; |
1908 |
|
1813 |
|
1909 |
for (i = 0; i < exphashsize; i++) { |
1814 |
/* |
1910 |
SLIST_INIT(&exphead[i]); |
1815 |
* EXDEV is returned when path exists but is not a |
1911 |
SLIST_INIT(&oldexphead[i]); |
1816 |
* mount point. May happens if raced with unmount. |
1912 |
} |
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 |
} |
1913 |
} |
|
|
1914 |
|
1915 |
for (i = 0; i < num; i++) |
1916 |
delete_export(iov, iovlen, &mntbufp[i], errmsg); |
1917 |
|
1918 |
|
1919 |
/* Read the export file(s) and process them */ |
1920 |
read_exportfile(0); |
1824 |
} |
1921 |
} |
1825 |
|
1922 |
|
1826 |
if (iov != NULL) { |
1923 |
if (iov != NULL) { |
Lines 1838-1843
get_exportlist(void)
Link Here
|
1838 |
} |
1935 |
} |
1839 |
|
1936 |
|
1840 |
/* |
1937 |
/* |
|
|
1938 |
* If there was no public fh, clear any previous one set. |
1939 |
*/ |
1940 |
if (has_publicfh == 0) { |
1941 |
LOGDEBUG("clear public fh"); |
1942 |
(void) nfssvc(NFSSVC_NOPUBLICFH, NULL); |
1943 |
} |
1944 |
|
1945 |
/* Resume the nfsd. If they weren't suspended, this is harmless. */ |
1946 |
(void)nfssvc(NFSSVC_RESUMENFSD, NULL); |
1947 |
LOGDEBUG("eo get_exportlist"); |
1948 |
} |
1949 |
|
1950 |
/* |
1951 |
* Insert an export entry in the appropriate list. |
1952 |
*/ |
1953 |
static void |
1954 |
insert_exports(struct exportlist *ep, struct exportlisthead *exhp) |
1955 |
{ |
1956 |
uint32_t i; |
1957 |
|
1958 |
i = EXPHASH(&ep->ex_fs); |
1959 |
LOGDEBUG("fs=%s hash=%i", ep->ex_fsdir, i); |
1960 |
SLIST_INSERT_HEAD(&exhp[i], ep, entries); |
1961 |
} |
1962 |
|
1963 |
/* |
1964 |
* Free up the exports lists passed in as arguments. |
1965 |
*/ |
1966 |
static void |
1967 |
free_exports(struct exportlisthead *exhp) |
1968 |
{ |
1969 |
struct exportlist *ep, *ep2; |
1970 |
int i; |
1971 |
|
1972 |
for (i = 0; i < exphashsize; i++) { |
1973 |
SLIST_FOREACH_SAFE(ep, &exhp[i], entries, ep2) { |
1974 |
SLIST_REMOVE(&exhp[i], ep, exportlist, entries); |
1975 |
free_exp(ep); |
1976 |
} |
1977 |
SLIST_INIT(&exhp[i]); |
1978 |
} |
1979 |
} |
1980 |
|
1981 |
/* |
1982 |
* Read the exports file(s) and call get_exportlist_one() for each line. |
1983 |
*/ |
1984 |
static void |
1985 |
read_exportfile(int passno) |
1986 |
{ |
1987 |
int done, i; |
1988 |
|
1989 |
/* |
1841 |
* Read in the exports file and build the list, calling |
1990 |
* Read in the exports file and build the list, calling |
1842 |
* nmount() as we go along to push the export rules into the kernel. |
1991 |
* nmount() as we go along to push the export rules into the kernel. |
1843 |
*/ |
1992 |
*/ |
Lines 1849-1855
get_exportlist(void)
Link Here
|
1849 |
syslog(LOG_WARNING, "can't open %s", exnames[i]); |
1998 |
syslog(LOG_WARNING, "can't open %s", exnames[i]); |
1850 |
continue; |
1999 |
continue; |
1851 |
} |
2000 |
} |
1852 |
get_exportlist_one(); |
2001 |
get_exportlist_one(passno); |
1853 |
fclose(exp_file); |
2002 |
fclose(exp_file); |
1854 |
done++; |
2003 |
done++; |
1855 |
} |
2004 |
} |
Lines 1857-1871
get_exportlist(void)
Link Here
|
1857 |
syslog(LOG_ERR, "can't open any exports file"); |
2006 |
syslog(LOG_ERR, "can't open any exports file"); |
1858 |
exit(2); |
2007 |
exit(2); |
1859 |
} |
2008 |
} |
|
|
2009 |
} |
2010 |
|
2011 |
/* |
2012 |
* Compare the export lists against the old ones and do nmount() operations |
2013 |
* for any cases that have changed. This avoids doing nmount() for entries |
2014 |
* that have not changed. |
2015 |
* Return 0 upon success, 1 otherwise. |
2016 |
*/ |
2017 |
static int |
2018 |
compare_nmount_exportlist(struct iovec *iov, int iovlen, char *errmsg) |
2019 |
{ |
2020 |
struct exportlist *ep, *oep; |
2021 |
struct grouplist *grp; |
2022 |
struct statfs fs, ofs; |
2023 |
int i, ret; |
1860 |
|
2024 |
|
1861 |
/* |
2025 |
/* |
1862 |
* If there was no public fh, clear any previous one set. |
2026 |
* Loop through the current list and look for an entry in the old |
|
|
2027 |
* list. |
2028 |
* If found, check to see if it the same. |
2029 |
* If it is not the same, delete and re-export. |
2030 |
* Then mark it done on the old list. |
2031 |
* else (not found) |
2032 |
* export it. |
2033 |
* Any entries left in the old list after processing must have their |
2034 |
* exports deleted. |
1863 |
*/ |
2035 |
*/ |
1864 |
if (has_publicfh == 0) |
2036 |
for (i = 0; i < exphashsize; i++) |
1865 |
(void) nfssvc(NFSSVC_NOPUBLICFH, NULL); |
2037 |
SLIST_FOREACH(ep, &exphead[i], entries) { |
|
|
2038 |
LOGDEBUG("foreach ep=%s", ep->ex_fsdir); |
2039 |
oep = ex_search(&ep->ex_fs, oldexphead); |
2040 |
if (oep != NULL) { |
2041 |
/* |
2042 |
* Check the mount paths are the same. |
2043 |
* If not, return 1 so that the reload of the |
2044 |
* exports will be done in bulk, the |
2045 |
* passno == 0 way. |
2046 |
*/ |
2047 |
LOGDEBUG("found old exp"); |
2048 |
if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0) |
2049 |
return (1); |
2050 |
LOGDEBUG("same fsdir"); |
2051 |
/* |
2052 |
* Test to see if the entry is the same. |
2053 |
* If not the same delete exports and |
2054 |
* re-export. |
2055 |
*/ |
2056 |
if (compare_export(ep, oep) != 0) { |
2057 |
/* |
2058 |
* Clear has_publicfh if if was set |
2059 |
* in the old exports, but only if it |
2060 |
* has not been set during processing of |
2061 |
* the exports for this pass, as |
2062 |
* indicated by has_set_publicfh. |
2063 |
*/ |
2064 |
if (has_set_publicfh == 0 && |
2065 |
(oep->ex_flag & EX_PUBLICFH) != 0) |
2066 |
has_publicfh = 0; |
1866 |
|
2067 |
|
1867 |
/* Resume the nfsd. If they weren't suspended, this is harmless. */ |
2068 |
/* Delete and re-export. */ |
1868 |
(void)nfssvc(NFSSVC_RESUMENFSD, NULL); |
2069 |
if (statfs(ep->ex_fsdir, &fs) < 0) |
|
|
2070 |
return (1); |
2071 |
delete_export(iov, iovlen, &fs, errmsg); |
2072 |
ret = do_export_mount(ep, &fs); |
2073 |
if (ret != 0) |
2074 |
return (ret); |
2075 |
} |
2076 |
oep->ex_flag |= EX_DONE; |
2077 |
LOGDEBUG("exdone"); |
2078 |
} else { |
2079 |
LOGDEBUG("not found so export"); |
2080 |
/* Not found, so do export. */ |
2081 |
if (statfs(ep->ex_fsdir, &fs) < 0) |
2082 |
return (1); |
2083 |
ret = do_export_mount(ep, &fs); |
2084 |
if (ret != 0) |
2085 |
return (ret); |
2086 |
} |
2087 |
} |
2088 |
|
2089 |
/* Delete exports not done. */ |
2090 |
for (i = 0; i < exphashsize; i++) |
2091 |
SLIST_FOREACH(oep, &oldexphead[i], entries) { |
2092 |
if ((oep->ex_flag & EX_DONE) == 0) { |
2093 |
LOGDEBUG("not done delete=%s", oep->ex_fsdir); |
2094 |
if (statfs(oep->ex_fsdir, &ofs) >= 0 && |
2095 |
oep->ex_fs.val[0] == ofs.f_fsid.val[0] && |
2096 |
oep->ex_fs.val[1] == ofs.f_fsid.val[1]) { |
2097 |
LOGDEBUG("do delete"); |
2098 |
/* |
2099 |
* Clear has_publicfh if if was set |
2100 |
* in the old exports, but only if it |
2101 |
* has not been set during processing of |
2102 |
* the exports for this pass, as |
2103 |
* indicated by has_set_publicfh. |
2104 |
*/ |
2105 |
if (has_set_publicfh == 0 && |
2106 |
(oep->ex_flag & EX_PUBLICFH) != 0) |
2107 |
has_publicfh = 0; |
2108 |
|
2109 |
delete_export(iov, iovlen, &ofs, |
2110 |
errmsg); |
2111 |
} |
2112 |
} |
2113 |
} |
2114 |
|
2115 |
/* Do the V4 root exports, as required. */ |
2116 |
grp = NULL; |
2117 |
if (v4root_ep != NULL) |
2118 |
grp = v4root_ep->ex_grphead; |
2119 |
v4root_phase = 2; |
2120 |
while (v4root_ep != NULL && grp != NULL) { |
2121 |
LOGDEBUG("v4root expath=%s", v4root_dirpath); |
2122 |
ret = do_mount(v4root_ep, grp, grp->gr_exflags, &grp->gr_anon, |
2123 |
v4root_dirpath, strlen(v4root_dirpath), &fs, |
2124 |
grp->gr_numsecflavors, grp->gr_secflavors); |
2125 |
if (ret != 0) { |
2126 |
v4root_phase = 0; |
2127 |
return (ret); |
2128 |
} |
2129 |
grp = grp->gr_next; |
2130 |
} |
2131 |
v4root_phase = 0; |
2132 |
free_v4rootexp(); |
2133 |
return (0); |
2134 |
} |
2135 |
|
2136 |
/* |
2137 |
* Compare old and current exportlist entries for the fsid and return 0 |
2138 |
* if they are the same, 1 otherwise. |
2139 |
*/ |
2140 |
static int |
2141 |
compare_export(struct exportlist *ep, struct exportlist *oep) |
2142 |
{ |
2143 |
struct grouplist *grp, *ogrp; |
2144 |
|
2145 |
if (strcmp(ep->ex_fsdir, oep->ex_fsdir) != 0) |
2146 |
return (1); |
2147 |
if ((ep->ex_flag & EX_DEFSET) != (oep->ex_flag & EX_DEFSET)) |
2148 |
return (1); |
2149 |
if ((ep->ex_defdir != NULL && oep->ex_defdir == NULL) || |
2150 |
(ep->ex_defdir == NULL && oep->ex_defdir != NULL)) |
2151 |
return (1); |
2152 |
if (ep->ex_defdir != NULL && (ep->ex_defdir->dp_flag & DP_DEFSET) != |
2153 |
(oep->ex_defdir->dp_flag & DP_DEFSET)) |
2154 |
return (1); |
2155 |
if ((ep->ex_flag & EX_DEFSET) != 0 && (ep->ex_defnumsecflavors != |
2156 |
oep->ex_defnumsecflavors || ep->ex_defexflags != |
2157 |
oep->ex_defexflags || compare_cred(&ep->ex_defanon, |
2158 |
&oep->ex_defanon) != 0 || compare_secflavor(ep->ex_defsecflavors, |
2159 |
oep->ex_defsecflavors, ep->ex_defnumsecflavors) != 0)) |
2160 |
return (1); |
2161 |
|
2162 |
/* Now, check all the groups. */ |
2163 |
for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next) |
2164 |
ogrp->gr_flag = 0; |
2165 |
for (grp = ep->ex_grphead; grp != NULL; grp = grp->gr_next) { |
2166 |
for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = |
2167 |
ogrp->gr_next) |
2168 |
if ((ogrp->gr_flag & GR_FND) == 0 && |
2169 |
grp->gr_numsecflavors == ogrp->gr_numsecflavors && |
2170 |
grp->gr_exflags == ogrp->gr_exflags && |
2171 |
compare_cred(&grp->gr_anon, &ogrp->gr_anon) == 0 && |
2172 |
compare_secflavor(grp->gr_secflavors, |
2173 |
ogrp->gr_secflavors, grp->gr_numsecflavors) == 0) |
2174 |
break; |
2175 |
if (ogrp != NULL) |
2176 |
ogrp->gr_flag |= GR_FND; |
2177 |
else |
2178 |
return (1); |
2179 |
} |
2180 |
for (ogrp = oep->ex_grphead; ogrp != NULL; ogrp = ogrp->gr_next) |
2181 |
if ((ogrp->gr_flag & GR_FND) == 0) |
2182 |
return (1); |
2183 |
return (0); |
2184 |
} |
2185 |
|
2186 |
/* |
2187 |
* Compare to struct xucred's. Return 0 if the same and 1 otherwise. |
2188 |
*/ |
2189 |
static int |
2190 |
compare_cred(struct xucred *cr0, struct xucred *cr1) |
2191 |
{ |
2192 |
int fnd, grp_fnd[XU_NGROUPS], i, j; |
2193 |
|
2194 |
if (cr0->cr_uid != cr1->cr_uid || cr0->cr_ngroups != cr1->cr_ngroups) |
2195 |
return (1); |
2196 |
|
2197 |
/* Handle common cases. */ |
2198 |
if (cr0->cr_ngroups == 0) |
2199 |
return (0); |
2200 |
if (cr0->cr_ngroups == 1) { |
2201 |
if (cr0->cr_groups[0] == cr1->cr_groups[0]) |
2202 |
return (0); |
2203 |
return (1); |
2204 |
} |
2205 |
if (memcmp(cr0->cr_groups, cr1->cr_groups, sizeof(*cr0->cr_groups) * |
2206 |
cr0->cr_ngroups) == 0) |
2207 |
return (0); |
2208 |
|
2209 |
for (i = 0; i < cr0->cr_ngroups; i++) |
2210 |
grp_fnd[i] = 0; |
2211 |
/* |
2212 |
* Search through the old and new groups lists, noting matches. |
2213 |
* Since there is no ordering and duplicates can exist in the lists, |
2214 |
* the algorithm is inefficient. However cr_ngroups is small and |
2215 |
* the common cases are handled above. |
2216 |
*/ |
2217 |
for (i = 0; i < cr0->cr_ngroups; i++) { |
2218 |
fnd = 0; |
2219 |
for (j = 0; j < cr0->cr_ngroups; j++) { |
2220 |
if (cr0->cr_groups[i] == cr1->cr_groups[j]) { |
2221 |
grp_fnd[j] = 1; |
2222 |
fnd = 1; |
2223 |
} |
2224 |
} |
2225 |
if (fnd == 0) |
2226 |
return (1); |
2227 |
} |
2228 |
for (i = 0; i < cr0->cr_ngroups; i++) |
2229 |
if (grp_fnd[i] == 0) |
2230 |
return (1); |
2231 |
return (0); |
2232 |
} |
2233 |
|
2234 |
/* |
2235 |
* Compare two lists of security flavors. Return 0 if the same and 1 otherwise. |
2236 |
* This is almost identical to compare_cred(), but I didn't factor out |
2237 |
* the algorithm, since compare_cred() may need to change if/when more than |
2238 |
* XU_NGROUPS groups are supported. |
2239 |
*/ |
2240 |
static int |
2241 |
compare_secflavor(int *sec1, int *sec2, int nsec) |
2242 |
{ |
2243 |
int fnd, sec_fnd[MAXSECFLAVORS], i, j; |
2244 |
|
2245 |
/* Handle common cases first. */ |
2246 |
if (nsec == 0) |
2247 |
return (0); |
2248 |
if (nsec == 1) { |
2249 |
if (sec1[0] == sec2[0]) |
2250 |
return (0); |
2251 |
return (1); |
2252 |
} |
2253 |
if (memcmp(sec1, sec2, sizeof(*sec1) * nsec) == 0) |
2254 |
return (0); |
2255 |
|
2256 |
for (i = 0; i < nsec; i++) |
2257 |
sec_fnd[i] = 0; |
2258 |
/* |
2259 |
* Search the new group list starting at the same position in the |
2260 |
* Search through the old and new secflavors lists, noting matches. |
2261 |
* Since there is no ordering and duplicates can exist in the lists, |
2262 |
* the algorithm is inefficient. However nsec is small and |
2263 |
* the common cases are handled above. |
2264 |
*/ |
2265 |
for (i = 0; i < nsec; i++) { |
2266 |
fnd = 0; |
2267 |
for (j = 0; j < nsec; j++) { |
2268 |
if (sec1[i] == sec2[j]) { |
2269 |
sec_fnd[j] = 1; |
2270 |
fnd = 1; |
2271 |
} |
2272 |
} |
2273 |
if (fnd == 0) |
2274 |
return (1); |
2275 |
} |
2276 |
for (i = 0; i < nsec; i++) |
2277 |
if (sec_fnd[i] == 0) |
2278 |
return (1); |
2279 |
return (0); |
2280 |
} |
2281 |
|
2282 |
/* |
2283 |
* Delete an exports entry. |
2284 |
*/ |
2285 |
static void |
2286 |
delete_export(struct iovec *iov, int iovlen, struct statfs *fsp, char *errmsg) |
2287 |
{ |
2288 |
struct xvfsconf vfc; |
2289 |
|
2290 |
if (getvfsbyname(fsp->f_fstypename, &vfc) != 0) { |
2291 |
syslog(LOG_ERR, "getvfsbyname() failed for %s", |
2292 |
fsp->f_fstypename); |
2293 |
return; |
2294 |
} |
2295 |
|
2296 |
/* |
2297 |
* We do not need to delete "export" flag from |
2298 |
* filesystems that do not have it set. |
2299 |
*/ |
2300 |
if (!(fsp->f_flags & MNT_EXPORTED)) |
2301 |
return; |
2302 |
/* |
2303 |
* Do not delete export for network filesystem by |
2304 |
* passing "export" arg to nmount(). |
2305 |
* It only makes sense to do this for local filesystems. |
2306 |
*/ |
2307 |
if (vfc.vfc_flags & VFCF_NETWORK) |
2308 |
return; |
2309 |
|
2310 |
iov[1].iov_base = fsp->f_fstypename; |
2311 |
iov[1].iov_len = strlen(fsp->f_fstypename) + 1; |
2312 |
iov[3].iov_base = fsp->f_mntonname; |
2313 |
iov[3].iov_len = strlen(fsp->f_mntonname) + 1; |
2314 |
iov[5].iov_base = fsp->f_mntfromname; |
2315 |
iov[5].iov_len = strlen(fsp->f_mntfromname) + 1; |
2316 |
errmsg[0] = '\0'; |
2317 |
|
2318 |
/* |
2319 |
* EXDEV is returned when path exists but is not a |
2320 |
* mount point. May happens if raced with unmount. |
2321 |
*/ |
2322 |
if (nmount(iov, iovlen, fsp->f_flags) < 0 && errno != ENOENT && |
2323 |
errno != ENOTSUP && errno != EXDEV) { |
2324 |
syslog(LOG_ERR, |
2325 |
"can't delete exports for %s: %m %s", |
2326 |
fsp->f_mntonname, errmsg); |
2327 |
} |
1869 |
} |
2328 |
} |
1870 |
|
2329 |
|
1871 |
/* |
2330 |
/* |
Lines 1924-1934
getexp_err(struct exportlist *ep, struct
Link Here
|
1924 |
* Search the export list for a matching fs. |
2383 |
* Search the export list for a matching fs. |
1925 |
*/ |
2384 |
*/ |
1926 |
static struct exportlist * |
2385 |
static struct exportlist * |
1927 |
ex_search(fsid_t *fsid) |
2386 |
ex_search(fsid_t *fsid, struct exportlisthead *exhp) |
1928 |
{ |
2387 |
{ |
1929 |
struct exportlist *ep; |
2388 |
struct exportlist *ep; |
|
|
2389 |
uint32_t i; |
1930 |
|
2390 |
|
1931 |
SLIST_FOREACH(ep, &exphead, entries) { |
2391 |
i = EXPHASH(fsid); |
|
|
2392 |
SLIST_FOREACH(ep, &exhp[i], entries) { |
1932 |
if (ep->ex_fs.val[0] == fsid->val[0] && |
2393 |
if (ep->ex_fs.val[0] == fsid->val[0] && |
1933 |
ep->ex_fs.val[1] == fsid->val[1]) |
2394 |
ep->ex_fs.val[1] == fsid->val[1]) |
1934 |
return (ep); |
2395 |
return (ep); |
Lines 1965-1971
add_expdir(struct dirlist **dpp, char *c
Link Here
|
1965 |
*/ |
2426 |
*/ |
1966 |
static void |
2427 |
static void |
1967 |
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep, |
2428 |
hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep, |
1968 |
int flags) |
2429 |
int flags, struct xucred *anoncrp, int exflags) |
1969 |
{ |
2430 |
{ |
1970 |
struct hostlist *hp; |
2431 |
struct hostlist *hp; |
1971 |
struct dirlist *dp2; |
2432 |
struct dirlist *dp2; |
Lines 1976-1987
hang_dirp(struct dirlist *dp, struct gro
Link Here
|
1976 |
else |
2437 |
else |
1977 |
ep->ex_defdir = dp; |
2438 |
ep->ex_defdir = dp; |
1978 |
if (grp == (struct grouplist *)NULL) { |
2439 |
if (grp == (struct grouplist *)NULL) { |
|
|
2440 |
ep->ex_flag |= EX_DEFSET; |
1979 |
ep->ex_defdir->dp_flag |= DP_DEFSET; |
2441 |
ep->ex_defdir->dp_flag |= DP_DEFSET; |
1980 |
/* Save the default security flavors list. */ |
2442 |
/* Save the default security flavors list. */ |
1981 |
ep->ex_defnumsecflavors = ep->ex_numsecflavors; |
2443 |
ep->ex_defnumsecflavors = ep->ex_numsecflavors; |
1982 |
if (ep->ex_numsecflavors > 0) |
2444 |
if (ep->ex_numsecflavors > 0) |
1983 |
memcpy(ep->ex_defsecflavors, ep->ex_secflavors, |
2445 |
memcpy(ep->ex_defsecflavors, ep->ex_secflavors, |
1984 |
sizeof(ep->ex_secflavors)); |
2446 |
sizeof(ep->ex_secflavors)); |
|
|
2447 |
ep->ex_defanon = *anoncrp; |
2448 |
ep->ex_defexflags = exflags; |
1985 |
} else while (grp) { |
2449 |
} else while (grp) { |
1986 |
hp = get_ht(); |
2450 |
hp = get_ht(); |
1987 |
hp->ht_grp = grp; |
2451 |
hp->ht_grp = grp; |
Lines 2001-2007
hang_dirp(struct dirlist *dp, struct gro
Link Here
|
2001 |
*/ |
2465 |
*/ |
2002 |
while (dp) { |
2466 |
while (dp) { |
2003 |
dp2 = dp->dp_left; |
2467 |
dp2 = dp->dp_left; |
2004 |
add_dlist(&ep->ex_dirl, dp, grp, flags, ep); |
2468 |
add_dlist(&ep->ex_dirl, dp, grp, flags, ep, anoncrp, |
|
|
2469 |
exflags); |
2005 |
dp = dp2; |
2470 |
dp = dp2; |
2006 |
} |
2471 |
} |
2007 |
} |
2472 |
} |
Lines 2013-2019
hang_dirp(struct dirlist *dp, struct gro
Link Here
|
2013 |
*/ |
2478 |
*/ |
2014 |
static void |
2479 |
static void |
2015 |
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp, |
2480 |
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp, |
2016 |
int flags, struct exportlist *ep) |
2481 |
int flags, struct exportlist *ep, struct xucred *anoncrp, int exflags) |
2017 |
{ |
2482 |
{ |
2018 |
struct dirlist *dp; |
2483 |
struct dirlist *dp; |
2019 |
struct hostlist *hp; |
2484 |
struct hostlist *hp; |
Lines 2023-2032
add_dlist(struct dirlist **dpp, struct d
Link Here
|
2023 |
if (dp) { |
2488 |
if (dp) { |
2024 |
cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); |
2489 |
cmp = strcmp(dp->dp_dirp, newdp->dp_dirp); |
2025 |
if (cmp > 0) { |
2490 |
if (cmp > 0) { |
2026 |
add_dlist(&dp->dp_left, newdp, grp, flags, ep); |
2491 |
add_dlist(&dp->dp_left, newdp, grp, flags, ep, anoncrp, |
|
|
2492 |
exflags); |
2027 |
return; |
2493 |
return; |
2028 |
} else if (cmp < 0) { |
2494 |
} else if (cmp < 0) { |
2029 |
add_dlist(&dp->dp_right, newdp, grp, flags, ep); |
2495 |
add_dlist(&dp->dp_right, newdp, grp, flags, ep, anoncrp, |
|
|
2496 |
exflags); |
2030 |
return; |
2497 |
return; |
2031 |
} else |
2498 |
} else |
2032 |
free((caddr_t)newdp); |
2499 |
free((caddr_t)newdp); |
Lines 2053-2064
add_dlist(struct dirlist **dpp, struct d
Link Here
|
2053 |
grp = grp->gr_next; |
2520 |
grp = grp->gr_next; |
2054 |
} while (grp); |
2521 |
} while (grp); |
2055 |
} else { |
2522 |
} else { |
|
|
2523 |
ep->ex_flag |= EX_DEFSET; |
2056 |
dp->dp_flag |= DP_DEFSET; |
2524 |
dp->dp_flag |= DP_DEFSET; |
2057 |
/* Save the default security flavors list. */ |
2525 |
/* Save the default security flavors list. */ |
2058 |
ep->ex_defnumsecflavors = ep->ex_numsecflavors; |
2526 |
ep->ex_defnumsecflavors = ep->ex_numsecflavors; |
2059 |
if (ep->ex_numsecflavors > 0) |
2527 |
if (ep->ex_numsecflavors > 0) |
2060 |
memcpy(ep->ex_defsecflavors, ep->ex_secflavors, |
2528 |
memcpy(ep->ex_defsecflavors, ep->ex_secflavors, |
2061 |
sizeof(ep->ex_secflavors)); |
2529 |
sizeof(ep->ex_secflavors)); |
|
|
2530 |
ep->ex_defanon = *anoncrp; |
2531 |
ep->ex_defexflags = exflags; |
2062 |
} |
2532 |
} |
2063 |
} |
2533 |
} |
2064 |
|
2534 |
|
Lines 2403-2408
get_host(char *cp, struct grouplist *grp
Link Here
|
2403 |
static void |
2873 |
static void |
2404 |
free_exp(struct exportlist *ep) |
2874 |
free_exp(struct exportlist *ep) |
2405 |
{ |
2875 |
{ |
|
|
2876 |
struct grouplist *grp, *tgrp; |
2406 |
|
2877 |
|
2407 |
if (ep->ex_defdir) { |
2878 |
if (ep->ex_defdir) { |
2408 |
free_host(ep->ex_defdir->dp_hosts); |
2879 |
free_host(ep->ex_defdir->dp_hosts); |
Lines 2413-2422
free_exp(struct exportlist *ep)
Link Here
|
2413 |
if (ep->ex_indexfile) |
2884 |
if (ep->ex_indexfile) |
2414 |
free(ep->ex_indexfile); |
2885 |
free(ep->ex_indexfile); |
2415 |
free_dir(ep->ex_dirl); |
2886 |
free_dir(ep->ex_dirl); |
|
|
2887 |
grp = ep->ex_grphead; |
2888 |
while (grp) { |
2889 |
tgrp = grp; |
2890 |
grp = grp->gr_next; |
2891 |
free_grp(tgrp); |
2892 |
} |
2416 |
free((caddr_t)ep); |
2893 |
free((caddr_t)ep); |
2417 |
} |
2894 |
} |
2418 |
|
2895 |
|
2419 |
/* |
2896 |
/* |
|
|
2897 |
* Free up the v4root exports. |
2898 |
*/ |
2899 |
static void |
2900 |
free_v4rootexp(void) |
2901 |
{ |
2902 |
|
2903 |
if (v4root_ep != NULL) { |
2904 |
free_exp(v4root_ep); |
2905 |
v4root_ep = NULL; |
2906 |
} |
2907 |
} |
2908 |
|
2909 |
/* |
2420 |
* Free hosts. |
2910 |
* Free hosts. |
2421 |
*/ |
2911 |
*/ |
2422 |
static void |
2912 |
static void |
Lines 2456-2467
out_of_mem(void)
Link Here
|
2456 |
} |
2946 |
} |
2457 |
|
2947 |
|
2458 |
/* |
2948 |
/* |
|
|
2949 |
* Call do_mount() from the struct exportlist, for each case needed. |
2950 |
*/ |
2951 |
static int |
2952 |
do_export_mount(struct exportlist *ep, struct statfs *fsp) |
2953 |
{ |
2954 |
struct grouplist *grp, defgrp; |
2955 |
int ret; |
2956 |
size_t dirlen; |
2957 |
|
2958 |
LOGDEBUG("do_export_mount=%s", ep->ex_fsdir); |
2959 |
dirlen = strlen(ep->ex_fsdir); |
2960 |
if ((ep->ex_flag & EX_DEFSET) != 0) { |
2961 |
defgrp.gr_type = GT_DEFAULT; |
2962 |
defgrp.gr_next = NULL; |
2963 |
/* We have an entry for all other hosts/nets. */ |
2964 |
LOGDEBUG("ex_defexflags=0x%x", ep->ex_defexflags); |
2965 |
ret = do_mount(ep, &defgrp, ep->ex_defexflags, &ep->ex_defanon, |
2966 |
ep->ex_fsdir, dirlen, fsp, ep->ex_defnumsecflavors, |
2967 |
ep->ex_defsecflavors); |
2968 |
if (ret != 0) |
2969 |
return (ret); |
2970 |
} |
2971 |
|
2972 |
/* Do a mount for each group. */ |
2973 |
grp = ep->ex_grphead; |
2974 |
while (grp != NULL) { |
2975 |
LOGDEBUG("do mount gr_type=0x%x gr_exflags=0x%x", |
2976 |
grp->gr_type, grp->gr_exflags); |
2977 |
ret = do_mount(ep, grp, grp->gr_exflags, &grp->gr_anon, |
2978 |
ep->ex_fsdir, dirlen, fsp, grp->gr_numsecflavors, |
2979 |
grp->gr_secflavors); |
2980 |
if (ret != 0) |
2981 |
return (ret); |
2982 |
grp = grp->gr_next; |
2983 |
} |
2984 |
return (0); |
2985 |
} |
2986 |
|
2987 |
/* |
2459 |
* Do the nmount() syscall with the update flag to push the export info into |
2988 |
* Do the nmount() syscall with the update flag to push the export info into |
2460 |
* the kernel. |
2989 |
* the kernel. |
2461 |
*/ |
2990 |
*/ |
2462 |
static int |
2991 |
static int |
2463 |
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags, |
2992 |
do_mount(struct exportlist *ep, struct grouplist *grp, int exflags, |
2464 |
struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb) |
2993 |
struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb, |
|
|
2994 |
int numsecflavors, int *secflavors) |
2465 |
{ |
2995 |
{ |
2466 |
struct statfs fsb1; |
2996 |
struct statfs fsb1; |
2467 |
struct addrinfo *ai; |
2997 |
struct addrinfo *ai; |
Lines 2487-2500
do_mount(struct exportlist *ep, struct g
Link Here
|
2487 |
bzero(errmsg, sizeof(errmsg)); |
3017 |
bzero(errmsg, sizeof(errmsg)); |
2488 |
eap->ex_flags = exflags; |
3018 |
eap->ex_flags = exflags; |
2489 |
eap->ex_anon = *anoncrp; |
3019 |
eap->ex_anon = *anoncrp; |
|
|
3020 |
LOGDEBUG("do_mount exflags=0x%x", exflags); |
2490 |
eap->ex_indexfile = ep->ex_indexfile; |
3021 |
eap->ex_indexfile = ep->ex_indexfile; |
2491 |
if (grp->gr_type == GT_HOST) |
3022 |
if (grp->gr_type == GT_HOST) |
2492 |
ai = grp->gr_ptr.gt_addrinfo; |
3023 |
ai = grp->gr_ptr.gt_addrinfo; |
2493 |
else |
3024 |
else |
2494 |
ai = NULL; |
3025 |
ai = NULL; |
2495 |
eap->ex_numsecflavors = ep->ex_numsecflavors; |
3026 |
eap->ex_numsecflavors = numsecflavors; |
|
|
3027 |
LOGDEBUG("do_mount numsec=%d", numsecflavors); |
2496 |
for (i = 0; i < eap->ex_numsecflavors; i++) |
3028 |
for (i = 0; i < eap->ex_numsecflavors; i++) |
2497 |
eap->ex_secflavors[i] = ep->ex_secflavors[i]; |
3029 |
eap->ex_secflavors[i] = secflavors[i]; |
2498 |
if (eap->ex_numsecflavors == 0) { |
3030 |
if (eap->ex_numsecflavors == 0) { |
2499 |
eap->ex_numsecflavors = 1; |
3031 |
eap->ex_numsecflavors = 1; |
2500 |
eap->ex_secflavors[0] = AUTH_SYS; |
3032 |
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) |
3190 |
else if (nfssvc(NFSSVC_PUBLICFH, (caddr_t)&fh) < 0) |
2659 |
syslog(LOG_ERR, |
3191 |
syslog(LOG_ERR, |
2660 |
"Can't set public fh for %s", public_name); |
3192 |
"Can't set public fh for %s", public_name); |
2661 |
else |
3193 |
else { |
2662 |
has_publicfh = 1; |
3194 |
has_publicfh = 1; |
|
|
3195 |
has_set_publicfh = 1; |
3196 |
ep->ex_flag |= EX_PUBLICFH; |
3197 |
} |
2663 |
} |
3198 |
} |
2664 |
skip: |
3199 |
skip: |
2665 |
if (ai != NULL) |
3200 |
if (ai != NULL) |
Lines 2824-2841
static void
Link Here
|
2824 |
nextfield(char **cp, char **endcp) |
3359 |
nextfield(char **cp, char **endcp) |
2825 |
{ |
3360 |
{ |
2826 |
char *p; |
3361 |
char *p; |
|
|
3362 |
char quot = 0; |
2827 |
|
3363 |
|
2828 |
p = *cp; |
3364 |
p = *cp; |
2829 |
while (*p == ' ' || *p == '\t') |
3365 |
while (*p == ' ' || *p == '\t') |
2830 |
p++; |
3366 |
p++; |
2831 |
if (*p == '\n' || *p == '\0') |
3367 |
*cp = p; |
2832 |
*cp = *endcp = p; |
3368 |
while (*p != '\0') { |
2833 |
else { |
3369 |
if (quot) { |
2834 |
*cp = p++; |
3370 |
if (*p == quot) |
2835 |
while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') |
3371 |
quot = 0; |
2836 |
p++; |
3372 |
} else { |
2837 |
*endcp = p; |
3373 |
if (*p == '\\' && *(p + 1) != '\0') |
2838 |
} |
3374 |
p++; |
|
|
3375 |
else if (*p == '\'' || *p == '"') |
3376 |
quot = *p; |
3377 |
else if (*p == ' ' || *p == '\t') |
3378 |
break; |
3379 |
} |
3380 |
p++; |
3381 |
}; |
3382 |
*endcp = p; |
2839 |
} |
3383 |
} |
2840 |
|
3384 |
|
2841 |
/* |
3385 |
/* |
Lines 2907-2914
parsecred(char *namelist, struct xucred
Link Here
|
2907 |
/* |
3451 |
/* |
2908 |
* Get the user's password table entry. |
3452 |
* Get the user's password table entry. |
2909 |
*/ |
3453 |
*/ |
2910 |
names = strsep_quote(&namelist, " \t\n"); |
3454 |
names = namelist; |
2911 |
name = strsep(&names, ":"); |
3455 |
name = strsep_quote(&names, ":"); |
2912 |
/* Bug? name could be NULL here */ |
3456 |
/* Bug? name could be NULL here */ |
2913 |
if (isdigit(*name) || *name == '-') |
3457 |
if (isdigit(*name) || *name == '-') |
2914 |
pw = getpwuid(atoi(name)); |
3458 |
pw = getpwuid(atoi(name)); |
Lines 2952-2958
parsecred(char *namelist, struct xucred
Link Here
|
2952 |
} |
3496 |
} |
2953 |
cr->cr_ngroups = 0; |
3497 |
cr->cr_ngroups = 0; |
2954 |
while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) { |
3498 |
while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) { |
2955 |
name = strsep(&names, ":"); |
3499 |
name = strsep_quote(&names, ":"); |
2956 |
if (isdigit(*name) || *name == '-') { |
3500 |
if (isdigit(*name) || *name == '-') { |
2957 |
cr->cr_groups[cr->cr_ngroups++] = atoi(name); |
3501 |
cr->cr_groups[cr->cr_ngroups++] = atoi(name); |
2958 |
} else { |
3502 |
} else { |