mountd.c (75754) | mountd.c (75801) |
---|---|
1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Herb Hasler and Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 31 unchanged lines hidden (view full) --- 40 The Regents of the University of California. All rights reserved.\n"; 41#endif /*not lint*/ 42 43#ifndef lint 44#if 0 45static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; 46#endif 47static const char rcsid[] = | 1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Herb Hasler and Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 31 unchanged lines hidden (view full) --- 40 The Regents of the University of California. All rights reserved.\n"; 41#endif /*not lint*/ 42 43#ifndef lint 44#if 0 45static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; 46#endif 47static const char rcsid[] = |
48 "$FreeBSD: head/usr.sbin/mountd/mountd.c 75754 2001-04-21 00:55:17Z iedowse $"; | 48 "$FreeBSD: head/usr.sbin/mountd/mountd.c 75801 2001-04-21 20:06:18Z iedowse $"; |
49#endif /*not lint*/ 50 51#include <sys/param.h> 52#include <sys/mount.h> 53#include <sys/fcntl.h> 54#include <sys/stat.h> 55#include <sys/syslog.h> 56#include <sys/sysctl.h> --- 63 unchanged lines hidden (view full) --- 120 char *ex_fsdir; 121 char *ex_indexfile; 122}; 123/* ex_flag bits */ 124#define EX_LINKED 0x1 125 126struct netmsk { 127 struct sockaddr_storage nt_net; | 49#endif /*not lint*/ 50 51#include <sys/param.h> 52#include <sys/mount.h> 53#include <sys/fcntl.h> 54#include <sys/stat.h> 55#include <sys/syslog.h> 56#include <sys/sysctl.h> --- 63 unchanged lines hidden (view full) --- 120 char *ex_fsdir; 121 char *ex_indexfile; 122}; 123/* ex_flag bits */ 124#define EX_LINKED 0x1 125 126struct netmsk { 127 struct sockaddr_storage nt_net; |
128 u_int32_t nt_mask; | 128 struct sockaddr_storage nt_mask; |
129 char *nt_name; 130}; 131 132union grouptypes { 133 struct addrinfo *gt_addrinfo; 134 struct netmsk gt_net; 135}; 136 --- 23 unchanged lines hidden (view full) --- 160 161/* Global defs */ 162char *add_expdir __P((struct dirlist **, char *, int)); 163void add_dlist __P((struct dirlist **, struct dirlist *, 164 struct grouplist *, int)); 165void add_mlist __P((char *, char *)); 166int check_dirpath __P((char *)); 167int check_options __P((struct dirlist *)); | 129 char *nt_name; 130}; 131 132union grouptypes { 133 struct addrinfo *gt_addrinfo; 134 struct netmsk gt_net; 135}; 136 --- 23 unchanged lines hidden (view full) --- 160 161/* Global defs */ 162char *add_expdir __P((struct dirlist **, char *, int)); 163void add_dlist __P((struct dirlist **, struct dirlist *, 164 struct grouplist *, int)); 165void add_mlist __P((char *, char *)); 166int check_dirpath __P((char *)); 167int check_options __P((struct dirlist *)); |
168int checkmask(struct sockaddr *sa); |
|
168int chk_host __P((struct dirlist *, struct sockaddr *, int *, int *)); 169void del_mlist(char *hostp, char *dirp); 170struct dirlist *dirp_search __P((struct dirlist *, char *)); 171int do_mount __P((struct exportlist *, struct grouplist *, int, 172 struct xucred *, char *, int, struct statfs *)); 173int do_opt __P((char **, char **, struct exportlist *, struct grouplist *, 174 int *, int *, struct xucred *)); 175struct exportlist *ex_search __P((fsid_t *)); --- 8 unchanged lines hidden (view full) --- 184int get_line __P((void)); 185void get_mountlist __P((void)); 186int get_net __P((char *, struct netmsk *, int)); 187void getexp_err __P((struct exportlist *, struct grouplist *)); 188struct grouplist *get_grp __P((void)); 189void hang_dirp __P((struct dirlist *, struct grouplist *, 190 struct exportlist *, int)); 191void huphandler(int sig); | 169int chk_host __P((struct dirlist *, struct sockaddr *, int *, int *)); 170void del_mlist(char *hostp, char *dirp); 171struct dirlist *dirp_search __P((struct dirlist *, char *)); 172int do_mount __P((struct exportlist *, struct grouplist *, int, 173 struct xucred *, char *, int, struct statfs *)); 174int do_opt __P((char **, char **, struct exportlist *, struct grouplist *, 175 int *, int *, struct xucred *)); 176struct exportlist *ex_search __P((fsid_t *)); --- 8 unchanged lines hidden (view full) --- 185int get_line __P((void)); 186void get_mountlist __P((void)); 187int get_net __P((char *, struct netmsk *, int)); 188void getexp_err __P((struct exportlist *, struct grouplist *)); 189struct grouplist *get_grp __P((void)); 190void hang_dirp __P((struct dirlist *, struct grouplist *, 191 struct exportlist *, int)); 192void huphandler(int sig); |
193int makemask(struct sockaddr_storage *ssp, int bitlen); |
|
192void mntsrv __P((struct svc_req *, SVCXPRT *)); 193void nextfield __P((char **, char **)); 194void out_of_mem __P((void)); 195void parsecred __P((char *, struct xucred *)); 196int put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *)); | 194void mntsrv __P((struct svc_req *, SVCXPRT *)); 195void nextfield __P((char **, char **)); 196void out_of_mem __P((void)); 197void parsecred __P((char *, struct xucred *)); 198int put_exlist __P((struct dirlist *, XDR *, struct dirlist *, int *)); |
199void *sa_rawaddr(struct sockaddr *sa, int *nbytes); 200int sacmp(struct sockaddr *sa1, struct sockaddr *sa2, 201 struct sockaddr *samask); |
|
197int scan_tree __P((struct dirlist *, struct sockaddr *)); 198static void usage __P((void)); 199int xdr_dir __P((XDR *, char *)); 200int xdr_explist __P((XDR *, caddr_t)); 201int xdr_fhs __P((XDR *, caddr_t)); 202int xdr_mlist __P((XDR *, caddr_t)); 203void terminate __P((int)); 204 | 202int scan_tree __P((struct dirlist *, struct sockaddr *)); 203static void usage __P((void)); 204int xdr_dir __P((XDR *, char *)); 205int xdr_explist __P((XDR *, caddr_t)); 206int xdr_fhs __P((XDR *, caddr_t)); 207int xdr_mlist __P((XDR *, caddr_t)); 208void terminate __P((int)); 209 |
205static int bitcmp __P((void *, void *, int)); 206static int netpartcmp __P((struct sockaddr *, struct sockaddr *, int)); 207static int sacmp __P((struct sockaddr *, struct sockaddr *)); 208static int allones __P((struct sockaddr_storage *, int)); 209static int countones __P((struct sockaddr *)); 210 | |
211struct exportlist *exphead; 212struct mountlist *mlhead; 213struct grouplist *grphead; 214char exname[MAXPATHLEN]; 215struct xucred def_anon = { 216 0, 217 (uid_t)-2, 218 1, --- 10 unchanged lines hidden (view full) --- 229static int have_v6 = 1; 230#ifdef NI_WITHSCOPEID 231static const int ninumeric = NI_NUMERICHOST | NI_WITHSCOPEID; 232#else 233static const int ninumeric = NI_NUMERICHOST; 234#endif 235 236int mountdlockfd; | 210struct exportlist *exphead; 211struct mountlist *mlhead; 212struct grouplist *grphead; 213char exname[MAXPATHLEN]; 214struct xucred def_anon = { 215 0, 216 (uid_t)-2, 217 1, --- 10 unchanged lines hidden (view full) --- 228static int have_v6 = 1; 229#ifdef NI_WITHSCOPEID 230static const int ninumeric = NI_NUMERICHOST | NI_WITHSCOPEID; 231#else 232static const int ninumeric = NI_NUMERICHOST; 233#endif 234 235int mountdlockfd; |
237/* Bits for above */ | 236/* Bits for opt_flags above */ |
238#define OP_MAPROOT 0x01 239#define OP_MAPALL 0x02 240#define OP_KERB 0x04 241#define OP_MASK 0x08 242#define OP_NET 0x10 243#define OP_ALLDIRS 0x40 | 237#define OP_MAPROOT 0x01 238#define OP_MAPALL 0x02 239#define OP_KERB 0x04 240#define OP_MASK 0x08 241#define OP_NET 0x10 242#define OP_ALLDIRS 0x40 |
243#define OP_HAVEMASK 0x80 /* A mask was specified or inferred. */ |
|
244#define OP_MASKLEN 0x200 245 246#ifdef DEBUG 247int debug = 1; 248void SYSLOG __P((int, const char *, ...)); 249#define syslog SYSLOG 250#else 251int debug = 0; --- 859 unchanged lines hidden (view full) --- 1111 if (debug) 1112 warnx("adding a default entry"); 1113 1114 /* 1115 * Don't allow a network export coincide with a list of 1116 * host(s) on the same line. 1117 */ 1118 } else if ((opt_flags & OP_NET) && tgrp->gr_next) { | 244#define OP_MASKLEN 0x200 245 246#ifdef DEBUG 247int debug = 1; 248void SYSLOG __P((int, const char *, ...)); 249#define syslog SYSLOG 250#else 251int debug = 0; --- 859 unchanged lines hidden (view full) --- 1111 if (debug) 1112 warnx("adding a default entry"); 1113 1114 /* 1115 * Don't allow a network export coincide with a list of 1116 * host(s) on the same line. 1117 */ 1118 } else if ((opt_flags & OP_NET) && tgrp->gr_next) { |
1119 syslog(LOG_ERR, "network/host conflict"); |
|
1119 getexp_err(ep, tgrp); 1120 goto nextline; 1121 1122 /* 1123 * If an export list was specified on this line, make sure 1124 * that we have at least one valid entry, otherwise skip it. 1125 */ 1126 } else { --- 265 unchanged lines hidden (view full) --- 1392 return (dirp_search(dp->dp_right, dirp)); 1393 else 1394 return (dp); 1395 } 1396 return (dp); 1397} 1398 1399/* | 1120 getexp_err(ep, tgrp); 1121 goto nextline; 1122 1123 /* 1124 * If an export list was specified on this line, make sure 1125 * that we have at least one valid entry, otherwise skip it. 1126 */ 1127 } else { --- 265 unchanged lines hidden (view full) --- 1393 return (dirp_search(dp->dp_right, dirp)); 1394 else 1395 return (dp); 1396 } 1397 return (dp); 1398} 1399 1400/* |
1400 * Some helper functions for netmasks. They all assume masks in network 1401 * order (big endian). 1402 */ 1403static int 1404bitcmp(void *dst, void *src, int bitlen) 1405{ 1406 int i; 1407 u_int8_t *p1 = dst, *p2 = src; 1408 u_int8_t bitmask; 1409 int bytelen, bitsleft; 1410 1411 bytelen = bitlen / 8; 1412 bitsleft = bitlen % 8; 1413 1414 if (debug) { 1415 printf("comparing:\n"); 1416 for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++) 1417 printf("%02x", p1[i]); 1418 printf("\n"); 1419 for (i = 0; i < (bitsleft ? bytelen + 1 : bytelen); i++) 1420 printf("%02x", p2[i]); 1421 printf("\n"); 1422 } 1423 1424 for (i = 0; i < bytelen; i++) { 1425 if (*p1 != *p2) 1426 return 1; 1427 p1++; 1428 p2++; 1429 } 1430 1431 for (i = 0; i < bitsleft; i++) { 1432 bitmask = 1 << (7 - i); 1433 if ((*p1 & bitmask) != (*p2 & bitmask)) 1434 return 1; 1435 } 1436 1437 return 0; 1438} 1439 1440/* | |
1441 * Scan for a host match in a directory tree. 1442 */ 1443int 1444chk_host(dp, saddr, defsetp, hostsetp) 1445 struct dirlist *dp; 1446 struct sockaddr *saddr; 1447 int *defsetp; 1448 int *hostsetp; --- 7 unchanged lines hidden (view full) --- 1456 *defsetp = dp->dp_flag; 1457 hp = dp->dp_hosts; 1458 while (hp) { 1459 grp = hp->ht_grp; 1460 switch (grp->gr_type) { 1461 case GT_HOST: 1462 ai = grp->gr_ptr.gt_addrinfo; 1463 for (; ai; ai = ai->ai_next) { | 1401 * Scan for a host match in a directory tree. 1402 */ 1403int 1404chk_host(dp, saddr, defsetp, hostsetp) 1405 struct dirlist *dp; 1406 struct sockaddr *saddr; 1407 int *defsetp; 1408 int *hostsetp; --- 7 unchanged lines hidden (view full) --- 1416 *defsetp = dp->dp_flag; 1417 hp = dp->dp_hosts; 1418 while (hp) { 1419 grp = hp->ht_grp; 1420 switch (grp->gr_type) { 1421 case GT_HOST: 1422 ai = grp->gr_ptr.gt_addrinfo; 1423 for (; ai; ai = ai->ai_next) { |
1464 if (!sacmp(ai->ai_addr, saddr)) { | 1424 if (!sacmp(ai->ai_addr, saddr, NULL)) { |
1465 *hostsetp = 1466 (hp->ht_flag | DP_HOSTSET); 1467 return (1); 1468 } 1469 } | 1425 *hostsetp = 1426 (hp->ht_flag | DP_HOSTSET); 1427 return (1); 1428 } 1429 } |
1470 break; | 1430 break; |
1471 case GT_NET: | 1431 case GT_NET: |
1472 if (!netpartcmp(saddr, 1473 (struct sockaddr *) &grp->gr_ptr.gt_net.nt_net, 1474 grp->gr_ptr.gt_net.nt_mask)) { | 1432 if (!sacmp(saddr, (struct sockaddr *) 1433 &grp->gr_ptr.gt_net.nt_net, 1434 (struct sockaddr *) 1435 &grp->gr_ptr.gt_net.nt_mask)) { |
1475 *hostsetp = (hp->ht_flag | DP_HOSTSET); 1476 return (1); 1477 } | 1436 *hostsetp = (hp->ht_flag | DP_HOSTSET); 1437 return (1); 1438 } |
1478 break; 1479 }; | 1439 break; 1440 } |
1480 hp = hp->ht_next; 1481 } 1482 } 1483 return (0); 1484} 1485 1486/* 1487 * Scan tree for a host that matches the address. --- 89 unchanged lines hidden (view full) --- 1577 *exflagsp |= MNT_EXPORTANON; 1578 opt_flags |= OP_MAPALL; 1579 } else 1580 opt_flags |= OP_MAPROOT; 1581 } else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) { 1582 *exflagsp |= MNT_EXKERB; 1583 opt_flags |= OP_KERB; 1584 } else if (cpoptarg && (!strcmp(cpopt, "mask") || | 1441 hp = hp->ht_next; 1442 } 1443 } 1444 return (0); 1445} 1446 1447/* 1448 * Scan tree for a host that matches the address. --- 89 unchanged lines hidden (view full) --- 1538 *exflagsp |= MNT_EXPORTANON; 1539 opt_flags |= OP_MAPALL; 1540 } else 1541 opt_flags |= OP_MAPROOT; 1542 } else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) { 1543 *exflagsp |= MNT_EXKERB; 1544 opt_flags |= OP_KERB; 1545 } else if (cpoptarg && (!strcmp(cpopt, "mask") || |
1585 !strcmp(cpopt, "m"))) { | 1546 !strcmp(cpopt, "m"))) { |
1586 if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 1587 syslog(LOG_ERR, "bad mask: %s", cpoptarg); 1588 return (1); 1589 } 1590 usedarg++; 1591 opt_flags |= OP_MASK; 1592 } else if (cpoptarg && (!strcmp(cpopt, "network") || 1593 !strcmp(cpopt, "n"))) { --- 84 unchanged lines hidden (view full) --- 1678 * for this host in the grouplist. 1679 */ 1680 for (checkgrp = tgrp; checkgrp != NULL; 1681 checkgrp = checkgrp->gr_next) { 1682 if (checkgrp->gr_type != GT_HOST) 1683 continue; 1684 for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL; 1685 tai = tai->ai_next) { | 1547 if (get_net(cpoptarg, &grp->gr_ptr.gt_net, 1)) { 1548 syslog(LOG_ERR, "bad mask: %s", cpoptarg); 1549 return (1); 1550 } 1551 usedarg++; 1552 opt_flags |= OP_MASK; 1553 } else if (cpoptarg && (!strcmp(cpopt, "network") || 1554 !strcmp(cpopt, "n"))) { --- 84 unchanged lines hidden (view full) --- 1639 * for this host in the grouplist. 1640 */ 1641 for (checkgrp = tgrp; checkgrp != NULL; 1642 checkgrp = checkgrp->gr_next) { 1643 if (checkgrp->gr_type != GT_HOST) 1644 continue; 1645 for (tai = checkgrp->gr_ptr.gt_addrinfo; tai != NULL; 1646 tai = tai->ai_next) { |
1686 if (sacmp(tai->ai_addr, ai->ai_addr) != 0) | 1647 if (sacmp(tai->ai_addr, ai->ai_addr, NULL) != 0) |
1687 continue; 1688 if (debug) 1689 fprintf(stderr, 1690 "ignoring duplicate host %s\n", 1691 ai->ai_canonname); 1692 grp->gr_type = GT_IGNORE; 1693 return (0); 1694 } --- 73 unchanged lines hidden (view full) --- 1768 struct exportlist *ep; 1769 struct grouplist *grp; 1770 int exflags; 1771 struct xucred *anoncrp; 1772 char *dirp; 1773 int dirplen; 1774 struct statfs *fsb; 1775{ | 1648 continue; 1649 if (debug) 1650 fprintf(stderr, 1651 "ignoring duplicate host %s\n", 1652 ai->ai_canonname); 1653 grp->gr_type = GT_IGNORE; 1654 return (0); 1655 } --- 73 unchanged lines hidden (view full) --- 1729 struct exportlist *ep; 1730 struct grouplist *grp; 1731 int exflags; 1732 struct xucred *anoncrp; 1733 char *dirp; 1734 int dirplen; 1735 struct statfs *fsb; 1736{ |
1776 struct sockaddr_storage ss; | |
1777 struct addrinfo *ai; | 1737 struct addrinfo *ai; |
1738 struct export_args *eap; |
|
1778 char *cp = NULL; 1779 int done; 1780 char savedc = '\0'; 1781 union { 1782 struct ufs_args ua; 1783 struct iso_args ia; 1784 struct mfs_args ma; | 1739 char *cp = NULL; 1740 int done; 1741 char savedc = '\0'; 1742 union { 1743 struct ufs_args ua; 1744 struct iso_args ia; 1745 struct mfs_args ma; |
1785#ifdef __NetBSD__ | |
1786 struct msdosfs_args da; | 1746 struct msdosfs_args da; |
1787 struct adosfs_args aa; 1788#endif | |
1789 struct ntfs_args na; 1790 } args; 1791 | 1747 struct ntfs_args na; 1748 } args; 1749 |
1750 bzero(&args, sizeof args); 1751 /* XXX, we assume that all xx_args look like ufs_args. */ |
|
1792 args.ua.fspec = 0; | 1752 args.ua.fspec = 0; |
1793 args.ua.export.ex_flags = exflags; 1794 args.ua.export.ex_anon = *anoncrp; 1795 args.ua.export.ex_indexfile = ep->ex_indexfile; | 1753 eap = &args.ua.export; 1754 1755 eap->ex_flags = exflags; 1756 eap->ex_anon = *anoncrp; 1757 eap->ex_indexfile = ep->ex_indexfile; |
1796 if (grp->gr_type == GT_HOST) 1797 ai = grp->gr_ptr.gt_addrinfo; 1798 else 1799 ai = NULL; 1800 done = FALSE; 1801 while (!done) { 1802 switch (grp->gr_type) { 1803 case GT_HOST: 1804 if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) 1805 goto skip; | 1758 if (grp->gr_type == GT_HOST) 1759 ai = grp->gr_ptr.gt_addrinfo; 1760 else 1761 ai = NULL; 1762 done = FALSE; 1763 while (!done) { 1764 switch (grp->gr_type) { 1765 case GT_HOST: 1766 if (ai->ai_addr->sa_family == AF_INET6 && have_v6 == 0) 1767 goto skip; |
1806 args.ua.export.ex_addr = ai->ai_addr; 1807 args.ua.export.ex_addrlen = ai->ai_addrlen; 1808 args.ua.export.ex_masklen = 0; | 1768 eap->ex_addr = ai->ai_addr; 1769 eap->ex_addrlen = ai->ai_addrlen; 1770 eap->ex_masklen = 0; |
1809 break; 1810 case GT_NET: | 1771 break; 1772 case GT_NET: |
1811 args.ua.export.ex_addr = (struct sockaddr *) 1812 &grp->gr_ptr.gt_net.nt_net; 1813 if (args.ua.export.ex_addr->sa_family == AF_INET6 && | 1773 if (grp->gr_ptr.gt_net.nt_net.ss_family == AF_INET6 && |
1814 have_v6 == 0) 1815 goto skip; | 1774 have_v6 == 0) 1775 goto skip; |
1816 args.ua.export.ex_addrlen = 1817 args.ua.export.ex_addr->sa_len; 1818 memset(&ss, 0, sizeof ss); 1819 ss.ss_family = args.ua.export.ex_addr->sa_family; 1820 ss.ss_len = args.ua.export.ex_addr->sa_len; 1821 if (allones(&ss, grp->gr_ptr.gt_net.nt_mask) != 0) { 1822 syslog(LOG_ERR, "Bad network flag"); 1823 if (cp) 1824 *cp = savedc; 1825 return (1); 1826 } 1827 args.ua.export.ex_mask = (struct sockaddr *)&ss; 1828 args.ua.export.ex_masklen = ss.ss_len; | 1776 eap->ex_addr = 1777 (struct sockaddr *)&grp->gr_ptr.gt_net.nt_net; 1778 eap->ex_addrlen = args.ua.export.ex_addr->sa_len; 1779 eap->ex_mask = 1780 (struct sockaddr *)&grp->gr_ptr.gt_net.nt_mask; 1781 eap->ex_masklen = args.ua.export.ex_mask->sa_len; |
1829 break; 1830 case GT_DEFAULT: | 1782 break; 1783 case GT_DEFAULT: |
1831 args.ua.export.ex_addr = NULL; 1832 args.ua.export.ex_addrlen = 0; 1833 args.ua.export.ex_mask = NULL; 1834 args.ua.export.ex_masklen = 0; | 1784 eap->ex_addr = NULL; 1785 eap->ex_addrlen = 0; 1786 eap->ex_mask = NULL; 1787 eap->ex_masklen = 0; |
1835 break; 1836 case GT_IGNORE: 1837 return(0); 1838 break; 1839 default: 1840 syslog(LOG_ERR, "bad grouptype"); 1841 if (cp) 1842 *cp = savedc; --- 48 unchanged lines hidden (view full) --- 1891 } 1892 if (cp) 1893 *cp = savedc; 1894 return (0); 1895} 1896 1897/* 1898 * Translate a net address. | 1788 break; 1789 case GT_IGNORE: 1790 return(0); 1791 break; 1792 default: 1793 syslog(LOG_ERR, "bad grouptype"); 1794 if (cp) 1795 *cp = savedc; --- 48 unchanged lines hidden (view full) --- 1844 } 1845 if (cp) 1846 *cp = savedc; 1847 return (0); 1848} 1849 1850/* 1851 * Translate a net address. |
1852 * 1853 * If `maskflg' is nonzero, then `cp' is a netmask, not a network address. |
|
1899 */ 1900int 1901get_net(cp, net, maskflg) 1902 char *cp; 1903 struct netmsk *net; 1904 int maskflg; 1905{ 1906 struct netent *np; 1907 char *name, *p, *prefp; | 1854 */ 1855int 1856get_net(cp, net, maskflg) 1857 char *cp; 1858 struct netmsk *net; 1859 int maskflg; 1860{ 1861 struct netent *np; 1862 char *name, *p, *prefp; |
1908 struct sockaddr_in sin, *sinp; | 1863 struct sockaddr_in sin; |
1909 struct sockaddr *sa; 1910 struct addrinfo hints, *ai = NULL; 1911 char netname[NI_MAXHOST]; 1912 long preflen; | 1864 struct sockaddr *sa; 1865 struct addrinfo hints, *ai = NULL; 1866 char netname[NI_MAXHOST]; 1867 long preflen; |
1913 int ecode; | |
1914 1915 p = prefp = NULL; 1916 if ((opt_flags & OP_MASKLEN) && !maskflg) { 1917 p = strchr(cp, '/'); 1918 *p = '\0'; 1919 prefp = p + 1; 1920 } 1921 1922 if ((np = getnetbyname(cp)) != NULL) { | 1868 1869 p = prefp = NULL; 1870 if ((opt_flags & OP_MASKLEN) && !maskflg) { 1871 p = strchr(cp, '/'); 1872 *p = '\0'; 1873 prefp = p + 1; 1874 } 1875 1876 if ((np = getnetbyname(cp)) != NULL) { |
1877 bzero(&sin, sizeof sin); |
|
1923 sin.sin_family = AF_INET; 1924 sin.sin_len = sizeof sin; 1925 sin.sin_addr = inet_makeaddr(np->n_net, 0); 1926 sa = (struct sockaddr *)&sin; | 1878 sin.sin_family = AF_INET; 1879 sin.sin_len = sizeof sin; 1880 sin.sin_addr = inet_makeaddr(np->n_net, 0); 1881 sa = (struct sockaddr *)&sin; |
1927 } else if (isdigit(*cp)) { | 1882 } else if (isxdigit(*cp) || *cp == ':') { |
1928 memset(&hints, 0, sizeof hints); | 1883 memset(&hints, 0, sizeof hints); |
1929 hints.ai_family = AF_UNSPEC; | 1884 /* Ensure the mask and the network have the same family. */ 1885 if (maskflg && (opt_flags & OP_NET)) 1886 hints.ai_family = net->nt_net.ss_family; 1887 else if (!maskflg && (opt_flags & OP_HAVEMASK)) 1888 hints.ai_family = net->nt_mask.ss_family; 1889 else 1890 hints.ai_family = AF_UNSPEC; |
1930 hints.ai_flags = AI_NUMERICHOST; | 1891 hints.ai_flags = AI_NUMERICHOST; |
1931 if (getaddrinfo(cp, NULL, &hints, &ai) != 0) { | 1892 if (getaddrinfo(cp, NULL, &hints, &ai) != 0) 1893 goto fail; 1894 if (ai->ai_family == AF_INET) { |
1932 /* | 1895 /* |
1933 * If getaddrinfo() failed, try the inet4 network 1934 * notation with less than 3 dots. | 1896 * The address in `cp' is really a network address, so 1897 * use inet_network() to re-interpret this correctly. 1898 * e.g. "127.1" means 127.1.0.0, not 127.0.0.1. |
1935 */ | 1899 */ |
1900 bzero(&sin, sizeof sin); |
|
1936 sin.sin_family = AF_INET; 1937 sin.sin_len = sizeof sin; | 1901 sin.sin_family = AF_INET; 1902 sin.sin_len = sizeof sin; |
1938 sin.sin_addr = inet_makeaddr(inet_network(cp),0); | 1903 sin.sin_addr = inet_makeaddr(inet_network(cp), 0); |
1939 if (debug) | 1904 if (debug) |
1940 fprintf(stderr, "get_net: v4 addr %x\n", 1941 sin.sin_addr.s_addr); | 1905 fprintf(stderr, "get_net: v4 addr %s\n", 1906 inet_ntoa(sin.sin_addr)); |
1942 sa = (struct sockaddr *)&sin; 1943 } else 1944 sa = ai->ai_addr; | 1907 sa = (struct sockaddr *)&sin; 1908 } else 1909 sa = ai->ai_addr; |
1945 } else if (isxdigit(*cp) || *cp == ':') { 1946 memset(&hints, 0, sizeof hints); 1947 hints.ai_family = AF_UNSPEC; 1948 hints.ai_flags = AI_NUMERICHOST; 1949 if (getaddrinfo(cp, NULL, &hints, &ai) == 0) 1950 sa = ai->ai_addr; 1951 else 1952 goto fail; | |
1953 } else 1954 goto fail; 1955 | 1910 } else 1911 goto fail; 1912 |
1956 ecode = getnameinfo(sa, sa->sa_len, netname, sizeof netname, 1957 NULL, 0, ninumeric); 1958 if (ecode != 0) 1959 goto fail; | 1913 if (maskflg) { 1914 /* The specified sockaddr is a mask. */ 1915 if (checkmask(sa) != 0) 1916 goto fail; 1917 bcopy(sa, &net->nt_mask, sa->sa_len); 1918 opt_flags |= OP_HAVEMASK; 1919 } else { 1920 /* The specified sockaddr is a network address. */ 1921 bcopy(sa, &net->nt_net, sa->sa_len); |
1960 | 1922 |
1961 if (maskflg) 1962 net->nt_mask = countones(sa); 1963 else { | 1923 /* Get a network name for the export list. */ 1924 if (np) { 1925 name = np->n_name; 1926 } else if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, 1927 NULL, 0, ninumeric) == 0) { 1928 name = netname; 1929 } else { 1930 goto fail; 1931 } 1932 if ((net->nt_name = strdup(name)) == NULL) 1933 out_of_mem(); 1934 1935 /* 1936 * Extract a mask from either a "/<masklen>" suffix, or 1937 * from the class of an IPv4 address. 1938 */ |
1964 if (opt_flags & OP_MASKLEN) { 1965 preflen = strtol(prefp, NULL, 10); | 1939 if (opt_flags & OP_MASKLEN) { 1940 preflen = strtol(prefp, NULL, 10); |
1966 if (preflen == LONG_MIN && errno == ERANGE) | 1941 if (preflen < 0L || preflen == LONG_MAX) |
1967 goto fail; | 1942 goto fail; |
1968 net->nt_mask = (int)preflen; | 1943 bcopy(sa, &net->nt_mask, sa->sa_len); 1944 if (makemask(&net->nt_mask, (int)preflen) != 0) 1945 goto fail; 1946 opt_flags |= OP_HAVEMASK; |
1969 *p = '/'; | 1947 *p = '/'; |
1970 } | 1948 } else if (sa->sa_family == AF_INET && 1949 (opt_flags & OP_MASK) == 0) { 1950 in_addr_t addr; |
1971 | 1951 |
1972 if (np) 1973 name = np->n_name; 1974 else { 1975 if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, 1976 NULL, 0, ninumeric) != 0) 1977 strlcpy(netname, "?", sizeof(netname)); 1978 name = netname; | 1952 addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 1953 if (IN_CLASSA(addr)) 1954 preflen = 8; 1955 else if (IN_CLASSB(addr)) 1956 preflen = 16; 1957 else if (IN_CLASSC(addr)) 1958 preflen = 24; 1959 else if (IN_CLASSD(addr)) 1960 preflen = 28; 1961 else 1962 preflen = 32; /* XXX */ 1963 1964 bcopy(sa, &net->nt_mask, sa->sa_len); 1965 makemask(&net->nt_mask, (int)preflen); 1966 opt_flags |= OP_HAVEMASK; |
1979 } | 1967 } |
1980 net->nt_name = strdup(name); 1981 memcpy(&net->nt_net, sa, sa->sa_len); | |
1982 } 1983 | 1968 } 1969 |
1984 if (!maskflg && sa->sa_family == AF_INET && 1985 !(opt_flags & (OP_MASK|OP_MASKLEN))) { 1986 sinp = (struct sockaddr_in *)sa; 1987 if (IN_CLASSA(sinp->sin_addr.s_addr)) 1988 net->nt_mask = 8; 1989 else if (IN_CLASSB(sinp->sin_addr.s_addr)) 1990 net->nt_mask = 16; 1991 else if (IN_CLASSC(sinp->sin_addr.s_addr)) 1992 net->nt_mask = 24; 1993 else if (IN_CLASSD(sinp->sin_addr.s_addr)) 1994 net->nt_mask = 28; 1995 else 1996 net->nt_mask = 32; /* XXX */ 1997 } 1998 | |
1999 if (ai) 2000 freeaddrinfo(ai); 2001 return 0; 2002 2003fail: 2004 if (ai) 2005 freeaddrinfo(ai); 2006 return 1; --- 294 unchanged lines hidden (view full) --- 2301 return (1); 2302 if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL) || 2303 (opt_flags & (OP_MAPROOT | OP_KERB)) == (OP_MAPROOT | OP_KERB) || 2304 (opt_flags & (OP_MAPALL | OP_KERB)) == (OP_MAPALL | OP_KERB)) { 2305 syslog(LOG_ERR, "-mapall, -maproot and -kerb mutually exclusive"); 2306 return (1); 2307 } 2308 if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { | 1970 if (ai) 1971 freeaddrinfo(ai); 1972 return 0; 1973 1974fail: 1975 if (ai) 1976 freeaddrinfo(ai); 1977 return 1; --- 294 unchanged lines hidden (view full) --- 2272 return (1); 2273 if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL) || 2274 (opt_flags & (OP_MAPROOT | OP_KERB)) == (OP_MAPROOT | OP_KERB) || 2275 (opt_flags & (OP_MAPALL | OP_KERB)) == (OP_MAPALL | OP_KERB)) { 2276 syslog(LOG_ERR, "-mapall, -maproot and -kerb mutually exclusive"); 2277 return (1); 2278 } 2279 if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { |
2309 syslog(LOG_ERR, "-mask requires -net"); 2310 return (1); | 2280 syslog(LOG_ERR, "-mask requires -network"); 2281 return (1); |
2311 } | 2282 } |
2283 if ((opt_flags & OP_NET) && (opt_flags & OP_HAVEMASK) == 0) { 2284 syslog(LOG_ERR, "-network requires mask specification"); 2285 return (1); 2286 } 2287 if ((opt_flags & OP_MASK) && (opt_flags & OP_MASKLEN)) { 2288 syslog(LOG_ERR, "-mask and /masklen are mutually exclusive"); 2289 return (1); 2290 } |
|
2312 if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 2313 syslog(LOG_ERR, "-alldirs has multiple directories"); 2314 return (1); 2315 } 2316 return (0); 2317} 2318 2319/* --- 17 unchanged lines hidden (view full) --- 2337 } 2338 cp++; 2339 } 2340 if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 2341 ret = 0; 2342 return (ret); 2343} 2344 | 2291 if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { 2292 syslog(LOG_ERR, "-alldirs has multiple directories"); 2293 return (1); 2294 } 2295 return (0); 2296} 2297 2298/* --- 17 unchanged lines hidden (view full) --- 2316 } 2317 cp++; 2318 } 2319 if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode)) 2320 ret = 0; 2321 return (ret); 2322} 2323 |
2345static int 2346netpartcmp(struct sockaddr *s1, struct sockaddr *s2, int bitlen) | 2324/* 2325 * Make a netmask according to the specified prefix length. The ss_family 2326 * and other non-address fields must be initialised before calling this. 2327 */ 2328int 2329makemask(struct sockaddr_storage *ssp, int bitlen) |
2347{ | 2330{ |
2348 void *src, *dst; | 2331 u_char *p; 2332 int bits, i, len; |
2349 | 2333 |
2350 if (s1->sa_family != s2->sa_family) 2351 return 1; | 2334 if ((p = sa_rawaddr((struct sockaddr *)ssp, &len)) == NULL) 2335 return (-1); 2336 if (bitlen > len * NBBY) 2337 return (-1); |
2352 | 2338 |
2353 switch (s1->sa_family) { 2354 case AF_INET: 2355 src = &((struct sockaddr_in *)s1)->sin_addr; 2356 dst = &((struct sockaddr_in *)s2)->sin_addr; 2357 if (bitlen > sizeof(((struct sockaddr_in *)s1)->sin_addr) * 8) 2358 return 1; 2359 break; 2360 case AF_INET6: 2361 src = &((struct sockaddr_in6 *)s1)->sin6_addr; 2362 dst = &((struct sockaddr_in6 *)s2)->sin6_addr; 2363 if (((struct sockaddr_in6 *)s1)->sin6_scope_id != 2364 ((struct sockaddr_in6 *)s2)->sin6_scope_id) 2365 return 1; 2366 if (bitlen > sizeof(((struct sockaddr_in6 *)s1)->sin6_addr) * 8) 2367 return 1; 2368 break; 2369 default: 2370 return 1; | 2339 for (i = 0; i < len; i++) { 2340 bits = (bitlen > NBBY) ? NBBY : bitlen; 2341 *p++ = (1 << bits) - 1; 2342 bitlen -= bits; |
2371 } | 2343 } |
2372 2373 return bitcmp(src, dst, bitlen); | 2344 return 0; |
2374} 2375 | 2345} 2346 |
2376static int 2377allones(struct sockaddr_storage *ssp, int bitlen) | 2347/* 2348 * Check that the sockaddr is a valid netmask. Returns 0 if the mask 2349 * is acceptable (i.e. of the form 1...10....0). 2350 */ 2351int 2352checkmask(struct sockaddr *sa) |
2378{ | 2353{ |
2379 u_int8_t *p; 2380 int bytelen, bitsleft, i; 2381 int zerolen; | 2354 u_char *mask; 2355 int i, len; |
2382 | 2356 |
2383 switch (ssp->ss_family) { 2384 case AF_INET: 2385 p = (u_int8_t *)&((struct sockaddr_in *)ssp)->sin_addr; 2386 zerolen = sizeof (((struct sockaddr_in *)ssp)->sin_addr); 2387 break; 2388 case AF_INET6: 2389 p = (u_int8_t *)&((struct sockaddr_in6 *)ssp)->sin6_addr; 2390 zerolen = sizeof (((struct sockaddr_in6 *)ssp)->sin6_addr); 2391 break; 2392 default: 2393 return -1; 2394 } | 2357 if ((mask = sa_rawaddr(sa, &len)) == NULL) 2358 return (-1); |
2395 | 2359 |
2396 memset(p, 0, zerolen); 2397 2398 bytelen = bitlen / 8; 2399 bitsleft = bitlen % 8; 2400 2401 if (bytelen > zerolen) 2402 return -1; 2403 2404 for (i = 0; i < bytelen; i++) 2405 *p++ = 0xff; 2406 2407 for (i = 0; i < bitsleft; i++) 2408 *p |= 1 << (7 - i); 2409 2410 return 0; | 2360 for (i = 0; i < len; i++) 2361 if (mask[i] != 0xff) 2362 break; 2363 if (i < len) { 2364 if (~mask[i] & (u_char)(~mask[i] + 1)) 2365 return (-1); 2366 i++; 2367 } 2368 for (; i < len; i++) 2369 if (mask[i] != 0) 2370 return (-1); 2371 return (0); |
2411} 2412 | 2372} 2373 |
2413static int 2414countones(struct sockaddr *sa) | 2374/* 2375 * Compare two sockaddrs according to a specified mask. Return zero if 2376 * `sa1' matches `sa2' when filtered by the netmask in `samask'. 2377 * If samask is NULL, perform a full comparision. 2378 */ 2379int 2380sacmp(struct sockaddr *sa1, struct sockaddr *sa2, struct sockaddr *samask) |
2415{ | 2381{ |
2416 void *mask; 2417 int i, bits = 0, bytelen; 2418 u_int8_t *p; | 2382 unsigned char *p1, *p2, *mask; 2383 int len, i; |
2419 | 2384 |
2420 switch (sa->sa_family) { 2421 case AF_INET: 2422 mask = (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr; 2423 bytelen = 4; 2424 break; | 2385 if (sa1->sa_family != sa2->sa_family || 2386 (p1 = sa_rawaddr(sa1, &len)) == NULL || 2387 (p2 = sa_rawaddr(sa2, NULL)) == NULL) 2388 return (1); 2389 2390 switch (sa1->sa_family) { |
2425 case AF_INET6: | 2391 case AF_INET6: |
2426 mask = (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr; 2427 bytelen = 16; | 2392 if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != 2393 ((struct sockaddr_in6 *)sa2)->sin6_scope_id) 2394 return (1); |
2428 break; | 2395 break; |
2429 default: 2430 return 0; | |
2431 } 2432 | 2396 } 2397 |
2433 p = mask; | 2398 /* Simple binary comparison if no mask specified. */ 2399 if (samask == NULL) 2400 return (memcmp(p1, p2, len)); |
2434 | 2401 |
2435 for (i = 0; i < bytelen; i++, p++) { 2436 if (*p != 0xff) { 2437 for (bits = 0; bits < 8; bits++) { 2438 if (!(*p & (1 << (7 - bits)))) 2439 break; 2440 } 2441 break; 2442 } 2443 } | 2402 /* Set up the mask, and do a mask-based comparison. */ 2403 if (sa1->sa_family != samask->sa_family || 2404 (mask = sa_rawaddr(samask, NULL)) == NULL) 2405 return (1); |
2444 | 2406 |
2445 return (i * 8 + bits); | 2407 for (i = 0; i < len; i++) 2408 if ((p1[i] & mask[i]) != (p2[i] & mask[i])) 2409 return (1); 2410 return (0); |
2446} 2447 | 2411} 2412 |
2448static int 2449sacmp(struct sockaddr *sa1, struct sockaddr *sa2) 2450{ 2451 void *p1, *p2; | 2413/* 2414 * Return a pointer to the part of the sockaddr that contains the 2415 * raw address, and set *nbytes to its length in bytes. Returns 2416 * NULL if the address family is unknown. 2417 */ 2418void * 2419sa_rawaddr(struct sockaddr *sa, int *nbytes) { 2420 void *p; |
2452 int len; 2453 | 2421 int len; 2422 |
2454 if (sa1->sa_family != sa2->sa_family) 2455 return 1; 2456 2457 switch (sa1->sa_family) { | 2423 switch (sa->sa_family) { |
2458 case AF_INET: | 2424 case AF_INET: |
2459 p1 = &((struct sockaddr_in *)sa1)->sin_addr; 2460 p2 = &((struct sockaddr_in *)sa2)->sin_addr; 2461 len = 4; | 2425 len = sizeof(((struct sockaddr_in *)sa)->sin_addr); 2426 p = &((struct sockaddr_in *)sa)->sin_addr; |
2462 break; 2463 case AF_INET6: | 2427 break; 2428 case AF_INET6: |
2464 p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr; 2465 p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr; 2466 len = 16; 2467 if (((struct sockaddr_in6 *)sa1)->sin6_scope_id != 2468 ((struct sockaddr_in6 *)sa2)->sin6_scope_id) 2469 return 1; | 2429 len = sizeof(((struct sockaddr_in6 *)sa)->sin6_addr); 2430 p = &((struct sockaddr_in6 *)sa)->sin6_addr; |
2470 break; 2471 default: | 2431 break; 2432 default: |
2472 return 1; | 2433 p = NULL; 2434 len = 0; |
2473 } 2474 | 2435 } 2436 |
2475 return memcmp(p1, p2, len); | 2437 if (nbytes != NULL) 2438 *nbytes = len; 2439 return (p); |
2476} 2477 2478void 2479huphandler(int sig) 2480{ 2481 got_sighup = 1; 2482} 2483 2484void terminate(sig) 2485int sig; 2486{ 2487 close(mountdlockfd); 2488 unlink(MOUNTDLOCK); 2489 rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 2490 rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 2491 exit (0); 2492} | 2440} 2441 2442void 2443huphandler(int sig) 2444{ 2445 got_sighup = 1; 2446} 2447 2448void terminate(sig) 2449int sig; 2450{ 2451 close(mountdlockfd); 2452 unlink(MOUNTDLOCK); 2453 rpcb_unset(RPCPROG_MNT, RPCMNT_VER1, NULL); 2454 rpcb_unset(RPCPROG_MNT, RPCMNT_VER3, NULL); 2455 exit (0); 2456} |