Module Name: src Committed By: christos Date: Wed Dec 23 16:19:49 UTC 2015
Modified Files: src/usr.sbin/mountd: Makefile mountd.c Added Files: src/usr.sbin/mountd: get_net.c mountd.h Log Message: Split out get_net function so that it is easily testable. Restore functionality where 1.2.3/24 -> 1.2.3.0/24 not 1.2.0.3/24 now that getaddrinfo(3) parses old-style incomplete dotted quads as old style addresses. To generate a diff of this commit: cvs rdiff -u -r1.18 -r1.19 src/usr.sbin/mountd/Makefile cvs rdiff -u -r0 -r1.1 src/usr.sbin/mountd/get_net.c \ src/usr.sbin/mountd/mountd.h cvs rdiff -u -r1.128 -r1.129 src/usr.sbin/mountd/mountd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/mountd/Makefile diff -u src/usr.sbin/mountd/Makefile:1.18 src/usr.sbin/mountd/Makefile:1.19 --- src/usr.sbin/mountd/Makefile:1.18 Mon May 28 08:06:37 2007 +++ src/usr.sbin/mountd/Makefile Wed Dec 23 11:19:49 2015 @@ -1,10 +1,10 @@ -# $NetBSD: Makefile,v 1.18 2007/05/28 12:06:37 tls Exp $ +# $NetBSD: Makefile,v 1.19 2015/12/23 16:19:49 christos Exp $ # @(#)Makefile 8.3 (Berkeley) 1/25/94 USE_FORT?= yes # network server PROG= mountd -SRCS= mountd.c ipsec.c +SRCS= mountd.c ipsec.c get_net.c MAN= exports.5 mountd.8 INETDDIR= ${.CURDIR}/../inetd Index: src/usr.sbin/mountd/mountd.c diff -u src/usr.sbin/mountd/mountd.c:1.128 src/usr.sbin/mountd/mountd.c:1.129 --- src/usr.sbin/mountd/mountd.c:1.128 Sun Nov 8 16:03:16 2015 +++ src/usr.sbin/mountd/mountd.c Wed Dec 23 11:19:49 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: mountd.c,v 1.128 2015/11/08 21:03:16 christos Exp $ */ +/* $NetBSD: mountd.c,v 1.129 2015/12/23 16:19:49 christos Exp $ */ /* * Copyright (c) 1989, 1993 @@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 19 #if 0 static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; #else -__RCSID("$NetBSD: mountd.c,v 1.128 2015/11/08 21:03:16 christos Exp $"); +__RCSID("$NetBSD: mountd.c,v 1.129 2015/12/23 16:19:49 christos Exp $"); #endif #endif /* not lint */ @@ -105,6 +105,8 @@ __RCSID("$NetBSD: mountd.c,v 1.128 2015/ #define DEBUGGING 0 #endif +#include "mountd.h" + /* * Structures for keeping the mount list and export list */ @@ -140,12 +142,6 @@ struct exportlist { /* ex_flag bits */ #define EX_LINKED 0x1 -struct netmsk { - struct sockaddr_storage nt_net; - int nt_len; - char *nt_name; -}; - union grouptypes { struct addrinfo *gt_addrinfo; struct netmsk gt_net; @@ -206,7 +202,6 @@ static int get_host(const char *, size_t struct grouplist *); static struct hostlist *get_ht(void); static void get_mountlist(void); -static int get_net(char *, struct netmsk *, int); static void free_exp_grp(struct exportlist *, struct grouplist *); static struct grouplist *get_grp(void); static void hang_dirp(struct dirlist *, struct grouplist *, @@ -225,7 +220,6 @@ static int bitcmp(void *, void *, int); static int netpartcmp(struct sockaddr *, struct sockaddr *, int); static int sacmp(struct sockaddr *, struct sockaddr *); static int allones(struct sockaddr_storage *, int); -static int countones(struct sockaddr *); static void bind_resv_port(int, sa_family_t, in_port_t); __dead static void no_nfs(int); static struct exportlist *exphead; @@ -240,22 +234,11 @@ static struct uucred def_anon = { { 0 } }; -static int opt_flags; +int opt_flags; static int have_v6 = 1; -static const int ninumeric = NI_NUMERICHOST; - -/* Bits for above */ -#define OP_MAPROOT 0x001 -#define OP_MAPALL 0x002 -#define OP_KERB 0x004 -#define OP_MASK 0x008 -#define OP_NET 0x010 -#define OP_ALLDIRS 0x040 -#define OP_NORESPORT 0x080 -#define OP_NORESMNT 0x100 -#define OP_MASKLEN 0x200 +const int ninumeric = NI_NUMERICHOST; -static int debug = DEBUGGING; +int debug = DEBUGGING; #if 0 static void SYSLOG(int, const char *,...); #endif @@ -1590,41 +1573,6 @@ allones(struct sockaddr_storage *ssp, in } static int -countones(struct sockaddr *sa) -{ - void *mask; - int i, bits = 0, bytelen; - u_int8_t *p; - - switch (sa->sa_family) { - case AF_INET: - mask = (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr; - bytelen = 4; - break; - case AF_INET6: - mask = (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr; - bytelen = 16; - break; - default: - return 0; - } - - p = mask; - - for (i = 0; i < bytelen; i++, p++) { - if (*p != 0xff) { - for (bits = 0; bits < 8; bits++) { - if (!(*p & (1 << (7 - bits)))) - break; - } - break; - } - } - - return (i * 8 + bits); -} - -static int sacmp(struct sockaddr *sa1, struct sockaddr *sa2) { void *p1, *p2; @@ -2051,125 +1999,6 @@ skip: } /* - * Translate a net address. - */ -static int -get_net(char *cp, struct netmsk *net, int maskflg) -{ - struct netent *np; - char *nname, *p, *prefp; - struct sockaddr_in sin, *sinp; - struct sockaddr *sa; - struct addrinfo hints, *ai = NULL; - char netname[NI_MAXHOST]; - long preflen; - int ecode; - - (void)memset(&sin, 0, sizeof(sin)); - if ((opt_flags & OP_MASKLEN) && !maskflg) { - p = strchr(cp, '/'); - *p = '\0'; - prefp = p + 1; - } else { - p = NULL; /* XXXGCC -Wuninitialized */ - prefp = NULL; /* XXXGCC -Wuninitialized */ - } - - if ((np = getnetbyname(cp)) != NULL) { - sin.sin_family = AF_INET; - sin.sin_len = sizeof sin; - sin.sin_addr = inet_makeaddr(np->n_net, 0); - sa = (struct sockaddr *)&sin; - } else if (isdigit((unsigned char)*cp)) { - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(cp, NULL, &hints, &ai) != 0) { - /* - * If getaddrinfo() failed, try the inet4 network - * notation with less than 3 dots. - */ - sin.sin_family = AF_INET; - sin.sin_len = sizeof sin; - sin.sin_addr = inet_makeaddr(inet_network(cp),0); - if (debug) - fprintf(stderr, "get_net: v4 addr %x\n", - sin.sin_addr.s_addr); - sa = (struct sockaddr *)&sin; - } else - sa = ai->ai_addr; - } else if (isxdigit((unsigned char)*cp) || *cp == ':') { - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(cp, NULL, &hints, &ai) == 0) - sa = ai->ai_addr; - else - goto fail; - } else - goto fail; - - /* - * Only allow /pref notation for v6 addresses. - */ - if (sa->sa_family == AF_INET6 && (!(opt_flags & OP_MASKLEN) || maskflg)) - return 1; - - ecode = getnameinfo(sa, sa->sa_len, netname, sizeof netname, - NULL, 0, ninumeric); - if (ecode != 0) - goto fail; - - if (maskflg) - net->nt_len = countones(sa); - else { - if (opt_flags & OP_MASKLEN) { - errno = 0; - preflen = strtol(prefp, NULL, 10); - if (preflen == LONG_MIN && errno == ERANGE) - goto fail; - net->nt_len = (int)preflen; - *p = '/'; - } - - if (np) - nname = np->n_name; - else { - if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, - NULL, 0, ninumeric) != 0) - strlcpy(netname, "?", sizeof(netname)); - nname = netname; - } - net->nt_name = estrdup(nname); - memcpy(&net->nt_net, sa, sa->sa_len); - } - - if (!maskflg && sa->sa_family == AF_INET && - !(opt_flags & (OP_MASK|OP_MASKLEN))) { - sinp = (struct sockaddr_in *)sa; - if (IN_CLASSA(sinp->sin_addr.s_addr)) - net->nt_len = 8; - else if (IN_CLASSB(sinp->sin_addr.s_addr)) - net->nt_len = 16; - else if (IN_CLASSC(sinp->sin_addr.s_addr)) - net->nt_len = 24; - else if (IN_CLASSD(sinp->sin_addr.s_addr)) - net->nt_len = 28; - else - net->nt_len = 32; /* XXX */ - } - - if (ai) - freeaddrinfo(ai); - return 0; - -fail: - if (ai) - freeaddrinfo(ai); - return 1; -} - -/* * Parse out the next white space separated field */ static void Added files: Index: src/usr.sbin/mountd/get_net.c diff -u /dev/null src/usr.sbin/mountd/get_net.c:1.1 --- /dev/null Wed Dec 23 11:19:49 2015 +++ src/usr.sbin/mountd/get_net.c Wed Dec 23 11:19:49 2015 @@ -0,0 +1,236 @@ +/* $NetBSD: get_net.c,v 1.1 2015/12/23 16:19:49 christos Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Herb Hasler and Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__RCSID("$NetBSD: get_net.c,v 1.1 2015/12/23 16:19:49 christos Exp $"); + +#include <sys/types.h> +#include <netdb.h> +#include <stdio.h> +#include <limits.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <util.h> +#include <arpa/inet.h> +#include <netinet/in.h> + +#include "mountd.h" + +#ifdef TEST +int opt_flags; +const int ninumeric = NI_NUMERICHOST; +int debug = 1; +#endif + +static int +isdottedquad(const char *cp) +{ + for (;;) + switch (*cp++) { + case '\0': + return 1; + case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + continue; + default: + return 0; + } +} + +static int +countones(struct sockaddr *sa) +{ + void *mask; + int i, bits = 0, bytelen; + u_int8_t *p; + + switch (sa->sa_family) { + case AF_INET: + mask = (u_int8_t *)&((struct sockaddr_in *)sa)->sin_addr; + bytelen = 4; + break; + case AF_INET6: + mask = (u_int8_t *)&((struct sockaddr_in6 *)sa)->sin6_addr; + bytelen = 16; + break; + default: + return 0; + } + + p = mask; + + for (i = 0; i < bytelen; i++, p++) { + if (*p != 0xff) { + for (bits = 0; bits < 8; bits++) { + if (!(*p & (1 << (7 - bits)))) + break; + } + break; + } + } + + return (i * 8 + bits); +} + +/* + * Translate a net address. + */ +int +get_net(char *cp, struct netmsk *net, int maskflg) +{ + struct netent *np; + char *nname, *p, *prefp; + struct sockaddr_in sin, *sinp; + struct sockaddr *sa; + struct addrinfo hints, *ai = NULL; + char netname[NI_MAXHOST]; + long preflen; + int ecode; + + (void)memset(&sin, 0, sizeof(sin)); + if ((opt_flags & OP_MASKLEN) && !maskflg) { + p = strchr(cp, '/'); + *p = '\0'; + prefp = p + 1; + } else { + p = NULL; /* XXXGCC -Wuninitialized */ + prefp = NULL; /* XXXGCC -Wuninitialized */ + } + + if ((np = getnetbyname(cp)) != NULL) { + sin.sin_family = AF_INET; + sin.sin_len = sizeof sin; + sin.sin_addr = inet_makeaddr(np->n_net, 0); + sa = (struct sockaddr *)&sin; + } else if (isdottedquad(cp)) { + /* + * Handle dotted quad [or less than quad] notation specially + * because getaddrinfo() will parse them in the old style: + * i.e. 1.2.3 -> 1.2.0.3 not 1.2.3.0 + */ + sin.sin_family = AF_INET; + sin.sin_len = sizeof sin; + sin.sin_addr = inet_makeaddr(inet_network(cp), 0); + if (debug) + fprintf(stderr, "get_net: '%s' v4 addr %x\n", + cp, sin.sin_addr.s_addr); + sa = (struct sockaddr *)&sin; + } else { + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(cp, NULL, &hints, &ai) == 0) + sa = ai->ai_addr; + else + goto fail; + } + + /* + * Only allow /pref notation for v6 addresses. + */ + if (sa->sa_family == AF_INET6 && (!(opt_flags & OP_MASKLEN) || maskflg)) + return 1; + + ecode = getnameinfo(sa, sa->sa_len, netname, sizeof netname, + NULL, 0, ninumeric); + if (ecode != 0) + goto fail; + + if (maskflg) + net->nt_len = countones(sa); + else { + if (opt_flags & OP_MASKLEN) { + errno = 0; + preflen = strtol(prefp, NULL, 10); + if (preflen == LONG_MIN && errno == ERANGE) + goto fail; + net->nt_len = (int)preflen; + *p = '/'; + } + + if (np) + nname = np->n_name; + else { + if (getnameinfo(sa, sa->sa_len, netname, sizeof netname, + NULL, 0, ninumeric) != 0) + strlcpy(netname, "?", sizeof(netname)); + nname = netname; + } + net->nt_name = estrdup(nname); + memcpy(&net->nt_net, sa, sa->sa_len); + } + + if (!maskflg && sa->sa_family == AF_INET && + !(opt_flags & (OP_MASK|OP_MASKLEN))) { + sinp = (struct sockaddr_in *)sa; + if (IN_CLASSA(sinp->sin_addr.s_addr)) + net->nt_len = 8; + else if (IN_CLASSB(sinp->sin_addr.s_addr)) + net->nt_len = 16; + else if (IN_CLASSC(sinp->sin_addr.s_addr)) + net->nt_len = 24; + else if (IN_CLASSD(sinp->sin_addr.s_addr)) + net->nt_len = 28; + else + net->nt_len = 32; /* XXX */ + } + + if (ai) + freeaddrinfo(ai); + return 0; + +fail: + if (ai) + freeaddrinfo(ai); + return 1; +} + +#ifdef TEST +int +main(int argc, char *argv[]) +{ + char buf[1024]; + struct netmsk nm; + + if (get_net(argv[1], &nm, 0)) + errx(EXIT_FAILURE, "get_net failed"); + + sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&nm.nt_net); + printf("%s %d %s\n", buf, nm.nt_len, nm.nt_name); + return 0; +} +#endif Index: src/usr.sbin/mountd/mountd.h diff -u /dev/null src/usr.sbin/mountd/mountd.h:1.1 --- /dev/null Wed Dec 23 11:19:49 2015 +++ src/usr.sbin/mountd/mountd.h Wed Dec 23 11:19:49 2015 @@ -0,0 +1,22 @@ + +#define OP_MAPROOT 0x001 +#define OP_MAPALL 0x002 +#define OP_KERB 0x004 +#define OP_MASK 0x008 +#define OP_NET 0x010 +#define OP_ALLDIRS 0x040 +#define OP_NORESPORT 0x080 +#define OP_NORESMNT 0x100 +#define OP_MASKLEN 0x200 + +extern int opt_flags; +extern int debug; +extern const int ninumeric; + +struct netmsk { + struct sockaddr_storage nt_net; + int nt_len; + char *nt_name; +}; + +int get_net(char *, struct netmsk *, int);