diff options
Diffstat (limited to 'usr.sbin')
28 files changed, 1300 insertions, 453 deletions
diff --git a/usr.sbin/route6d/Makefile b/usr.sbin/route6d/Makefile index df23d33..51c59b8 100644 --- a/usr.sbin/route6d/Makefile +++ b/usr.sbin/route6d/Makefile @@ -6,6 +6,6 @@ MAN= route6d.8 CFLAGS+= -DHAVE_POLL_H -WARNS?= 1 +WARNS?= 6 .include <bsd.prog.mk> diff --git a/usr.sbin/route6d/route6d.8 b/usr.sbin/route6d/route6d.8 index 121f5f2..db0e70f 100644 --- a/usr.sbin/route6d/route6d.8 +++ b/usr.sbin/route6d/route6d.8 @@ -16,7 +16,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 31, 1997 +.Dd July 21, 2009 .Dt ROUTE6D 8 .Os .Sh NAME @@ -26,6 +26,15 @@ .Nm .Op Fl adDhlnqsS .Bk -words +.Op Fl p Ar pidfile +.Ek +.Bk -words +.Op Fl P Ar protonum +.Ek +.Bk -words +.Op Fl Q Ar protonum +.Ek +.Bk -words .Op Fl R Ar routelog .Ek .Bk -words @@ -62,6 +71,29 @@ statically defined routes will be removed unless corresponding updates arrive as if the routes are received at the startup of .Nm . .\" +.It Fl p Ar pidfile +This option specifies PID filename as +.Ar pidfile . +The default value is +.Pa /var/run/route6d.pid . +.It Fl P Ar protonum +This option makes the +.Nm +recognize a route with RTF_PROTO[123] flag as one with infinite lifetime. The +.Ar protonum +must be 1, 2, or 3 and they corresponds to RTF_PROTO1, RTF_PROTO2, and +RTF_PROTO3, respectively. Multiple +.Fl P +flags are allowed. +.It Fl Q Ar protonum +This option makes the +.Nm +add RTF_PROTO[123] flags to routes which are obtained via RIP sessions. The +.Ar protonum +must be 1, 2, or 3 and they corresponds to RTF_PROTO1, RTF_PROTO2, and +RTF_PROTO3, respectively. Multiple +.Fl Q +flags are allowed. .It Fl R Ar routelog This option makes the .Nm diff --git a/usr.sbin/route6d/route6d.c b/usr.sbin/route6d/route6d.c index 0205a03..761deeb 100644 --- a/usr.sbin/route6d/route6d.c +++ b/usr.sbin/route6d/route6d.c @@ -31,13 +31,14 @@ */ #ifndef lint -static char _rcsid[] = "$KAME: route6d.c,v 1.104 2003/10/31 00:30:20 itojun Exp $"; +static const char _rcsid[] = "$KAME: route6d.c,v 1.104 2003/10/31 00:30:20 itojun Exp $"; #endif #include <stdio.h> #include <time.h> #include <unistd.h> +#include <fnmatch.h> #include <stdlib.h> #include <string.h> #include <signal.h> @@ -78,6 +79,7 @@ static char _rcsid[] = "$KAME: route6d.c,v 1.104 2003/10/31 00:30:20 itojun Exp #include "route6d.h" #define MAXFILTER 40 +#define RT_DUMP_MAXRETRY 15 #ifdef DEBUG #define INIT_INTERVAL6 6 @@ -103,7 +105,7 @@ static char _rcsid[] = "$KAME: route6d.c,v 1.104 2003/10/31 00:30:20 itojun Exp } while (0) struct ifc { /* Configuration of an interface */ - char *ifc_name; /* if name */ + char ifc_name[IFNAMSIZ]; /* if name */ struct ifc *ifc_next; int ifc_index; /* if index */ int ifc_mtu; /* if mtu */ @@ -112,7 +114,6 @@ struct ifc { /* Configuration of an interface */ short ifc_cflags; /* IFC_XXX */ struct in6_addr ifc_mylladdr; /* my link-local address */ struct sockaddr_in6 ifc_ripsin; /* rip multicast address */ - struct iff *ifc_filter; /* filter structure */ struct ifac *ifc_addr; /* list of AF_INET6 addresses */ int ifc_joined; /* joined to ff02::9 */ }; @@ -126,6 +127,7 @@ struct ifac { /* Adddress associated to an interface */ }; struct iff { + char iff_name[IFNAMSIZ]; int iff_type; struct in6_addr iff_addr; int iff_plen; @@ -133,9 +135,10 @@ struct iff { }; struct ifc *ifc; +struct iff *iff_head; int nifc; /* number of valid ifc's */ struct ifc **index2ifc; -int nindex2ifc; +unsigned int nindex2ifc; struct ifc *loopifcp = NULL; /* pointing to loopback */ #ifdef HAVE_POLL_H struct pollfd set[2]; @@ -181,6 +184,8 @@ int nflag = 0; /* don't update kernel routing table */ int aflag = 0; /* age out even the statically defined routes */ int hflag = 0; /* don't split horizon */ int lflag = 0; /* exchange site local routes */ +int Pflag = 0; /* don't age out routes with RTF_PROTO[123] */ +int Qflag = RTF_PROTO2; /* set RTF_PROTO[123] flag to routes by RIPng */ int sflag = 0; /* announce static routes w/ split horizon */ int Sflag = 0; /* announce static routes to every interface */ unsigned long routetag = 0; /* route tag attached on originating case */ @@ -222,7 +227,7 @@ int out_filter(struct riprt *, struct ifc *); void init(void); void sockopt(struct ifc *); void ifconfig(void); -void ifconfig1(const char *, const struct sockaddr *, struct ifc *, int); +int ifconfig1(const char *, const struct sockaddr *, struct ifc *, int); void rtrecv(void); int rt_del(const struct sockaddr_in6 *, const struct sockaddr_in6 *, const struct sockaddr_in6 *); @@ -240,12 +245,13 @@ void applyplen(struct in6_addr *, int); void ifrtdump(int); void ifdump(int); void ifdump0(FILE *, const struct ifc *); +void ifremove(int); void rtdump(int); void rt_entry(struct rt_msghdr *, int); void rtdexit(void); void riprequest(struct ifc *, struct netinfo6 *, int, struct sockaddr_in6 *); -void ripflush(struct ifc *, struct sockaddr_in6 *); +void ripflush(struct ifc *, struct sockaddr_in6 *, int, struct netinfo6 *np); void sendrequest(struct ifc *); int sin6mask2len(const struct sockaddr_in6 *); int mask2len(const struct in6_addr *, int); @@ -276,16 +282,23 @@ void setindex2ifc(int, struct ifc *); #define MALLOC(type) ((type *)malloc(sizeof(type))) +#define IFIL_TYPE_ANY 0 +#define IFIL_TYPE_A 'A' +#define IFIL_TYPE_N 'N' +#define IFIL_TYPE_T 'T' +#define IFIL_TYPE_O 'O' +#define IFIL_TYPE_L 'L' + int -main(argc, argv) - int argc; - char **argv; +main(int argc, char *argv[]) { int ch; int error = 0; + unsigned long proto; struct ifc *ifcp; sigset_t mask, omask; - FILE *pidfile; + const char *pidfile = ROUTE6D_PID; + FILE *pidfh; char *progname; char *ep; @@ -296,7 +309,7 @@ main(argc, argv) progname = *argv; pid = getpid(); - while ((ch = getopt(argc, argv, "A:N:O:R:T:L:t:adDhlnqsS")) != -1) { + while ((ch = getopt(argc, argv, "A:N:O:R:T:L:t:adDhlnp:P:Q:qsS")) != -1) { switch (ch) { case 'A': case 'N': @@ -318,6 +331,41 @@ main(argc, argv) /*NOTREACHED*/ } break; + case 'p': + pidfile = optarg; + break; + case 'P': + ep = NULL; + proto = strtoul(optarg, &ep, 0); + if (!ep || *ep != '\0' || 3 < proto) { + fatal("invalid P flag"); + /*NOTREACHED*/ + } + if (proto == 0) + Pflag = 0; + if (proto == 1) + Pflag |= RTF_PROTO1; + if (proto == 2) + Pflag |= RTF_PROTO2; + if (proto == 3) + Pflag |= RTF_PROTO3; + break; + case 'Q': + ep = NULL; + proto = strtoul(optarg, &ep, 0); + if (!ep || *ep != '\0' || 3 < proto) { + fatal("invalid Q flag"); + /*NOTREACHED*/ + } + if (proto == 0) + Qflag = 0; + if (proto == 1) + Qflag |= RTF_PROTO1; + if (proto == 2) + Qflag |= RTF_PROTO2; + if (proto == 3) + Qflag |= RTF_PROTO3; + break; case 'R': if ((rtlog = fopen(optarg, "w")) == NULL) { fatal("Can not write to routelog"); @@ -395,9 +443,9 @@ main(argc, argv) #if 1 pid = getpid(); - if ((pidfile = fopen(ROUTE6D_PID, "w")) != NULL) { - fprintf(pidfile, "%d\n", pid); - fclose(pidfile); + if ((pidfh = fopen(pidfile, "w")) != NULL) { + fprintf(pidfh, "%d\n", pid); + fclose(pidfh); } #endif @@ -428,7 +476,7 @@ main(argc, argv) alarm(ripinterval(INIT_INTERVAL6)); for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { - if (iff_find(ifcp, 'N')) + if (iff_find(ifcp, IFIL_TYPE_N)) continue; if (ifcp->ifc_index > 0 && (ifcp->ifc_flags & IFF_UP)) sendrequest(ifcp); @@ -495,8 +543,7 @@ main(argc, argv) } void -sighandler(signo) - int signo; +sighandler(int signo) { switch (signo) { @@ -520,7 +567,7 @@ sighandler(signo) */ /* ARGSUSED */ void -rtdexit() +rtdexit(void) { struct riprt *rrt; @@ -547,7 +594,7 @@ rtdexit() */ /* ARGSUSED */ void -ripalarm() +ripalarm(void) { struct ifc *ifcp; struct riprt *rrt, *rrt_prev, *rrt_next; @@ -587,7 +634,7 @@ ripalarm() } void -init() +init(void) { int error; const int int0 = 0, int1 = 1, int255 = 255; @@ -735,13 +782,8 @@ init() /* * ripflush flushes the rip datagram stored in the rip buffer */ -static int nrt; -static struct netinfo6 *np; - void -ripflush(ifcp, sin6) - struct ifc *ifcp; - struct sockaddr_in6 *sin6; +ripflush(struct ifc *ifcp, struct sockaddr_in6 *sin6, int nrt, struct netinfo6 *np) { int i; int error; @@ -783,21 +825,19 @@ ripflush(ifcp, sin6) ifcp->ifc_name, inet6_n2p(&ifcp->ifc_ripsin.sin6_addr)); ifcp->ifc_flags &= ~IFF_UP; /* As if down for AF_INET6 */ } - nrt = 0; np = ripbuf->rip6_nets; } /* * Generate RIP6_RESPONSE packets and send them. */ void -ripsend(ifcp, sin6, flag) - struct ifc *ifcp; - struct sockaddr_in6 *sin6; - int flag; +ripsend(struct ifc *ifcp, struct sockaddr_in6 *sin6, int flag) { struct riprt *rrt; struct in6_addr *nh; /* next hop */ + struct netinfo6 *np; int maxrte; + int nrt; if (qflag) return; @@ -811,7 +851,9 @@ ripsend(ifcp, sin6, flag) sizeof(struct udphdr) - sizeof(struct rip6) + sizeof(struct netinfo6)) / sizeof(struct netinfo6); - nrt = 0; np = ripbuf->rip6_nets; nh = NULL; + nh = NULL; + nrt = 0; + np = ripbuf->rip6_nets; for (rrt = riprt; rrt; rrt = rrt->rrt_next) { if (rrt->rrt_rflags & RRTF_NOADVERTISE) continue; @@ -819,12 +861,14 @@ ripsend(ifcp, sin6, flag) *np = rrt->rrt_info; np++; nrt++; if (nrt == maxrte) { - ripflush(NULL, sin6); + ripflush(NULL, sin6, nrt, np); nh = NULL; + nrt = 0; + np = ripbuf->rip6_nets; } } if (nrt) /* Send last packet */ - ripflush(NULL, sin6); + ripflush(NULL, sin6, nrt, np); return; } @@ -833,11 +877,11 @@ ripsend(ifcp, sin6, flag) return; /* -N: no use */ - if (iff_find(ifcp, 'N') != NULL) + if (iff_find(ifcp, IFIL_TYPE_N) != NULL) return; /* -T: generate default route only */ - if (iff_find(ifcp, 'T') != NULL) { + if (iff_find(ifcp, IFIL_TYPE_T) != NULL) { struct netinfo6 rrt_info; memset(&rrt_info, 0, sizeof(struct netinfo6)); rrt_info.rip6_dest = in6addr_any; @@ -848,7 +892,7 @@ ripsend(ifcp, sin6, flag) np = ripbuf->rip6_nets; *np = rrt_info; nrt = 1; - ripflush(ifcp, sin6); + ripflush(ifcp, sin6, nrt, np); return; } @@ -880,8 +924,13 @@ ripsend(ifcp, sin6, flag) !IN6_IS_ADDR_UNSPECIFIED(&rrt->rrt_gw) && (rrt->rrt_rflags & RRTF_NH_NOT_LLADDR) == 0) { if (nh == NULL || !IN6_ARE_ADDR_EQUAL(nh, &rrt->rrt_gw)) { - if (nrt == maxrte - 2) - ripflush(ifcp, sin6); + if (nrt == maxrte - 2) { + ripflush(ifcp, sin6, nrt, np); + nh = NULL; + nrt = 0; + np = ripbuf->rip6_nets; + } + np->rip6_dest = rrt->rrt_gw; if (IN6_IS_ADDR_LINKLOCAL(&np->rip6_dest)) SET_IN6_LINKLOCAL_IFINDEX(np->rip6_dest, 0); @@ -895,8 +944,12 @@ ripsend(ifcp, sin6, flag) !IN6_ARE_ADDR_EQUAL(nh, &rrt->rrt_gw) || rrt->rrt_rflags & RRTF_NH_NOT_LLADDR)) { /* Reset nexthop */ - if (nrt == maxrte - 2) - ripflush(ifcp, sin6); + if (nrt == maxrte - 2) { + ripflush(ifcp, sin6, nrt, np); + nh = NULL; + nrt = 0; + np = ripbuf->rip6_nets; + } memset(np, 0, sizeof(struct netinfo6)); np->rip6_metric = NEXTHOP_METRIC; nh = NULL; @@ -907,21 +960,21 @@ ripsend(ifcp, sin6, flag) *np = rrt->rrt_info; np++; nrt++; if (nrt == maxrte) { - ripflush(ifcp, sin6); + ripflush(ifcp, sin6, nrt, np); nh = NULL; + nrt = 0; + np = ripbuf->rip6_nets; } } if (nrt) /* Send last packet */ - ripflush(ifcp, sin6); + ripflush(ifcp, sin6, nrt, np); } /* * outbound filter logic, per-route/interface. */ int -out_filter(rrt, ifcp) - struct riprt *rrt; - struct ifc *ifcp; +out_filter(struct riprt *rrt, struct ifc *ifcp) { struct iff *iffp; struct in6_addr ia; @@ -931,9 +984,11 @@ out_filter(rrt, ifcp) * -A: filter out less specific routes, if we have aggregated * route configured. */ - for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { + for (iffp = iff_head; iffp; iffp = iffp->iff_next) { if (iffp->iff_type != 'A') continue; + if (fnmatch(iffp->iff_name, ifcp->ifc_name, 0) != 0) + continue; if (rrt->rrt_info.rip6_plen <= iffp->iff_plen) continue; ia = rrt->rrt_info.rip6_dest; @@ -948,9 +1003,11 @@ out_filter(rrt, ifcp) */ if ((rrt->rrt_rflags & RRTF_AGGREGATE) != 0) { ok = 0; - for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { + for (iffp = iff_head; iffp; iffp = iffp->iff_next) { if (iffp->iff_type != 'A') continue; + if (fnmatch(iffp->iff_name, ifcp->ifc_name, 0) != 0) + continue; if (rrt->rrt_info.rip6_plen == iffp->iff_plen && IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest, &iffp->iff_addr)) { @@ -965,11 +1022,13 @@ out_filter(rrt, ifcp) /* * -O: advertise only if prefix matches the configured prefix. */ - if (iff_find(ifcp, 'O')) { + if (iff_find(ifcp, IFIL_TYPE_O)) { ok = 0; - for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { + for (iffp = iff_head; iffp; iffp = iffp->iff_next) { if (iffp->iff_type != 'O') continue; + if (fnmatch(iffp->iff_name, ifcp->ifc_name, 0) != 0) + continue; if (rrt->rrt_info.rip6_plen < iffp->iff_plen) continue; ia = rrt->rrt_info.rip6_dest; @@ -992,9 +1051,7 @@ out_filter(rrt, ifcp) * It checks options specified in the arguments and the split horizon rule. */ int -tobeadv(rrt, ifcp) - struct riprt *rrt; - struct ifc *ifcp; +tobeadv(struct riprt *rrt, struct ifc *ifcp) { /* Special care for static routes */ @@ -1019,9 +1076,7 @@ tobeadv(rrt, ifcp) * Send a rip packet actually. */ int -sendpacket(sin6, len) - struct sockaddr_in6 *sin6; - int len; +sendpacket(struct sockaddr_in6 *sin6, int len) { struct msghdr m; struct cmsghdr *cm; @@ -1080,7 +1135,7 @@ sendpacket(sin6, len) * table if necessary. */ void -riprecv() +riprecv(void) { struct ifc *ifcp, *ic; struct sockaddr_in6 fsock; @@ -1147,7 +1202,7 @@ riprecv() if (idx && IN6_IS_ADDR_LINKLOCAL(&fsock.sin6_addr)) SET_IN6_LINKLOCAL_IFINDEX(fsock.sin6_addr, idx); - if (len < sizeof(struct rip6)) { + if ((size_t)len < sizeof(struct rip6)) { trace(1, "Packet too short\n"); return; } @@ -1235,7 +1290,7 @@ riprecv() } /* -N: no use */ - if (iff_find(ifcp, 'N') != NULL) + if (iff_find(ifcp, IFIL_TYPE_N) != NULL) return; tracet(1, "Recv(%s): from %s.%d info(%d)\n", @@ -1301,8 +1356,10 @@ riprecv() * -L: listen only if the prefix matches the configuration */ ok = 1; /* if there's no L filter, it is ok */ - for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { - if (iffp->iff_type != 'L') + for (iffp = iff_head; iffp; iffp = iffp->iff_next) { + if (iffp->iff_type != IFIL_TYPE_L) + continue; + if (fnmatch(iffp->iff_name, ifcp->ifc_name, 0) != 0) continue; ok = 0; if (np->rip6_plen < iffp->iff_plen) @@ -1429,8 +1486,7 @@ riprecv() * Send all routes request packet to the specified interface. */ void -sendrequest(ifcp) - struct ifc *ifcp; +sendrequest(struct ifc *ifcp) { struct netinfo6 *np; int error; @@ -1458,11 +1514,10 @@ sendrequest(ifcp) * Process a RIP6_REQUEST packet. */ void -riprequest(ifcp, np, nn, sin6) - struct ifc *ifcp; - struct netinfo6 *np; - int nn; - struct sockaddr_in6 *sin6; +riprequest(struct ifc *ifcp, + struct netinfo6 *np, + int nn, + struct sockaddr_in6 *sin6) { int i; struct riprt *rrt; @@ -1490,7 +1545,7 @@ riprequest(ifcp, np, nn, sin6) * Get information of each interface. */ void -ifconfig() +ifconfig(void) { struct ifaddrs *ifap, *ifa; struct ifc *ifcp; @@ -1525,9 +1580,8 @@ ifconfig() ifcp->ifc_next = ifc; ifc = ifcp; nifc++; - ifcp->ifc_name = allocopy(ifa->ifa_name); + strlcpy(ifcp->ifc_name, ifa->ifa_name, sizeof(ifcp->ifc_name)); ifcp->ifc_addr = 0; - ifcp->ifc_filter = 0; ifcp->ifc_flags = ifa->ifa_flags; trace(1, "newif %s <%s>\n", ifcp->ifc_name, ifflags(ifcp->ifc_flags)); @@ -1543,7 +1597,10 @@ ifconfig() } ifcp->ifc_flags = ifa->ifa_flags; } - ifconfig1(ifa->ifa_name, ifa->ifa_addr, ifcp, s); + if (ifconfig1(ifa->ifa_name, ifa->ifa_addr, ifcp, s) < 0) { + /* maybe temporary failure */ + continue; + } if ((ifcp->ifc_flags & (IFF_LOOPBACK | IFF_UP)) == IFF_UP && 0 < ifcp->ifc_index && !ifcp->ifc_joined) { mreq.ipv6mr_multiaddr = ifcp->ifc_ripsin.sin6_addr; @@ -1561,12 +1618,11 @@ ifconfig() freeifaddrs(ifap); } -void -ifconfig1(name, sa, ifcp, s) - const char *name; - const struct sockaddr *sa; - struct ifc *ifcp; - int s; +int +ifconfig1(const char *name, + const struct sockaddr *sa, + struct ifc *ifcp, + int s) { struct in6_ifreq ifr; const struct sockaddr_in6 *sin6; @@ -1576,19 +1632,19 @@ ifconfig1(name, sa, ifcp, s) sin6 = (const struct sockaddr_in6 *)sa; if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && !lflag) - return; + return -1; ifr.ifr_addr = *sin6; strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); if (ioctl(s, SIOCGIFNETMASK_IN6, (char *)&ifr) < 0) { - fatal("ioctl: SIOCGIFNETMASK_IN6"); - /*NOTREACHED*/ + syslog(LOG_INFO, "ioctl: SIOCGIFNETMASK_IN6"); + return -1; } plen = sin6mask2len(&ifr.ifr_addr); if ((ifa = ifa_match(ifcp, &sin6->sin6_addr, plen)) != NULL) { /* same interface found */ /* need check if something changed */ /* XXX not yet implemented */ - return; + return -1; } /* * New address is found @@ -1636,6 +1692,38 @@ ifconfig1(name, sa, ifcp, s) ifcp->ifc_index, ifcp->ifc_mtu, ifcp->ifc_metric); } else ifcp->ifc_cflags |= IFC_CHANGED; + + return 0; +} + +void +ifremove(int ifindex) +{ + struct ifc *ifcp; + struct ifc *ifcp_prev = NULL; + struct riprt *rrt; + + for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { + if (ifcp->ifc_index == ifindex) + break; + ifcp_prev = ifcp; + } + if (ifcp == NULL) + return; + + tracet(1, "ifremove: %s is departed.\n", ifcp->ifc_name); + if (ifcp_prev == NULL) { + ifc = ifcp->ifc_next; + } else { + ifcp_prev->ifc_next = ifcp->ifc_next; + } + + for (rrt = riprt; rrt; rrt = rrt->rrt_next) { + if (rrt->rrt_index == ifcp->ifc_index && + rrt->rrt_rflags & RRTF_AGGREGATE) + delroute(&rrt->rrt_info, &rrt->rrt_gw); + } + free(ifcp); } /* @@ -1643,30 +1731,35 @@ ifconfig1(name, sa, ifcp, s) * Update interface information as necesssary. */ void -rtrecv() +rtrecv(void) { char buf[BUFSIZ]; - char *p, *q; + char *p, *q = NULL; struct rt_msghdr *rtm; struct ifa_msghdr *ifam; struct if_msghdr *ifm; + struct if_announcemsghdr *ifan; int len; struct ifc *ifcp, *ic; int iface = 0, rtable = 0; struct sockaddr_in6 *rta[RTAX_MAX]; struct sockaddr_in6 mask; - int i, addrs; + int i, addrs = 0; struct riprt *rrt; if ((len = read(rtsock, buf, sizeof(buf))) < 0) { perror("read from rtsock"); exit(1); } + if (len == 0) + return; +#if 0 if (len < sizeof(*rtm)) { trace(1, "short read from rtsock: %d (should be > %lu)\n", len, (u_long)sizeof(*rtm)); return; } +#endif if (dflag >= 2) { fprintf(stderr, "rtmsg:\n"); for (i = 0; i < len; i++) { @@ -1677,6 +1770,9 @@ rtrecv() } for (p = buf; p - buf < len; p += ((struct rt_msghdr *)p)->rtm_msglen) { + if (((struct rt_msghdr *)p)->rtm_version != RTM_VERSION) + continue; + /* safety against bogus message */ if (((struct rt_msghdr *)p)->rtm_msglen <= 0) { trace(1, "bogus rtmsg: length=%d\n", @@ -1698,6 +1794,18 @@ rtrecv() addrs = ifm->ifm_addrs; q = (char *)(ifm + 1); break; + case RTM_IFANNOUNCE: + ifan = (struct if_announcemsghdr *)p; + switch (ifan->ifan_what) { + case IFAN_ARRIVAL: + iface++; + break; + case IFAN_DEPARTURE: + ifremove(ifan->ifan_index); + iface++; + break; + } + break; default: rtm = (struct rt_msghdr *)p; addrs = rtm->rtm_addrs; @@ -1874,10 +1982,9 @@ rtrecv() * remove specified route from the internal routing table. */ int -rt_del(sdst, sgw, smask) - const struct sockaddr_in6 *sdst; - const struct sockaddr_in6 *sgw; - const struct sockaddr_in6 *smask; +rt_del(const struct sockaddr_in6 *sdst, + const struct sockaddr_in6 *sgw, + const struct sockaddr_in6 *smask) { const struct in6_addr *dst = NULL; const struct in6_addr *gw = NULL; @@ -1973,10 +2080,9 @@ rt_del(sdst, sgw, smask) * remove specified address from internal interface/routing table. */ int -rt_deladdr(ifcp, sifa, smask) - struct ifc *ifcp; - const struct sockaddr_in6 *sifa; - const struct sockaddr_in6 *smask; +rt_deladdr(struct ifc *ifcp, + const struct sockaddr_in6 *sifa, + const struct sockaddr_in6 *smask) { const struct in6_addr *addr = NULL; int prefix; @@ -2085,9 +2191,7 @@ rt_deladdr(ifcp, sifa, smask) * list. */ int -ifrt(ifcp, again) - struct ifc *ifcp; - int again; +ifrt(struct ifc *ifcp, int again) { struct ifac *ifa; struct riprt *rrt = NULL, *search_rrt, *prev_rrt, *loop_rrt; @@ -2202,9 +2306,7 @@ ifrt(ifcp, again) * since BSD kernels do not look at prefix length on p2p interfaces. */ void -ifrt_p2p(ifcp, again) - struct ifc *ifcp; - int again; +ifrt_p2p(struct ifc *ifcp, int again) { struct ifac *ifa; struct riprt *rrt, *orrt, *prevrrt; @@ -2372,8 +2474,7 @@ ifrt_p2p(ifcp, again) } int -getifmtu(ifindex) - int ifindex; +getifmtu(int ifindex) { int mib[6]; char *buf; @@ -2410,8 +2511,7 @@ getifmtu(ifindex) } const char * -rttypes(rtm) - struct rt_msghdr *rtm; +rttypes(struct rt_msghdr *rtm) { #define RTTYPE(s, f) \ do { \ @@ -2454,8 +2554,7 @@ do { \ } const char * -rtflags(rtm) - struct rt_msghdr *rtm; +rtflags(struct rt_msghdr *rtm) { static char buf[BUFSIZ]; @@ -2524,8 +2623,7 @@ do { \ } const char * -ifflags(flags) - int flags; +ifflags(int flags) { static char buf[BUFSIZ]; @@ -2564,8 +2662,7 @@ do { \ } void -krtread(again) - int again; +krtread(int again) { int mib[6]; size_t msize; @@ -2583,6 +2680,8 @@ krtread(again) mib[4] = NET_RT_DUMP; /* Dump the kernel routing table */ mib[5] = 0; /* No flags */ do { + if (retry) + sleep(1); retry++; errmsg = NULL; if (buf) @@ -2599,7 +2698,7 @@ krtread(again) errmsg = "sysctl NET_RT_DUMP"; continue; } - } while (retry < 5 && errmsg != NULL); + } while (retry < RT_DUMP_MAXRETRY && errmsg != NULL); if (errmsg) { fatal("%s (with %d retries, msize=%lu)", errmsg, retry, (u_long)msize); @@ -2616,16 +2715,14 @@ krtread(again) } void -rt_entry(rtm, again) - struct rt_msghdr *rtm; - int again; +rt_entry(struct rt_msghdr *rtm, int again) { struct sockaddr_in6 *sin6_dst, *sin6_gw, *sin6_mask; struct sockaddr_in6 *sin6_genmask, *sin6_ifp; char *rtmp, *ifname = NULL; struct riprt *rrt, *orrt; struct netinfo6 *np; - int s; + int ifindex; sin6_dst = sin6_gw = sin6_mask = sin6_genmask = sin6_ifp = 0; if ((rtm->rtm_flags & RTF_UP) == 0 || rtm->rtm_flags & @@ -2641,6 +2738,9 @@ rt_entry(rtm, again) if (rtm->rtm_flags & RTF_CLONED) return; #endif + /* XXX: Ignore connected routes. */ + if (!(rtm->rtm_flags & (RTF_GATEWAY|RTF_HOST|RTF_STATIC))) + return; /* * do not look at dynamic routes. * netbsd/openbsd cloned routes have UGHD. @@ -2690,6 +2790,8 @@ rt_entry(rtm, again) rrt->rrt_t = time(NULL); if (aflag == 0 && (rtm->rtm_flags & RTF_STATIC)) rrt->rrt_t = 0; /* Don't age static routes */ + if (rtm->rtm_flags & Pflag) + rrt->rrt_t = 0; /* Don't age PROTO[123] routes */ if ((rtm->rtm_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) rrt->rrt_t = 0; /* Don't age non-gateway host routes */ np->rip6_tag = 0; @@ -2735,16 +2837,16 @@ rt_entry(rtm, again) trace(1, " gw %s", inet6_n2p(&rrt->rrt_gw)); /* Interface */ - s = rtm->rtm_index; - if (s < nindex2ifc && index2ifc[s]) - ifname = index2ifc[s]->ifc_name; + ifindex = rtm->rtm_index; + if ((unsigned int)ifindex < nindex2ifc && index2ifc[ifindex]) + ifname = index2ifc[ifindex]->ifc_name; else { trace(1, " not configured\n"); free(rrt); return; } - trace(1, " if %s sock %d", ifname, s); - rrt->rrt_index = s; + trace(1, " if %s sock %d", ifname, ifindex); + rrt->rrt_index = ifindex; trace(1, "\n"); @@ -2775,10 +2877,9 @@ rt_entry(rtm, again) } int -addroute(rrt, gw, ifcp) - struct riprt *rrt; - const struct in6_addr *gw; - struct ifc *ifcp; +addroute(struct riprt *rrt, + const struct in6_addr *gw, + struct ifc *ifcp) { struct netinfo6 *np; u_char buf[BUFSIZ], buf1[BUFSIZ], buf2[BUFSIZ]; @@ -2806,6 +2907,7 @@ addroute(rrt, gw, ifcp) rtm->rtm_seq = ++seq; rtm->rtm_pid = pid; rtm->rtm_flags = rrt->rrt_flags; + rtm->rtm_flags |= Qflag; rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; rtm->rtm_rmx.rmx_hopcount = np->rip6_metric - 1; rtm->rtm_inits = RTV_HOPCOUNT; @@ -2848,9 +2950,7 @@ addroute(rrt, gw, ifcp) } int -delroute(np, gw) - struct netinfo6 *np; - struct in6_addr *gw; +delroute(struct netinfo6 *np, struct in6_addr *gw) { u_char buf[BUFSIZ], buf2[BUFSIZ]; struct rt_msghdr *rtm; @@ -2873,6 +2973,7 @@ delroute(np, gw) rtm->rtm_seq = ++seq; rtm->rtm_pid = pid; rtm->rtm_flags = RTF_UP | RTF_GATEWAY; + rtm->rtm_flags |= Qflag; if (np->rip6_plen == sizeof(struct in6_addr) * 8) rtm->rtm_flags |= RTF_HOST; rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; @@ -2915,9 +3016,7 @@ delroute(np, gw) } struct in6_addr * -getroute(np, gw) - struct netinfo6 *np; - struct in6_addr *gw; +getroute(struct netinfo6 *np, struct in6_addr *gw) { u_char buf[BUFSIZ]; int myseq; @@ -2964,8 +3063,7 @@ getroute(np, gw) } const char * -inet6_n2p(p) - const struct in6_addr *p; +inet6_n2p(const struct in6_addr *p) { static char buf[BUFSIZ]; @@ -2973,8 +3071,7 @@ inet6_n2p(p) } void -ifrtdump(sig) - int sig; +ifrtdump(int sig) { ifdump(sig); @@ -2982,8 +3079,7 @@ ifrtdump(sig) } void -ifdump(sig) - int sig; +ifdump(int sig) { struct ifc *ifcp; FILE *dump; @@ -3003,10 +3099,11 @@ ifdump(sig) if (i == 0) { if ((ifcp->ifc_flags & IFF_UP) == 0) continue; - if (iff_find(ifcp, 'N') != NULL) + if (iff_find(ifcp, IFIL_TYPE_N) != NULL) continue; } else { - if (ifcp->ifc_flags & IFF_UP) + if ((ifcp->ifc_flags & IFF_UP) && + iff_find(ifcp, IFIL_TYPE_N) == NULL) continue; } ifdump0(dump, ifcp); @@ -3018,9 +3115,7 @@ ifdump(sig) } void -ifdump0(dump, ifcp) - FILE *dump; - const struct ifc *ifcp; +ifdump0(FILE *dump, const struct ifc *ifcp) { struct ifac *ifa; struct iff *iffp; @@ -3045,20 +3140,22 @@ ifdump0(dump, ifcp) ifa->ifa_plen); } } - if (ifcp->ifc_filter) { + if (1) { fprintf(dump, "\tFilter:"); - for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { + for (iffp = iff_head; iffp; iffp = iffp->iff_next) { + if (fnmatch(iffp->iff_name, ifcp->ifc_name, 0) != 0) + continue; addr = 0; switch (iffp->iff_type) { - case 'A': + case IFIL_TYPE_A: ft = "Aggregate"; addr++; break; - case 'N': + case IFIL_TYPE_N: ft = "No-use"; break; - case 'O': + case IFIL_TYPE_O: ft = "Advertise-only"; addr++; break; - case 'T': + case IFIL_TYPE_T: ft = "Default-only"; break; - case 'L': + case IFIL_TYPE_L: ft = "Listen-only"; addr++; break; default: snprintf(buf, sizeof(buf), "Unknown-%c", iffp->iff_type); @@ -3077,8 +3174,7 @@ ifdump0(dump, ifcp) } void -rtdump(sig) - int sig; +rtdump(int sig) { struct riprt *rrt; char buf[BUFSIZ]; @@ -3127,12 +3223,12 @@ rtdump(sig) * -O 5f09:c400::/32,ef0,ef1 (only when match) */ void -filterconfig() +filterconfig(void) { int i; char *p, *ap, *iflp, *ifname, *ep; - struct iff ftmp, *iff_obj; - struct ifc *ifcp; + struct iff ftmp, *iffp; + struct ifc ctmp, *ifcp; struct riprt *rrt; #if 0 struct in6_addr gw; @@ -3143,7 +3239,8 @@ filterconfig() ap = filter[i]; iflp = NULL; ifcp = NULL; - if (filtertype[i] == 'N' || filtertype[i] == 'T') { + memset(&ftmp, 0, sizeof(ftmp)); + if (filtertype[i] == IFIL_TYPE_N || filtertype[i] == IFIL_TYPE_T) { iflp = ap; goto ifonly; } @@ -3181,21 +3278,19 @@ ifonly: ifname = iflp; if ((iflp = strchr(iflp, ',')) != NULL) *iflp++ = '\0'; - ifcp = ifc_find(ifname); - if (ifcp == NULL) { - fatal("no interface %s exists", ifname); - /*NOTREACHED*/ - } - iff_obj = (struct iff *)malloc(sizeof(struct iff)); - if (iff_obj == NULL) { - fatal("malloc of iff_obj"); + strlcpy(ctmp.ifc_name, ifname, sizeof(ctmp.ifc_name)); + strlcpy(ftmp.iff_name, ifname, sizeof(ftmp.iff_name)); +#if 0 + syslog(LOG_INFO, "Add filter: type %d, ifname %s.", ftmp.iff_type, ifname); +#endif + iffp = malloc(sizeof(struct iff)); + if (iffp == NULL) { + fatal("malloc of iff"); /*NOTREACHED*/ } - memcpy((void *)iff_obj, (void *)&ftmp, - sizeof(struct iff)); - /* link it to the interface filter */ - iff_obj->iff_next = ifcp->ifc_filter; - ifcp->ifc_filter = iff_obj; + ftmp.iff_next = iff_head; + iff_head = iffp; + memcpy(iffp, &ftmp, sizeof(struct iff)); } /* @@ -3243,7 +3338,7 @@ ifonly: riprt = rrt; trace(1, "Aggregate: %s/%d for %s\n", inet6_n2p(&ftmp.iff_addr), ftmp.iff_plen, - ifcp->ifc_name); + ftmp.iff_name); /* Add this route to the kernel */ if (nflag) /* do not modify kernel routing table */ continue; @@ -3258,10 +3353,9 @@ ifonly: * with the address and prefix length specified in the arguments. */ struct ifac * -ifa_match(ifcp, ia, plen) - const struct ifc *ifcp; - const struct in6_addr *ia; - int plen; +ifa_match(const struct ifc *ifcp, + const struct in6_addr *ia, + int plen) { struct ifac *ifa; @@ -3279,9 +3373,7 @@ ifa_match(ifcp, ia, plen) * Note: This is not a rtalloc(). Therefore exact match is necessary. */ struct riprt * -rtsearch(np, prev_rrt) - struct netinfo6 *np; - struct riprt **prev_rrt; +rtsearch(struct netinfo6 *np, struct riprt **prev_rrt) { struct riprt *rrt; @@ -3301,8 +3393,7 @@ rtsearch(np, prev_rrt) } int -sin6mask2len(sin6) - const struct sockaddr_in6 *sin6; +sin6mask2len(const struct sockaddr_in6 *sin6) { return mask2len(&sin6->sin6_addr, @@ -3310,9 +3401,7 @@ sin6mask2len(sin6) } int -mask2len(addr, lenlim) - const struct in6_addr *addr; - int lenlim; +mask2len(const struct in6_addr *addr, int lenlim) { int i = 0, j; const u_char *p = (const u_char *)addr; @@ -3339,8 +3428,7 @@ mask2len(addr, lenlim) } void -applymask(addr, mask) - struct in6_addr *addr, *mask; +applymask(struct in6_addr *addr, struct in6_addr *mask) { int i; u_long *p, *q; @@ -3355,9 +3443,7 @@ static const u_char plent[8] = { }; void -applyplen(ia, plen) - struct in6_addr *ia; - int plen; +applyplen(struct in6_addr *ia, int plen) { u_char *p; int i; @@ -3377,8 +3463,7 @@ static const int pl2m[9] = { }; struct in6_addr * -plen2mask(n) - int n; +plen2mask(int n) { static struct in6_addr ia; u_char *p; @@ -3398,8 +3483,7 @@ plen2mask(n) } char * -allocopy(p) - char *p; +allocopy(char *p) { int len = strlen(p) + 1; char *q = (char *)malloc(len); @@ -3414,7 +3498,7 @@ allocopy(p) } char * -hms() +hms(void) { static char buf[BUFSIZ]; time_t t; @@ -3433,8 +3517,7 @@ hms() #define RIPRANDDEV 1.0 /* 30 +- 15, max - min = 30 */ int -ripinterval(timer) - int timer; +ripinterval(int timer) { double r = rand(); @@ -3444,7 +3527,7 @@ ripinterval(timer) } time_t -ripsuptrig() +ripsuptrig(void) { time_t t; @@ -3554,7 +3637,7 @@ trace(level, fmt, va_alist) } unsigned int -if_maxindex() +if_maxindex(void) { struct if_nameindex *p, *p0; unsigned int max = 0; @@ -3569,8 +3652,7 @@ if_maxindex() } struct ifc * -ifc_find(name) - char *name; +ifc_find(char *name) { struct ifc *ifcp; @@ -3582,23 +3664,23 @@ ifc_find(name) } struct iff * -iff_find(ifcp, type) - struct ifc *ifcp; - int type; +iff_find(struct ifc *ifcp, int type) { struct iff *iffp; - for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { - if (iffp->iff_type == type) - return iffp; + for (iffp = iff_head; iffp; iffp = iffp->iff_next) { + if (fnmatch(iffp->iff_name, ifcp->ifc_name, 0) == 0) { + if (type == IFIL_TYPE_ANY || + type == iffp->iff_type) { + return iffp; + } + } } return NULL; } void -setindex2ifc(idx, ifcp) - int idx; - struct ifc *ifcp; +setindex2ifc(int idx, struct ifc *ifcp) { int n, nsize; struct ifc **p; diff --git a/usr.sbin/rpc.yppasswdd/Makefile b/usr.sbin/rpc.yppasswdd/Makefile index b6a0a8c..2f01e28 100644 --- a/usr.sbin/rpc.yppasswdd/Makefile +++ b/usr.sbin/rpc.yppasswdd/Makefile @@ -5,12 +5,20 @@ RPCDIR= ${DESTDIR}/usr/include/rpcsvc .PATH: ${.CURDIR}/../../usr.sbin/ypserv ${.CURDIR}/../../usr.bin/chpass \ ${.CURDIR}/../../libexec/ypxfr ${RPCDIR} +.include <bsd.own.mk> + PROG= rpc.yppasswdd SCRIPTS=yppwupdate SCRIPTSDIR= /usr/libexec MAN= rpc.yppasswdd.8 SRCS= util.c yp_access.c yp_dblookup.c yp_dbwrite.c \ yp_error.c yppasswdd_main.c yppasswdd_server.c ypxfr_misc.c ${GENSRCS} +.if ${MK_INET_SUPPORT} != "no" +SRCS+= yp_access_inet.c +.endif +.if ${MK_INET6_SUPPORT} != "no" +SRCS+= yp_access_inet6.c +.endif GENSRCS=yp.h yp_clnt.c yppasswd.h yppasswd_private.h yppasswd_private_svc.c \ yppasswd_private_xdr.c yppasswd_svc.c diff --git a/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h b/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h index db15be2..901b75f 100644 --- a/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h +++ b/usr.sbin/rpc.yppasswdd/yppasswdd_extern.h @@ -46,8 +46,6 @@ #define MAP_UPDATE "yppwupdate" #define MAP_UPDATE_PATH YPLIBDIR "yppwupdate" -extern char *yp_dir; -extern char *progname; extern void do_master(void); extern void yppasswdprog_1(struct svc_req *, register SVCXPRT *); extern void master_yppasswdprog_1(struct svc_req *, register SVCXPRT *); diff --git a/usr.sbin/rpc.yppasswdd/yppasswdd_main.c b/usr.sbin/rpc.yppasswdd/yppasswdd_main.c index 8c89691..2311384 100644 --- a/usr.sbin/rpc.yppasswdd/yppasswdd_main.c +++ b/usr.sbin/rpc.yppasswdd/yppasswdd_main.c @@ -86,10 +86,8 @@ static int _rpcfdtype; static char _localhost[] = "localhost"; static char _passwd_byname[] = "passwd.byname"; extern int _rpcsvcstate; /* Set when a request is serviced */ -static char _progname[] = "rpc.yppasswdd"; -char *progname = _progname; -static char _yp_dir[] = _PATH_YP; -char *yp_dir = _yp_dir; +const char *progname = "rpc.yppasswdd"; +const char *yp_dir = _PATH_YP; static char _passfile_default[] = _PATH_YP "master.passwd"; char *passfile_default = _passfile_default; char *passfile; diff --git a/usr.sbin/rpc.ypupdated/ypupdated_main.c b/usr.sbin/rpc.ypupdated/ypupdated_main.c index c13af7d..f02ad24 100644 --- a/usr.sbin/rpc.ypupdated/ypupdated_main.c +++ b/usr.sbin/rpc.ypupdated/ypupdated_main.c @@ -75,8 +75,8 @@ static int _rpcfdtype; extern int _rpcsvcstate; /* Set when a request is serviced */ -char *progname = "rpc.ypupdated"; -char *yp_dir = "/var/yp/"; +const char *progname = "rpc.ypupdated"; +const char *yp_dir = _PATH_YP; static void _msgout(char* msg) diff --git a/usr.sbin/rpc.ypxfrd/Makefile b/usr.sbin/rpc.ypxfrd/Makefile index ee9e242..3b5478c 100644 --- a/usr.sbin/rpc.ypxfrd/Makefile +++ b/usr.sbin/rpc.ypxfrd/Makefile @@ -1,13 +1,21 @@ # $FreeBSD$ -.PATH: ${.CURDIR}/../../usr.sbin/ypserv +.PATH: ${.CURDIR}/../ypserv + +.include <bsd.own.mk> PROG= rpc.ypxfrd MAN= rpc.ypxfrd.8 SRCS= ypxfrd_svc.c ypxfrd.h ypxfrd_server.c yp_error.c \ yp_access.c ypxfrd_main.c - -CFLAGS+= -I. -DXFRBLOCKSIZE=65535 +.if ${MK_INET_SUPPORT} != "no" +SRCS+= yp_access_inet.c +.endif +.if ${MK_INET6_SUPPORT} != "no" +SRCS+= yp_access_inet6.c +.endif + +CFLAGS+= -I. -I${.CURDIR}/../ypserv -DXFRBLOCKSIZE=65535 WARNS?= 2 diff --git a/usr.sbin/rpc.ypxfrd/ypxfrd_extern.h b/usr.sbin/rpc.ypxfrd/ypxfrd_extern.h index 5aba934..ba4259c 100644 --- a/usr.sbin/rpc.ypxfrd/ypxfrd_extern.h +++ b/usr.sbin/rpc.ypxfrd/ypxfrd_extern.h @@ -42,9 +42,4 @@ extern int forked; extern int children; -extern void load_securenets(void); -extern void yp_error(const char *, ...); -extern int yp_access(const char *, const struct svc_req *); -extern int yp_validdomain(const char *); -extern char *yp_dir; extern void ypxfrd_freebsd_prog_1(struct svc_req *, register SVCXPRT *); diff --git a/usr.sbin/rpc.ypxfrd/ypxfrd_main.c b/usr.sbin/rpc.ypxfrd/ypxfrd_main.c index 8fa3e22..8970497 100644 --- a/usr.sbin/rpc.ypxfrd/ypxfrd_main.c +++ b/usr.sbin/rpc.ypxfrd/ypxfrd_main.c @@ -52,10 +52,12 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <netinet/in.h> #include <syslog.h> -#include "ypxfrd_extern.h" #include <sys/wait.h> #include <errno.h> +#include "ypxfrd_extern.h" +#include "yp_extern.h" + #ifndef SIG_PF #define SIG_PF void(*)(int) #endif @@ -76,8 +78,8 @@ static int _rpcfdtype; extern int _rpcsvcstate; /* Set when a request is serviced */ -char *progname = "rpc.ypxfrd"; -char *yp_dir = "/var/yp/"; +const char *progname = "rpc.ypxfrd"; +const char *yp_dir = _PATH_YP; static void _msgout(char *msg) diff --git a/usr.sbin/rpc.ypxfrd/ypxfrd_server.c b/usr.sbin/rpc.ypxfrd/ypxfrd_server.c index 5f60712..401711e 100644 --- a/usr.sbin/rpc.ypxfrd/ypxfrd_server.c +++ b/usr.sbin/rpc.ypxfrd/ypxfrd_server.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include <sys/fcntl.h> #include <machine/endian.h> #include "ypxfrd_extern.h" +#include "yp_extern.h" int forked = 0; int children = 0; diff --git a/usr.sbin/rtadvd/Makefile b/usr.sbin/rtadvd/Makefile index 9dbfc99..e34aa3c 100644 --- a/usr.sbin/rtadvd/Makefile +++ b/usr.sbin/rtadvd/Makefile @@ -23,6 +23,6 @@ LDADD= -lutil CFLAGS+= -DHAVE_ARC4RANDOM -DHAVE_POLL_H -DROUTEINFO -WARNS?= 1 +WARNS?= 6 .include <bsd.prog.mk> diff --git a/usr.sbin/rtsold/Makefile b/usr.sbin/rtsold/Makefile index efc322c..9e2b480 100644 --- a/usr.sbin/rtsold/Makefile +++ b/usr.sbin/rtsold/Makefile @@ -19,7 +19,7 @@ MAN= rtsold.8 MLINKS= rtsold.8 rtsol.8 SRCS= rtsold.c rtsol.c if.c probe.c dump.c rtsock.c -WARNS?= 3 +WARNS?= 6 CFLAGS+= -DHAVE_ARC4RANDOM -DHAVE_POLL_H DPADD= ${LIBKVM} LDADD= -lkvm diff --git a/usr.sbin/rtsold/rtsold.c b/usr.sbin/rtsold/rtsold.c index 94046a1..73c027f 100644 --- a/usr.sbin/rtsold/rtsold.c +++ b/usr.sbin/rtsold/rtsold.c @@ -189,9 +189,9 @@ main(int argc, char **argv) if (!fflag) { char *ident; - ident = strrchr(argv0, '/'); + ident = strrchr(argv[0], '/'); if (!ident) - ident = argv0; + ident = argv[0]; else ident++; openlog(ident, LOG_NDELAY|LOG_PID, LOG_DAEMON); diff --git a/usr.sbin/yp_mkdb/yp_mkdb.c b/usr.sbin/yp_mkdb/yp_mkdb.c index 6c3014b..fdbb466 100644 --- a/usr.sbin/yp_mkdb/yp_mkdb.c +++ b/usr.sbin/yp_mkdb/yp_mkdb.c @@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$"); #include "yp_extern.h" #include "ypxfr_extern.h" -char *yp_dir = ""; /* No particular default needed. */ +const char *yp_dir = _PATH_YP; int _rpcpmstart = 0; int debug = 1; diff --git a/usr.sbin/yppush/Makefile b/usr.sbin/yppush/Makefile index 887a80b..4ca3635 100644 --- a/usr.sbin/yppush/Makefile +++ b/usr.sbin/yppush/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ RPCDIR= ${.CURDIR}/../../include/rpcsvc -.PATH: ${RPCDIR} ${.CURDIR}/../../usr.sbin/ypserv \ +.PATH: ${RPCDIR} ${.CURDIR}/../ypserv \ ${.CURDIR}/../../libexec/ypxfr PROG= yppush diff --git a/usr.sbin/yppush/yppush_main.c b/usr.sbin/yppush/yppush_main.c index df1dbe4..3749d3e 100644 --- a/usr.sbin/yppush/yppush_main.c +++ b/usr.sbin/yppush/yppush_main.c @@ -53,10 +53,10 @@ __FBSDID("$FreeBSD$"); #include "ypxfr_extern.h" #include "yppush_extern.h" -char *progname = "yppush"; int debug = 1; int _rpcpmstart = 0; -char *yp_dir = _PATH_YP; +const char *progname = "yppush"; +const char *yp_dir = _PATH_YP; char *yppush_mapname = NULL; /* Map to transfer. */ char *yppush_domain = NULL; /* Domain in which map resides. */ diff --git a/usr.sbin/ypserv/Makefile b/usr.sbin/ypserv/Makefile index 73a6195..d3dd1fa 100644 --- a/usr.sbin/ypserv/Makefile +++ b/usr.sbin/ypserv/Makefile @@ -3,14 +3,22 @@ RPCDIR= ${.CURDIR}/../../include/rpcsvc .PATH: ${RPCDIR} +.include <bsd.own.mk> + PROG= ypserv MAN= ypserv.8 ypinit.8 SRCS= yp_svc.c yp_server.c yp_dblookup.c yp_dnslookup.c \ ypxfr_clnt.c yp.h yp_main.c yp_error.c yp_access.c yp_svc_udp.c +.if ${MK_INET_SUPPORT} != "no" +SRCS+= yp_access_inet.c +.endif +.if ${MK_INET6_SUPPORT} != "no" +SRCS+= yp_access_inet6.c +.endif CFLAGS+= -DDB_CACHE -DTCP_WRAPPER -I. -WARNS?= 0 +WARNS?= 6 DPADD= ${LIBWRAP} LDADD= -lwrap diff --git a/usr.sbin/ypserv/yp_access.c b/usr.sbin/ypserv/yp_access.c index 66d056b..5d754e0 100644 --- a/usr.sbin/ypserv/yp_access.c +++ b/usr.sbin/ypserv/yp_access.c @@ -34,31 +34,36 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include <stdlib.h> +#include <sys/fcntl.h> +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> #include <rpc/rpc.h> #include <rpcsvc/yp.h> #include <rpcsvc/yppasswd.h> #include <rpcsvc/ypxfrd.h> -#include <sys/types.h> -#include <limits.h> -#include <db.h> -#include <sys/socket.h> -#include <netinet/in.h> #include <arpa/inet.h> -#include <sys/stat.h> -#include <sys/fcntl.h> -#include <paths.h> +#include <netinet/in.h> +#include <db.h> #include <errno.h> -#include <sys/param.h> +#include <limits.h> +#include <netdb.h> +#include <paths.h> +#include <stdlib.h> + #include "yp_extern.h" #ifdef TCP_WRAPPER #include "tcpd.h" +extern int hosts_ctl(const char *, const char *, const char *, const char *); #endif -extern int debug; +char securenets_path[MAXPATHLEN]; +enum yp_snf_format securenets_format = YP_SNF_NATIVE; - /* NIS v1 */ const char *yp_procs[] = { + /* NIS v1 */ "ypoldproc_null", "ypoldproc_domain", "ypoldproc_domain_nonack", @@ -87,89 +92,431 @@ const char *yp_procs[] = { "ypproc_maplist" }; +static SLIST_HEAD(, securenet) securenets = + SLIST_HEAD_INITIALIZER(securenets); struct securenet { - struct in_addr net; - struct in_addr mask; - struct securenet *next; + struct sockaddr_storage sn_addr; + struct sockaddr_storage sn_mask; + SLIST_ENTRY(securenet) sn_next; }; -struct securenet *securenets; +static int +mask2prefixlen(const struct sockaddr *sap, int *prefixlen) +{ + switch (sap->sa_family) { +#ifdef AF_INET + case AF_INET: + return (yp_mask2prefixlen_in(sap, prefixlen)); + break; +#endif +#ifdef AF_INET6 + case AF_INET6: + return (yp_mask2prefixlen_in6(sap, prefixlen)); + break; +#endif + default: + break; + } + return (-1); +} -#define LINEBUFSZ 1024 +static int +prefixlen2mask(struct sockaddr *sap, const int *prefixlen) +{ + switch (sap->sa_family) { +#ifdef AF_INET + case AF_INET: + return (yp_prefixlen2mask_in(sap, prefixlen)); + break; +#endif +#ifdef AF_INET6 + case AF_INET6: + return (yp_prefixlen2mask_in6(sap, prefixlen)); + break; +#endif + default: + break; + } + return (-1); +} + +void +yp_debug_sa(const struct sockaddr *sap) +{ + int error; + int plen; + char host[NI_MAXHOST + 1]; + char serv[NI_MAXSERV + 1]; + + error = getnameinfo(sap, sap->sa_len, host, sizeof(host), serv, + sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV); + if (error) + yp_error("sockaddr: %s", gai_strerror(error)); + mask2prefixlen(sap, &plen); + yp_error("sockaddr: %d:[%s]:%s(/%d)", + sap->sa_family, host, serv, plen); +} + +void +show_securenets(void) +{ + struct securenet *snp; + struct sockaddr *sap; + int i = 0; + + yp_error("--- securenets dump start ---"); + SLIST_FOREACH(snp, &securenets, sn_next) { + i++; + yp_error("entry %d:", i); + sap = (struct sockaddr *)&(snp->sn_addr); + yp_debug_sa(sap); + sap = (struct sockaddr *)&(snp->sn_mask); + yp_debug_sa(sap); + } + yp_error("--- securenets dump end ---"); +} /* * Read /var/yp/securenets file and initialize the securenets * list. If the file doesn't exist, we set up a dummy entry that * allows all hosts to connect. */ -void +#define YP_ACL_HOSTMASK_INET "255.255.255.255" +#define YP_ACL_HOSTMASK_INET6 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" +int load_securenets(void) { FILE *fp; - char path[MAXPATHLEN + 2]; - char linebuf[1024 + 2]; - struct securenet *tmp; - - /* - * If securenets is not NULL, we are being called to reload - * the list; free the existing list before re-reading the - * securenets file. - */ - while (securenets) { - tmp = securenets->next; - free(securenets); - securenets = tmp; + char linebuf[BUFSIZ + 2]; + struct securenet *snp; + struct sockaddr *sap; + int error = 0; + int line; + struct addrinfo hints, *res, *res0; + + if (SLIST_EMPTY(&securenets)) + SLIST_INIT(&securenets); + else { + /* + * If securenets is not NULL, we are being called to reload + * the list; free the existing list before re-reading the + * securenets file. + */ + while (!SLIST_EMPTY(&securenets)) { + snp = SLIST_FIRST(&securenets); + SLIST_REMOVE_HEAD(&securenets, sn_next); + free(snp); + } } - - snprintf(path, MAXPATHLEN, "%s/securenets", yp_dir); - - if ((fp = fopen(path, "r")) == NULL) { + if (debug) + yp_error("load_securenets(): loading %s", securenets_path); + if ((fp = fopen(securenets_path, "r")) == NULL) { if (errno == ENOENT) { - securenets = (struct securenet *)malloc(sizeof(struct securenet)); - securenets->net.s_addr = INADDR_ANY; - securenets->mask.s_addr = INADDR_ANY; - securenets->next = NULL; - return; + /* Create empty access list. */ + if (debug) + yp_error("load_securenets(): ENOENT"); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_PASSIVE; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(NULL, "0", &hints, &res0); + if (error) { + yp_error("getaddrinfo() failed: %s", + gai_strerror(error)); + freeaddrinfo(res0); + return (1); + } + for (res = res0; res; res = res->ai_next) { + snp = malloc(sizeof(*snp)); + if (snp == NULL) { + yp_error("malloc failed: %s", + strerror(errno)); + freeaddrinfo(res0); + return (1); + } + memset(snp, 0, sizeof(*snp)); + memcpy(&snp->sn_addr, res->ai_addr, + sizeof(res->ai_addrlen)); + memcpy(&snp->sn_mask, res->ai_addr, + sizeof(res->ai_addrlen)); + sap = (struct sockaddr *)&(snp->sn_mask); + prefixlen2mask(sap, 0); + SLIST_INSERT_HEAD(&securenets, snp, sn_next); + } + freeaddrinfo(res0); + return (0); } else { - yp_error("fopen(%s) failed: %s", path, strerror(errno)); - exit(1); + yp_error("fopen(%s) failed: %s", securenets_path, + strerror(errno)); + return (1); } } - securenets = NULL; - - while (fgets(linebuf, LINEBUFSZ, fp)) { - char addr1[20], addr2[20]; - + line = 0; + while (fgets(linebuf, sizeof(linebuf), fp)) { + int nitems; + const char *col_host; + const char *col_mask; + char addr1[NI_MAXHOST + 1]; + char addr2[NI_MAXHOST + 1]; + int plen; + sa_family_t family; + char *p; + + line++; + if (debug) + yp_error("load_securenets(): read line %d", line); if ((linebuf[0] == '#') || (strspn(linebuf, " \t\r\n") == strlen(linebuf))) continue; - if (sscanf(linebuf, "%s %s", addr1, addr2) < 2) { - yp_error("badly formatted securenets entry: %s", - linebuf); + nitems = sscanf(linebuf, "%s %s", addr1, addr2); + snp = malloc(sizeof(*snp)); + memset(snp, 0, sizeof(*snp)); + + if (debug) + yp_error("load_securenets(): nitems = %d", nitems); + if (nitems == 2) { + switch (securenets_format) { + case YP_SNF_NATIVE: + /* ex. 127.0.0.1 255.0.0.0 */ + col_host = addr1; + col_mask = addr2; + break; + case YP_SNF_SOLARIS: + /* ex. 255.0.0.0 127.0.0.1 */ + col_host = addr2; + col_mask = addr1; + break; + default: + yp_error("line %d: internal error: %s", + line, linebuf); + continue; + + } + if (debug) { + yp_error("load_securenets(): try mask expr"); + yp_error("load_securenets(): host = [%s]", + col_host); + yp_error("load_securenets(): mask = [%s]", + col_mask); + } + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST; + error = getaddrinfo(col_host, NULL, &hints, &res0); + if (error) { + yp_error("line %d: " + "badly formatted securenets entry: " + "%s: %s", line, linebuf, + gai_strerror(error)); + freeaddrinfo(res0); + free(snp); + continue; + } + memcpy(&snp->sn_addr, res0->ai_addr, res0->ai_addrlen); + family = res0->ai_addr->sa_family; + freeaddrinfo(res0); + + if ((securenets_format == YP_SNF_SOLARIS) && + (strcmp(col_host, "host") == 0)) { + switch (family) { +#ifdef AF_INET + case AF_INET: + col_host = YP_ACL_HOSTMASK_INET; + break; +#endif +#ifdef AF_INET6 + case AF_INET6: + col_host = YP_ACL_HOSTMASK_INET6; + break; +#endif + default: + yp_error("line %d: host keyword for " + "unsupported address family: " + "%s: %s", line, linebuf, + gai_strerror(error)); + continue; + } + } + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST; + error = getaddrinfo(col_mask, NULL, &hints, &res0); + if (error) { + yp_error("line %d: " + "badly formatted securenets entry: " + "%s: %s", line, linebuf, + gai_strerror(error)); + freeaddrinfo(res0); + free(snp); + continue; + } + memcpy(&snp->sn_mask, res0->ai_addr, res0->ai_addrlen); + freeaddrinfo(res0); + } else if (nitems == 1) { + /* ex. 127.0.0.1/8 */ + /* ex. fe80::/10 */ + if (debug) + yp_error("load_securenets(): try CIDR expr"); + p = strrchr(addr1, '/'); + if (p != NULL) { + *p = ' '; + nitems = sscanf(addr1, "%s %d", addr2, &plen); + if (nitems < 2) { + yp_error("line %d: " + "badly formatted securenets entry:" + " %s", line, linebuf); + free(snp); + continue; + } + } else + memcpy(addr2, addr1, sizeof(addr2)); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST; + error = getaddrinfo(addr2, NULL, &hints, &res0); + if (error) { + yp_error("line %d: " + "badly formatted securenets entry: " + "%s: %s", line, linebuf, + gai_strerror(error)); + freeaddrinfo(res0); + free(snp); + continue; + } + if (p == NULL) + switch (res0->ai_addr->sa_family) { +#ifdef AF_INET + case AF_INET: + plen = 32; + break; +#endif +#ifdef AF_INET6 + case AF_INET6: + plen = 128; + break; +#endif + default: + yp_error("line %d: " + "unsupported address family: " + "%s: %s", line, linebuf, + gai_strerror(error)); + continue; + } + if (debug) { + yp_error("load_securenets(): addr2 = [%s]", + addr2); + yp_error("load_securenets(): plen = [%d]", + plen); + } + memcpy(&snp->sn_addr, res0->ai_addr, res0->ai_addrlen); + memcpy(&snp->sn_mask, res0->ai_addr, res0->ai_addrlen); + freeaddrinfo(res0); + + sap = (struct sockaddr *)&(snp->sn_mask); + prefixlen2mask(sap, &plen); + } else { + yp_error("line %d: " + "badly formatted securenets entry: " + "%s", line, linebuf); continue; } - - tmp = (struct securenet *)malloc(sizeof(struct securenet)); - - if (!inet_aton((char *)&addr1, (struct in_addr *)&tmp->net)) { - yp_error("badly formatted securenets entry: %s", addr1); - free(tmp); - continue; + if (debug) { + yp_error("load_securenets(): adding entry"); + yp_debug_sa((struct sockaddr*)&(snp->sn_addr)); + yp_debug_sa((struct sockaddr *)&(snp->sn_mask)); } - - if (!inet_aton((char *)&addr2, (struct in_addr *)&tmp->mask)) { - yp_error("badly formatted securenets entry: %s", addr2); - free(tmp); - continue; - } - - tmp->next = securenets; - securenets = tmp; + SLIST_INSERT_HEAD(&securenets, snp, sn_next); } - fclose(fp); + if (debug) + show_securenets(); + return (0); +} +static int +compare_subnet(struct sockaddr *addr1, + struct sockaddr *addr2, + struct sockaddr *mask) +{ +#ifdef AF_INET + struct sockaddr_in *in_addr1; + struct sockaddr_in *in_addr2; + struct sockaddr_in *in_addrm; +#endif +#ifdef AF_INET6 + struct sockaddr_in6 *in6_addr1; + struct sockaddr_in6 *in6_addr2; + struct sockaddr_in6 *in6_addrm; +#endif + u_char a1[sizeof(struct sockaddr_storage)]; + u_char a2[sizeof(struct sockaddr_storage)]; + u_char m[sizeof(struct sockaddr_storage)]; + ssize_t len; + int i; + int samescope; + + if (addr1->sa_family != addr2->sa_family) + return (1); + + memset(a1, 0, sizeof(a1)); + memset(a1, 0, sizeof(a2)); + memset(m, 0, sizeof(m)); + + switch (addr1->sa_family) { +#ifdef AF_INET + case AF_INET: + in_addr1 = (struct sockaddr_in *)(addr1); + in_addr2 = (struct sockaddr_in *)(addr2); + in_addrm = (struct sockaddr_in *)(mask); + len = sizeof(in_addr1->sin_addr.s_addr); + memcpy(a1, (u_char *)&(in_addr1->sin_addr.s_addr), + sizeof(in_addr1->sin_addr.s_addr)); + memcpy(a2, (u_char *)&(in_addr2->sin_addr.s_addr), + sizeof(in_addr2->sin_addr.s_addr)); + memcpy(m, (u_char *)&(in_addrm->sin_addr.s_addr), + sizeof(in_addrm->sin_addr.s_addr)); + samescope = 1; + break; +#endif +#ifdef AF_INET6 + case AF_INET6: + in6_addr1 = (struct sockaddr_in6 *)(addr1); + in6_addr2 = (struct sockaddr_in6 *)(addr2); + in6_addrm = (struct sockaddr_in6 *)(mask); + len = sizeof(in6_addr1->sin6_addr.s6_addr); + memcpy(a1, (u_char *)in6_addr1->sin6_addr.s6_addr, + sizeof(in6_addr1->sin6_addr.s6_addr)); + memcpy(a2, (u_char *)in6_addr2->sin6_addr.s6_addr, + sizeof(in6_addr2->sin6_addr.s6_addr)); + memcpy(m, (u_char *)in6_addrm->sin6_addr.s6_addr, + sizeof(in6_addrm->sin6_addr.s6_addr)); + samescope = (in6_addr1->sin6_scope_id == + in6_addr2->sin6_scope_id); + break; +#endif + default: + return (1); + } + for (i=0; i < len; i++) { + a1[i] &= m[i]; + a2[i] &= m[i]; + } + if (debug) { + yp_error("compare_subnet(): addr1"); + yp_debug_sa(addr1); + yp_error("compare_subnet(): addr2"); + yp_debug_sa(addr2); + yp_error("compare_subnet(): mask"); + yp_debug_sa(mask); + } + if (!samescope) + return (1); + return (memcmp(a1, a2, len)); } /* @@ -211,15 +558,21 @@ int yp_access(const char *map, const struct svc_req *rqstp) #endif { - struct sockaddr_in *rqhost; int status_securenets = 0; + int error; #ifdef TCP_WRAPPER int status_tcpwrap; #endif - static unsigned long oldaddr = 0; - struct securenet *tmp; + static struct sockaddr oldaddr; + struct securenet *snp; + struct sockaddr *sap; + struct netbuf *rqhost; const char *yp_procedure = NULL; char procbuf[50]; + char host[NI_MAXHOST]; + char serv[NI_MAXSERV]; + + memset(&oldaddr, 0, sizeof(oldaddr)); if (rqstp->rq_prog != YPPASSWDPROG && rqstp->rq_prog != YPPROG) { snprintf(procbuf, sizeof(procbuf), "#%lu/#%lu", @@ -232,12 +585,18 @@ yp_access(const char *map, const struct svc_req *rqstp) yp_procs[rqstp->rq_proc + (12 * (rqstp->rq_vers - 1))]; } - rqhost = svc_getcaller(rqstp->rq_xprt); - + rqhost = svc_getrpccaller(rqstp->rq_xprt); + sap = (struct sockaddr *)(rqhost->buf); + error = getnameinfo(sap, sap->sa_len, + host, sizeof(host), serv, sizeof(serv), + NI_NUMERICHOST | NI_NUMERICSERV); + if (error) { + yp_error("yp_access: getnameinfo(): %s", gai_strerror(error)); + return (1); + } if (debug) { - yp_error("procedure %s called from %s:%d", yp_procedure, - inet_ntoa(rqhost->sin_addr), - ntohs(rqhost->sin_port)); + yp_error("procedure %s called from %s:%s", yp_procedure, + host, serv); if (map != NULL) yp_error("client is referencing map \"%s\".", map); } @@ -245,14 +604,13 @@ yp_access(const char *map, const struct svc_req *rqstp) /* Check the map name if one was supplied. */ if (map != NULL) { if (strchr(map, '/')) { - yp_error("embedded slash in map name \"%s\" -- \ -possible spoof attempt from %s:%d", - map, inet_ntoa(rqhost->sin_addr), - ntohs(rqhost->sin_port)); - return(1); + yp_error("embedded slash in map name \"%s\" " + "-- possible spoof attempt from %s:%s", + map, host, serv); + return (1); } #ifdef DB_CACHE - if ((yp_testflag((char *)map, (char *)domain, YP_SECURE) || + if ((yp_testflag((const char *)map, (const char *)domain, YP_SECURE) || #else if ((strstr(map, "master.passwd.") || strstr(map, "shadow.") || #endif @@ -260,27 +618,30 @@ possible spoof attempt from %s:%d", rqstp->rq_proc == YPPROC_XFR) || (rqstp->rq_prog == YPXFRD_FREEBSD_PROG && rqstp->rq_proc == YPXFRD_GETMAP)) && - ntohs(rqhost->sin_port) >= IPPORT_RESERVED) { - yp_error("access to %s denied -- client %s:%d \ -not privileged", map, inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); - return(1); + atoi(serv) >= IPPORT_RESERVED) { + yp_error("access to %s denied -- client %s:%s" + " not privileged", map, host, serv); + return (1); } } #ifdef TCP_WRAPPER - status_tcpwrap = hosts_ctl("ypserv", STRING_UNKNOWN, - inet_ntoa(rqhost->sin_addr), ""); + status_tcpwrap = hosts_ctl("ypserv", STRING_UNKNOWN, host, ""); #endif - tmp = securenets; - while (tmp) { - if (((rqhost->sin_addr.s_addr & ~tmp->mask.s_addr) - | tmp->net.s_addr) == rqhost->sin_addr.s_addr) { + if (debug) + yp_error("yp_access(): compare start"); + SLIST_FOREACH (snp, &securenets, sn_next) { + if (compare_subnet(sap, + (struct sockaddr *)&(snp->sn_addr), + (struct sockaddr *)&(snp->sn_mask)) == 0) { status_securenets = 1; + if (debug) + yp_error("yp_access(): compare success!"); break; } - tmp = tmp->next; } - + if (debug) + yp_error("yp_access(): compare end"); #ifdef TCP_WRAPPER if (status_securenets == 0 || status_tcpwrap == 0) { #else @@ -296,16 +657,14 @@ not privileged", map, inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); * * In either case deny access. */ - if (rqhost->sin_addr.s_addr != oldaddr) { - yp_error("connect from %s:%d to procedure %s refused", - inet_ntoa(rqhost->sin_addr), - ntohs(rqhost->sin_port), - yp_procedure); - oldaddr = rqhost->sin_addr.s_addr; + if (memcmp(sap, &oldaddr, sizeof(oldaddr))) { + yp_error("connect from %s:%s to procedure %s refused", + host, serv, yp_procedure); + memcpy(&oldaddr, sap, sizeof(oldaddr)); } - return(1); + return (1); } - return(0); + return (0); } @@ -318,13 +677,12 @@ yp_validdomain(const char *domain) if (domain == NULL || strstr(domain, "binding") || !strcmp(domain, ".") || !strcmp(domain, "..") || strchr(domain, '/') || strlen(domain) > YPMAXDOMAIN) - return(1); + return (1); snprintf(dompath, sizeof(dompath), "%s/%s", yp_dir, domain); if (stat(dompath, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) - return(1); - + return (1); - return(0); + return (0); } diff --git a/usr.sbin/ypserv/yp_access_inet.c b/usr.sbin/ypserv/yp_access_inet.c new file mode 100644 index 0000000..c8ff52e --- /dev/null +++ b/usr.sbin/ypserv/yp_access_inet.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2010-2011 Hiroki Sato. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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> +__FBSDID("$FreeBSD$"); + +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <string.h> +#include <stdlib.h> + +#include "yp_extern.h" + +int +yp_mask2prefixlen_in(const struct sockaddr *sap, int *prefixlen) +{ + int x, y = 0; + const u_char *p; + const struct in_addr *addr; + const struct sockaddr_in *sainp; + + sainp = (const struct sockaddr_in *)sap; + addr = &(sainp->sin_addr); + p = (const u_char *)&addr->s_addr; + for (x = 0; x < (int)sizeof(addr->s_addr); x++) + if (p[x] != 0xff) + break; + if (x < (int)sizeof(addr->s_addr)) + for (y = 0; y < 8; y++) + if ((p[x] & (0x80 >> y)) == 0) + break; + *prefixlen = x * 8 + y; + return (0); +} + +int +yp_prefixlen2mask_in(struct sockaddr *sap, const int *prefixlen) +{ + int i; + int len; + u_char *p; + struct in_addr *addr; + struct sockaddr_in *sainp; + + len = *prefixlen; + if (0 > len || len > 32) + return (-1); + + sainp = (struct sockaddr_in *)sap; + memset(&sainp->sin_addr, 0, sizeof(sainp->sin_addr)); + addr = &(sainp->sin_addr); + p = (u_char *)&addr->s_addr; + for (i = 0; i < len / 8; i++) + p[i] = 0xff; + if (len % 8) + p[i] = (0xff00 >> (len % 8)) & 0xff; + return (0); +} + +struct sockaddr * +yp_mask_in(const struct sockaddr *addr, const struct sockaddr *mask) +{ + int i; + const u_char *p, *q; + u_char *r; + const struct sockaddr_in *in_addr; + const struct sockaddr_in *in_mask; + struct sockaddr_in *in_res; + + in_addr = (const struct sockaddr_in *)addr; + in_mask = (const struct sockaddr_in *)mask; + + if ((in_res = malloc(sizeof(*in_res))) == NULL) + return NULL; + memcpy(in_res, in_addr, sizeof(*in_res)); + p = (const u_char *)&(in_addr->sin_addr.s_addr); + q = (const u_char *)&(in_mask->sin_addr.s_addr); + r = (u_char *)&(in_res->sin_addr.s_addr); + for (i = 0; i < (int)sizeof(in_addr->sin_addr.s_addr); i++) + r[i] = p[i] & q[i]; + + return ((struct sockaddr *)in_res); +} + +int +yp_compare_subnet_in(const struct sockaddr *a1, const struct sockaddr *a2) +{ + const struct sockaddr_in *in_a1 = (const struct sockaddr_in *)a1; + const struct sockaddr_in *in_a2 = (const struct sockaddr_in *)a2; + + if (debug) { + yp_error("yp_subnet_cmp_in(): a1"); + yp_debug_sa(a1); + yp_error("yp_subnet_cmp_in(): a2"); + yp_debug_sa(a2); + } + return (memcmp((const u_char *)&(in_a1->sin_addr.s_addr), + (const u_char *)&(in_a2->sin_addr.s_addr), + sizeof(in_a1->sin_addr.s_addr))); +} diff --git a/usr.sbin/ypserv/yp_access_inet6.c b/usr.sbin/ypserv/yp_access_inet6.c new file mode 100644 index 0000000..a45de20 --- /dev/null +++ b/usr.sbin/ypserv/yp_access_inet6.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2010-2011 Hiroki Sato. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <stdlib.h> +#include <string.h> + +#include "yp_extern.h" + +int +yp_mask2prefixlen_in6(const struct sockaddr *sap, int *prefixlen) +{ + int x, y = 0; + const u_char *p; + const struct in6_addr *addr; + const struct sockaddr_in6 *sain6p; + + sain6p = (const struct sockaddr_in6 *)sap; + addr = &(sain6p->sin6_addr); + for (x = 0; x < (int)sizeof(addr->s6_addr); x++) + if (addr->s6_addr[x] != 0xff) + break; + if (x < (int)sizeof(addr->s6_addr)) + for (y = 0; y < 8; y++) + if ((addr->s6_addr[x] & (0x80 >> y)) == 0) + break; + if (x < (int)sizeof(addr->s6_addr)) { + if (y != 0 && (addr->s6_addr[x] & (0x00ff >> y)) != 0) + return (-1); + p = (const u_char *)&addr->s6_addr[x + 1]; + for (; p < addr->s6_addr + sizeof(addr->s6_addr); p++) + if (*p != 0) + return (-1); + } + *prefixlen = x * 8 + y; + return (0); +} + +int +yp_prefixlen2mask_in6(struct sockaddr *sap, const int *prefixlen) +{ + int i; + int len; + int bytelen, bitlen; + u_char maskarray[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; + struct in6_addr *addr; + struct sockaddr_in6 *sain6p; + + len = *prefixlen; + if (0 > len || len > 128) + return (-1); + + sain6p = (struct sockaddr_in6 *)sap; + memset(&sain6p->sin6_addr, 0, sizeof(sain6p->sin6_addr)); + addr = &(sain6p->sin6_addr); + bytelen = len / 8; + bitlen = len % 8; + for (i = 0; i < bytelen; i++) + addr->s6_addr[i] = 0xff; + if (bitlen) + addr->s6_addr[bytelen] = maskarray[bitlen - 1]; + return (0); +} + +struct sockaddr * +yp_mask_in6(const struct sockaddr *addr, const struct sockaddr *mask) +{ + int i; + const u_char *p, *q; + u_char *r; + const struct sockaddr_in6 *in6_addr; + const struct sockaddr_in6 *in6_mask; + struct sockaddr_in6 *in6_res; + + in6_addr = (const struct sockaddr_in6 *)addr; + in6_mask = (const struct sockaddr_in6 *)mask; + + if ((in6_res = malloc(sizeof(*in6_res))) == NULL) + return NULL; + memcpy(in6_res, in6_addr, sizeof(*in6_res)); + p = (const u_char *)&(in6_addr->sin6_addr.s6_addr); + q = (const u_char *)&(in6_mask->sin6_addr.s6_addr); + r = (u_char *)&(in6_res->sin6_addr.s6_addr); + for (i = 0; i < (int)sizeof(in6_addr->sin6_addr.s6_addr); i++) + r[i] = p[i] & q[i]; + + return ((struct sockaddr *)in6_res); +} + +int +yp_compare_subnet_in6(const struct sockaddr *a1, const struct sockaddr *a2) +{ + const struct sockaddr_in6 *in6_a1 = (const struct sockaddr_in6 *)a1; + const struct sockaddr_in6 *in6_a2 = (const struct sockaddr_in6 *)a2; + + if (debug) { + yp_error("yp_subnet_cmp_in6(): a1"); + yp_debug_sa(a1); + yp_error("yp_subnet_cmp_in6(): a2"); + yp_debug_sa(a2); + yp_error("yp_subnet_cmp_in6(): scope: %d - %d", + in6_a1->sin6_scope_id, in6_a2->sin6_scope_id); + } + + if (in6_a1->sin6_scope_id != in6_a2->sin6_scope_id) + return (-1); + + return (memcmp(in6_a1->sin6_addr.s6_addr, + in6_a2->sin6_addr.s6_addr, + sizeof(in6_a1->sin6_addr.s6_addr))); +} diff --git a/usr.sbin/ypserv/yp_dblookup.c b/usr.sbin/ypserv/yp_dblookup.c index 61944dc..5dfc637 100644 --- a/usr.sbin/ypserv/yp_dblookup.c +++ b/usr.sbin/ypserv/yp_dblookup.c @@ -67,6 +67,7 @@ HASHINFO openinfo = { #define MAXDBS 20 #endif +static char nullbuf[] = ""; static int numdbs = 0; struct dbent { @@ -193,10 +194,8 @@ yp_flush_all(void) return; } -static char *inter_string = "YP_INTERDOMAIN"; -static char *secure_string = "YP_SECURE"; -static int inter_sz = sizeof("YP_INTERDOMAIN") - 1; -static int secure_sz = sizeof("YP_SECURE") - 1; +static char inter_string[] = "YP_INTERDOMAIN"; +static char secure_string[] = "YP_SECURE"; static int yp_setflags(DB *dbp) @@ -205,13 +204,13 @@ yp_setflags(DB *dbp) int flags = 0; key.data = inter_string; - key.size = inter_sz; + key.size = sizeof(inter_string) - 1; if (!(dbp->get)(dbp, &key, &data, 0)) flags |= YP_INTERDOMAIN; key.data = secure_string; - key.size = secure_sz; + key.size = sizeof(secure_string) - 1; if (!(dbp->get)(dbp, &key, &data, 0)) flags |= YP_SECURE; @@ -220,7 +219,7 @@ yp_setflags(DB *dbp) } int -yp_testflag(char *map, char *domain, int flag) +yp_testflag(const char *map, const char *domain, int flag) { char buf[MAXPATHLEN + 2]; register struct circleq_entry *qptr; @@ -501,7 +500,7 @@ yp_get_record(const char *domain, const char *map, #ifdef DB_CACHE if (TAILQ_FIRST(&qhead)->dbptr->size) { - TAILQ_FIRST(&qhead)->dbptr->key = ""; + TAILQ_FIRST(&qhead)->dbptr->key = nullbuf; TAILQ_FIRST(&qhead)->dbptr->size = 0; } #else diff --git a/usr.sbin/ypserv/yp_dnslookup.c b/usr.sbin/ypserv/yp_dnslookup.c index 4ea6a13..c18e220 100644 --- a/usr.sbin/ypserv/yp_dnslookup.c +++ b/usr.sbin/ypserv/yp_dnslookup.c @@ -223,7 +223,7 @@ yp_send_dns_reply(struct circleq_dnsentry *q, char *buf) { ypresponse result_v1; ypresp_val result_v2; - unsigned long xid; + unsigned long xid = 0; struct sockaddr_in client_addr; xdrproc_t xdrfunc; char *result; @@ -456,7 +456,7 @@ yp_async_lookup_name(struct svc_req *rqstp, char *name, int af) pending++; if (debug) - yp_error("queueing async DNS name lookup (%d)", q->id); + yp_error("queueing async DNS name lookup (%lu)", q->id); yp_prune_dnsq(); return(YP_TRUE); @@ -544,7 +544,7 @@ yp_async_lookup_addr(struct svc_req *rqstp, char *addr, int af) pending++; if (debug) - yp_error("queueing async DNS address lookup (%d)", q->id); + yp_error("queueing async DNS address lookup (%lu)", q->id); yp_prune_dnsq(); return(YP_TRUE); diff --git a/usr.sbin/ypserv/yp_error.c b/usr.sbin/ypserv/yp_error.c index 8d488f3..d3589c7 100644 --- a/usr.sbin/ypserv/yp_error.c +++ b/usr.sbin/ypserv/yp_error.c @@ -48,8 +48,6 @@ __FBSDID("$FreeBSD$"); int debug; extern int _rpcpmstart; -extern char *progname; - static void __verr(const char *fmt, va_list ap) __printflike(1, 0); static void __verr(const char *fmt, va_list ap) diff --git a/usr.sbin/ypserv/yp_extern.h b/usr.sbin/ypserv/yp_extern.h index 2e574b6..bb7d8af 100644 --- a/usr.sbin/ypserv/yp_extern.h +++ b/usr.sbin/ypserv/yp_extern.h @@ -32,15 +32,16 @@ * $FreeBSD$ */ +#include <sys/cdefs.h> +#include <sys/param.h> +#include <sys/types.h> +#include <rpc/rpc.h> +#include <rpcsvc/yp.h> #include <db.h> #include <limits.h> #include <stdio.h> #include <string.h> #include <unistd.h> -#include <sys/cdefs.h> -#include <sys/types.h> -#include <rpc/rpc.h> -#include <rpcsvc/yp.h> #ifndef _PATH_YP #define _PATH_YP "/var/yp/" @@ -57,6 +58,8 @@ #define YP_SECURE 0x1 #define YP_INTERDOMAIN 0x2 +#define SECURENETS_FNAME "securenets" + /* * External functions and variables. */ @@ -66,9 +69,13 @@ extern int ypdb_debug; extern int do_dns; extern int children; extern int resfd; -extern char *progname; -extern char *yp_dir; +extern const char *progname; +extern const char *yp_dir; extern pid_t yp_pid; +extern char securenets_path[MAXPATHLEN]; +extern enum yp_snf_format { + YP_SNF_NATIVE, + YP_SNF_SOLARIS } securenets_format; extern enum ypstat yp_errno; extern void yp_error(const char *, ...) __printflike(1, 2); @@ -86,13 +93,27 @@ extern int yp_access(const char *, const char *, const struct svc_req *); #else extern int yp_access(const char *, const struct svc_req *); #endif +extern void yp_debug_sa(const struct sockaddr *); +#ifdef AF_INET +extern int yp_mask2prefixlen_in(const struct sockaddr *, int *); +extern int yp_prefixlen2mask_in(struct sockaddr *, const int *); +extern struct sockaddr *yp_mask_in(const struct sockaddr *, const struct sockaddr *); +extern int yp_compare_subnet_in(const struct sockaddr *, const struct sockaddr *); +#endif +#ifdef AF_INET6 +extern int yp_mask2prefixlen_in6(const struct sockaddr *, int *); +extern int yp_prefixlen2mask_in6(struct sockaddr *, const int *); +extern struct sockaddr *yp_mask_in6(const struct sockaddr *, const struct sockaddr *); +extern int yp_compare_subnet_in6(const struct sockaddr *, const struct sockaddr *); +#endif extern int yp_validdomain(const char *); extern DB *yp_open_db(const char *, const char *); extern DB *yp_open_db_cache(const char *, const char *, const char *, int); extern void yp_flush_all(void); extern void yp_init_dbs(void); -extern int yp_testflag(char *, char *, int); -extern void load_securenets(void); +extern int yp_testflag(const char *, const char *, int); +extern int load_securenets(void); +extern void show_securenets(void); #ifdef DB_CACHE extern ypstat yp_select_map(char *, char *, keydat *, int); diff --git a/usr.sbin/ypserv/yp_main.c b/usr.sbin/ypserv/yp_main.c index ec39d1b..71bc905 100644 --- a/usr.sbin/ypserv/yp_main.c +++ b/usr.sbin/ypserv/yp_main.c @@ -44,7 +44,8 @@ __FBSDID("$FreeBSD$"); #include <sys/queue.h> #include <sys/socket.h> #include <sys/wait.h> -#include "yp.h" +#include <rpc/rpc.h> +#include <rpc/rpc_com.h> #include <err.h> #include <errno.h> #include <memory.h> @@ -59,58 +60,58 @@ __FBSDID("$FreeBSD$"); #include <sysent.h> /* getdtablesize, open */ #endif /* __cplusplus */ #include <netinet/in.h> +#include <netconfig.h> #include <netdb.h> + +#include "yp.h" #include "yp_extern.h" -#include <netconfig.h> -#include <rpc/rpc.h> -#include <rpc/rpc_com.h> #ifndef SIG_PF #define SIG_PF void(*)(int) #endif #define _RPCSVC_CLOSEDOWN 120 -int _rpcpmstart; /* Started by a port monitor ? */ -static int _rpcfdtype; - /* Whether Stream or Datagram ? */ +int _rpcpmstart; /* Started by a port monitor ? */ +static int _rpcfdtype; /* Whether Stream or Datagram ? */ static int _rpcaf; static int _rpcfd; - /* States a server can be in wrt request */ +/* States a server can be in wrt request */ +/* Set when a request is serviced */ +static enum rpcsvcstate { + _IDLE = 0, + _SERVED, + _SERVING, +} _rpcsvcstate; -#define _IDLE 0 -#define _SERVED 1 -#define _SERVING 2 +const char *progname = "ypserv"; +const char *yp_dir = _PATH_YP; +static char *servname = NULL; -extern void ypprog_1(struct svc_req *, SVCXPRT *); -extern void ypprog_2(struct svc_req *, SVCXPRT *); -extern int _rpc_dtablesize(void); -extern int _rpcsvcstate; /* Set when a request is serviced */ -char *progname = "ypserv"; -char *yp_dir = _PATH_YP; -/*int debug = 0;*/ int do_dns = 0; int resfd; +int debug; +pid_t yp_pid; struct socklistent { + SLIST_ENTRY(socklistent) sle_next; + int sle_sock; struct sockaddr_storage sle_ss; - SLIST_ENTRY(socklistent) sle_next; }; static SLIST_HEAD(, socklistent) sle_head = SLIST_HEAD_INITIALIZER(sle_head); struct bindaddrlistent { - const char *ble_hostname; SLIST_ENTRY(bindaddrlistent) ble_next; + + const char *ble_hostname; }; static SLIST_HEAD(, bindaddrlistent) ble_head = SLIST_HEAD_INITIALIZER(ble_head); -static char *servname = "0"; - -static -void _msgout(char* msg, ...) +static void +_msgout(const char* msg, ...) { va_list ap; @@ -125,8 +126,6 @@ void _msgout(char* msg, ...) va_end(ap); } -pid_t yp_pid; - static void yp_svc_run(void) { @@ -188,24 +187,22 @@ unregister(void) static void reaper(int sig) { - int status; - int saved_errno; + int status; + int saved_errno; saved_errno = errno; - - if (sig == SIGHUP) { + switch (sig) { + case SIGHUP: load_securenets(); #ifdef DB_CACHE yp_flush_all(); #endif - errno = saved_errno; - return; - } - - if (sig == SIGCHLD) { + break; + case SIGCHLD: while (wait3(&status, WNOHANG, NULL) > 0) children--; - } else { + break; + default: unregister(); exit(0); } @@ -216,15 +213,16 @@ reaper(int sig) static void usage(void) { - fprintf(stderr, "usage: ypserv [-h] [-d] [-n] [-p path] [-P port]\n"); - exit(1); + fprintf(stderr, "usage: ypserv " + "[-d] [-h hostname] [-n] [-p ypdir] [-P port] [-S]\n"); } static void closedown(int sig) { + if (sig != SIGALRM) + return; if (_rpcsvcstate == _IDLE) { - extern fd_set svc_fdset; static int size; int i, openfd; @@ -246,8 +244,8 @@ closedown(int sig) if (_rpcsvcstate == _SERVED) _rpcsvcstate = _IDLE; - (void) signal(SIGALRM, (SIG_PF) closedown); - (void) alarm(_RPCSVC_CLOSEDOWN/2); + (void)signal(SIGALRM, (SIG_PF)closedown); + (void)alarm(_RPCSVC_CLOSEDOWN/2); } static int @@ -261,10 +259,13 @@ create_service(const int sock, const struct netconfig *nconf, struct socklistent *slep; struct bindaddrlistent *blep; struct netbuf svcaddr; + char nullserv[] = "0"; SLIST_INIT(&sle_head); memset(&hints, 0, sizeof(hints)); memset(&svcaddr, 0, sizeof(svcaddr)); + if (servname == NULL) + servname = nullserv; hints.ai_family = si->si_af; hints.ai_socktype = si->si_socktype; @@ -282,9 +283,10 @@ create_service(const int sock, const struct netconfig *nconf, error = getaddrinfo(blep->ble_hostname, servname, &hints, &res0); if (error) { - _msgout("getaddrinfo(): %s", - gai_strerror(error)); - return -1; + _msgout("%s: getaddrinfo(): %s", + __func__, + gai_strerror(error)); + return (-1); } for (res = res0; res; res = res->ai_next) { int s; @@ -301,7 +303,7 @@ create_service(const int sock, const struct netconfig *nconf, nconf->nc_netid, strerror(errno)); freeaddrinfo(res0); - return -1; + return (-1); } if (bindresvport_sa(s, res->ai_addr) == -1) { if ((errno != EPERM) || @@ -313,7 +315,7 @@ create_service(const int sock, const struct netconfig *nconf, strerror(errno)); freeaddrinfo(res0); close(sock); - return -1; + return (-1); } } if (nconf->nc_semantics != NC_TPI_CLTS) @@ -325,7 +327,7 @@ create_service(const int sock, const struct netconfig *nconf, strerror(errno)); freeaddrinfo(res0); close(s); - return -1; + return (-1); } memset(slep, 0, sizeof(*slep)); memcpy(&slep->sle_ss, @@ -338,7 +340,8 @@ create_service(const int sock, const struct netconfig *nconf, * If servname == "0", redefine it by using * the bound socket. */ - if (strncmp("0", servname, 1) == 0) { + if (servname == NULL || + strncmp("0", servname, 1) == 0) { struct sockaddr *sap; socklen_t slen; char *sname; @@ -349,30 +352,30 @@ create_service(const int sock, const struct netconfig *nconf, strerror(errno)); freeaddrinfo(res0); close(s); - return -1; + return (-1); } memset(sname, 0, NI_MAXSERV); sap = (struct sockaddr *)&slep->sle_ss; - slen = sizeof(*sap); + slen = sap->sa_len; error = getsockname(s, sap, &slen); if (error) { _msgout("getsockname(): %s", strerror(errno)); freeaddrinfo(res0); close(s); - return -1; + return (-1); } - error = getnameinfo(sap, slen, + error = getnameinfo(sap, sap->sa_len, NULL, 0, sname, NI_MAXSERV, - NI_NUMERICHOST | NI_NUMERICSERV); + NI_NUMERICSERV); if (error) { _msgout("getnameinfo(): %s", - strerror(errno)); + gai_strerror(error)); freeaddrinfo(res0); close(s); - return -1; + return (-1); } servname = sname; } @@ -383,7 +386,7 @@ create_service(const int sock, const struct netconfig *nconf, slep = malloc(sizeof(*slep)); if (slep == NULL) { _msgout("malloc failed: %s", strerror(errno)); - return -1; + return (-1); } memset(slep, 0, sizeof(*slep)); slep->sle_sock = sock; @@ -419,9 +422,11 @@ create_service(const int sock, const struct netconfig *nconf, continue; } } - while(!(SLIST_EMPTY(&sle_head))) + while(!(SLIST_EMPTY(&sle_head))) { + slep = SLIST_FIRST(&sle_head); SLIST_REMOVE_HEAD(&sle_head, sle_next); - + free(slep); + } /* * Register RPC service to rpcbind by using AI_PASSIVE address. */ @@ -429,7 +434,7 @@ create_service(const int sock, const struct netconfig *nconf, error = getaddrinfo(NULL, servname, &hints, &res0); if (error) { _msgout("getaddrinfo(): %s", gai_strerror(error)); - return -1; + return (-1); } svcaddr.buf = res0->ai_addr; svcaddr.len = res0->ai_addrlen; @@ -442,7 +447,7 @@ create_service(const int sock, const struct netconfig *nconf, rpcb_set(YPPROG, YPVERS, nconf, &svcaddr); freeaddrinfo(res0); - return 0; + return (0); } int @@ -460,7 +465,7 @@ main(int argc, char *argv[]) memset(&si, 0, sizeof(si)); SLIST_INIT(&ble_head); - while ((ch = getopt(argc, argv, "dh:np:P:")) != -1) { + while ((ch = getopt(argc, argv, "dh:np:P:S")) != -1) { switch (ch) { case 'd': debug = ypdb_debug = 1; @@ -481,8 +486,12 @@ main(int argc, char *argv[]) case 'P': servname = optarg; break; + case 'S': + securenets_format = YP_SNF_SOLARIS; + break; default: usage(); + exit(1); } } /* @@ -495,6 +504,8 @@ main(int argc, char *argv[]) memset(blep, 0, sizeof(*blep)); SLIST_INSERT_HEAD(&ble_head, blep, ble_next); } + snprintf(securenets_path, sizeof(securenets_path), + "%s/%s", yp_dir, SECURENETS_FNAME); load_securenets(); yp_init_resolver(); @@ -514,13 +525,12 @@ main(int argc, char *argv[]) } else { /* standalone mode */ if (!debug) { - if (daemon(0,0)) { + if (daemon(0,0)) err(1,"cannot fork"); - } openlog("ypserv", LOG_PID, LOG_DAEMON); } _rpcpmstart = 0; - _rpcaf = AF_INET; + _rpcaf = 0; _rpcfd = RPC_ANYFD; unregister(); } @@ -536,12 +546,10 @@ main(int argc, char *argv[]) "Ignored.", nconf->nc_netid); continue; } - if (_rpcpmstart) { + if (_rpcpmstart) if (si.si_socktype != _rpcfdtype || si.si_af != _rpcaf) continue; - } else if (si.si_af != _rpcaf) - continue; error = create_service(_rpcfd, nconf, &si); if (error) { endnetconfig(nc_handle); @@ -551,27 +559,31 @@ main(int argc, char *argv[]) } } endnetconfig(nc_handle); - while(!(SLIST_EMPTY(&ble_head))) + while(!(SLIST_EMPTY(&ble_head))) { + blep = SLIST_FIRST(&ble_head); SLIST_REMOVE_HEAD(&ble_head, ble_next); + free(blep); + } if (ntrans == 0) { _msgout("no transport is available. Aborted."); exit(1); } if (_rpcpmstart) { - (void) signal(SIGALRM, (SIG_PF) closedown); - (void) alarm(_RPCSVC_CLOSEDOWN/2); + (void)signal(SIGALRM, (SIG_PF)closedown); + (void)alarm(_RPCSVC_CLOSEDOWN/2); } /* * Make sure SIGPIPE doesn't blow us away while servicing TCP * connections. */ - (void) signal(SIGPIPE, SIG_IGN); - (void) signal(SIGCHLD, (SIG_PF) reaper); - (void) signal(SIGTERM, (SIG_PF) reaper); - (void) signal(SIGINT, (SIG_PF) reaper); - (void) signal(SIGHUP, (SIG_PF) reaper); + (void)signal(SIGPIPE, SIG_IGN); + (void)signal(SIGCHLD, (SIG_PF)reaper); + (void)signal(SIGTERM, (SIG_PF)reaper); + (void)signal(SIGINT, (SIG_PF)reaper); + (void)signal(SIGHUP, (SIG_PF)reaper); yp_svc_run(); - _msgout("svc_run returned"); - exit(1); + /* NOTREACHED */ + _msgout("svc_run returned"); + return (1); } diff --git a/usr.sbin/ypserv/yp_server.c b/usr.sbin/ypserv/yp_server.c index ba20c3cd..4526a4b 100644 --- a/usr.sbin/ypserv/yp_server.c +++ b/usr.sbin/ypserv/yp_server.c @@ -48,11 +48,10 @@ __FBSDID("$FreeBSD$"); #include <rpc/rpc.h> int children = 0; +static char nullbuf[] = ""; #define MASTER_STRING "YP_MASTER_NAME" -#define MASTER_SZ sizeof(MASTER_STRING) - 1 #define ORDER_STRING "YP_LAST_MODIFIED" -#define ORDER_SZ sizeof(ORDER_STRING) - 1 static pid_t yp_fork(void) @@ -76,6 +75,7 @@ ypproc_null_2_svc(void *argp, struct svc_req *rqstp) static char * result; static char rval = 0; + argp = NULL; #ifdef DB_CACHE if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) #else @@ -135,7 +135,7 @@ ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) { static ypresp_val result; - result.val.valdat_val = ""; + result.val.valdat_val = nullbuf; result.val.valdat_len = 0; #ifdef DB_CACHE @@ -205,7 +205,7 @@ ypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) { static ypresp_key_val result; - result.val.valdat_val = result.key.keydat_val = ""; + result.val.valdat_val = result.key.keydat_val = nullbuf; result.val.valdat_len = result.key.keydat_len = 0; #ifdef DB_CACHE @@ -237,7 +237,7 @@ ypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp) { static ypresp_key_val result; - result.val.valdat_val = result.key.keydat_val = ""; + result.val.valdat_val = result.key.keydat_val = nullbuf; result.val.valdat_len = result.key.keydat_len = 0; #ifdef DB_CACHE @@ -426,6 +426,7 @@ ypproc_clear_2_svc(void *argp, struct svc_req *rqstp) static char * result; static char rval = 0; + argp = NULL; #ifdef DB_CACHE if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) #else @@ -494,7 +495,7 @@ ypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) */ result.more = TRUE; result.ypresp_all_u.val.key.keydat_len = 0; - result.ypresp_all_u.val.key.keydat_val = ""; + result.ypresp_all_u.val.key.keydat_val = nullbuf; #ifdef DB_CACHE if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { @@ -574,10 +575,11 @@ ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) { static ypresp_master result; static char ypvalbuf[YPMAXRECORD]; - keydat key = { MASTER_SZ, MASTER_STRING }; + char keybuf[] = MASTER_STRING; + keydat key = { sizeof(keybuf) - 1, keybuf }; valdat val; - result.peer = ""; + result.peer = nullbuf; #ifdef DB_CACHE if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { @@ -612,7 +614,7 @@ ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) ypvalbuf[val.valdat_len] = '\0'; result.peer = ypvalbuf; } else - result.peer = ""; + result.peer = nullbuf; return (&result); } @@ -621,7 +623,8 @@ ypresp_order * ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) { static ypresp_order result; - keydat key = { ORDER_SZ, ORDER_STRING }; + char keybuf[] = ORDER_STRING; + keydat key = { sizeof(keybuf) - 1, keybuf }; valdat val; result.ordernum = 0; @@ -662,7 +665,8 @@ ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) return (&result); } -static void yp_maplist_free(struct ypmaplist *yp_maplist) +static void +yp_maplist_free(struct ypmaplist *yp_maplist) { register struct ypmaplist *next; @@ -815,7 +819,7 @@ ypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp) ypresp_val *v2_result; result.yp_resptype = YPRESP_VAL; - result.ypresponse_u.yp_resp_valtype.val.valdat_val = ""; + result.ypresponse_u.yp_resp_valtype.val.valdat_val = nullbuf; result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0; if (argp->yp_reqtype != YPREQ_KEY) { @@ -844,7 +848,7 @@ ypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp) result.yp_resptype = YPRESP_KEY_VAL; result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = - result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; + result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = nullbuf; result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; @@ -875,7 +879,7 @@ ypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp) result.yp_resptype = YPRESP_KEY_VAL; result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = - result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; + result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = nullbuf; result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; @@ -916,7 +920,7 @@ ypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp) * I hope this is right. */ result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0; - result.ypresponse_u.yp_resp_map_parmstype.peer = ""; + result.ypresponse_u.yp_resp_map_parmstype.peer = nullbuf; if (argp->yp_reqtype != YPREQ_MAP_PARMS) { return(&result); @@ -956,6 +960,8 @@ ypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp) /* * Not implemented. */ + argp = NULL; + rqstp = NULL; return (&result); } @@ -968,6 +974,8 @@ ypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp) /* * Not implemented. */ + argp = NULL; + rqstp = NULL; return (&result); } @@ -980,6 +988,8 @@ ypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp) /* * Not implemented. */ + argp = NULL; + rqstp = NULL; return (&result); } diff --git a/usr.sbin/ypserv/ypserv.8 b/usr.sbin/ypserv/ypserv.8 index 9d88731..c219263 100644 --- a/usr.sbin/ypserv/ypserv.8 +++ b/usr.sbin/ypserv/ypserv.8 @@ -30,7 +30,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 13, 2009 +.Dd May 29, 2011 .Dt YPSERV 8 .Os .Sh NAME @@ -40,8 +40,10 @@ .Nm .Op Fl n .Op Fl d +.Op Fl h Ar addr .Op Fl P Ar port .Op Fl p Ar path +.Op Fl S .Sh DESCRIPTION .Tn NIS is an RPC-based service designed to allow a number of UNIX-based @@ -259,6 +261,46 @@ sample securenets file might look like this: # allow connections from any host # between 10.0.0.0 to 10.0.15.255 10.0.0.0 255.255.240.0 +# IPv4 addresses in CIDR form +172.16.0.1/16 +# IPv4 host +172.17.0.1/32 +# IPv6 address with netmask +2001:db8:1::1 ffff:ffff:ffff:ffff:: +# IPv6 address with prefix length +2001:db8:2::1/64 +# IPv6 connections from local host +::/128 +# IPv6 host +2001:db8:3::1/128 +.Ed +.Pp +When +.Fl S +flag is specified, another format with the host field and the netmask +field exchanged is used instead. This is for compatibility with an +implementation found in Solaris. An example looks like the following: +.Bd -unfilled -offset indent +# allow connections from local host -- mandatory +255.255.255.255 127.0.0.1 +# allow connections from any host +# on the 192.168.128.0 network +255.255.255.0 192.168.128.0 +# allow connections from any host +# between 10.0.0.0 to 10.0.15.255 +255.255.240.0 10.0.0.0 +# IPv4 addresses in CIDR form +172.16.0.1/16 +# "host" keyword can be used as 255.255.255.255 +host 172.17.0.1 +# IPv6 address with netmask +ffff:ffff:ffff:ffff:: 2001:db8:1::1 +# IPv6 address with prefix length +2001:db8:2::1/64 +# IPv6 connections from local host +::/128 +# "host" keyword can be used as /128 +host 2001:db8:3::1 .Ed .Pp If @@ -434,6 +476,14 @@ flag may be used to specify an alternate root path, allowing the system administrator to move the map files to a different place within the file system. +.It Fl S +Specify +.Pa secrenets +file format as Solaris-compatible. The differences from the native +format are the order of the host and netmask fields, and availability +of +.Dq host +keyword. .El .Sh FILES .Bl -tag -width Pa -compact |