diff options
-rw-r--r-- | usr.sbin/routed/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/routed/defs.h | 36 | ||||
-rw-r--r-- | usr.sbin/routed/if.c | 70 | ||||
-rw-r--r-- | usr.sbin/routed/input.c | 101 | ||||
-rw-r--r-- | usr.sbin/routed/main.c | 29 | ||||
-rw-r--r-- | usr.sbin/routed/output.c | 25 | ||||
-rw-r--r-- | usr.sbin/routed/pathnames.h | 2 | ||||
-rw-r--r-- | usr.sbin/routed/rdisc.c | 84 | ||||
-rw-r--r-- | usr.sbin/routed/rtquery/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/routed/table.c | 138 | ||||
-rw-r--r-- | usr.sbin/routed/trace.c | 76 |
11 files changed, 360 insertions, 209 deletions
diff --git a/usr.sbin/routed/Makefile b/usr.sbin/routed/Makefile index 594a050..b17fd70 100644 --- a/usr.sbin/routed/Makefile +++ b/usr.sbin/routed/Makefile @@ -1,8 +1,10 @@ -# @(#)Makefile 8.1 (Berkeley) 6/19/93 +# From: @(#)Makefile 8.1 (Berkeley) 6/19/93 +# $Id$ PROG= routed SRCS= if.c input.c main.c output.c parms.c radix.c rdisc.c table.c trace.c MAN8= routed.8 SUBDIR= rtquery +#COPTS= -g -DDEBUG -Wall .include <bsd.prog.mk> diff --git a/usr.sbin/routed/defs.h b/usr.sbin/routed/defs.h index c4bcb6a..05c2403 100644 --- a/usr.sbin/routed/defs.h +++ b/usr.sbin/routed/defs.h @@ -31,9 +31,13 @@ * SUCH DAMAGE. * * @(#)defs.h 8.1 (Berkeley) 6/5/93 - * $Id$ + * $Id: defs.h,v 1.4 1996/07/22 21:12:14 wollman Exp $ */ +#ifndef __NetBSD__ +#ident "$Revision: 1.1.3.3 $" +#endif + /* Definitions for RIPv2 routing process. * * This code is based on the 4.4BSD `routed` daemon, with extensions to @@ -77,18 +81,20 @@ #include <sys/ioctl.h> #include <sys/sysctl.h> #include <sys/socket.h> -#include <net/if.h> -#include <net/route.h> +#ifdef sgi #include <net/radix.h> -#ifndef sgi -struct walkarg; +#else +#include "radix.h" #endif +#include <net/if.h> +#include <net/route.h> #include <net/if_dl.h> #include <netinet/in.h> #include <arpa/inet.h> #define RIPVERSION RIPv2 #include <protocols/routed.h> + /* Type of an IP address. * Some systems do not like to pass structures, so do not use in_addr. * Some systems think a long has 64 bits, which would be a gross waste. @@ -98,7 +104,11 @@ struct walkarg; #ifdef sgi #define naddr __uint32_t #else +#ifdef __NetBSD__ +#define naddr u_int32_t +#else #define naddr u_long +#endif #define _HAVE_SA_LEN #define _HAVE_SIN_LEN #endif @@ -147,6 +157,12 @@ union pkt_buf { }; +/* no more routes than this, to protect ourself in case something goes + * whacko and starts broadcast zillions of bogus routes. + */ +#define MAX_ROUTES (128*1024) +extern int total_routes; + /* Main, daemon routing table structure */ struct rt_entry { @@ -448,15 +464,10 @@ extern void logbad(int, char *, ...); #else #define DBGERR(dump,msg) LOGERR(msg) #endif -#ifdef MCAST_PPP_BUG -extern void mcasterr(struct interface *, int, char *); -#define MCASTERR(ifp,dump,msg) mcasterr(ifp, dump, "setsockopt(IP_"msg")") -#else -#define MCASTERR(ifp, dump,msg) DBGERR(dump,"setsockopt(IP_" msg ")") -#endif extern char *naddr_ntoa(naddr); extern char *saddr_ntoa(struct sockaddr *); +extern void *rtmalloc(size_t, char *); extern void timevaladd(struct timeval *, struct timeval *); extern void intvl_random(struct timeval *, u_long, u_long); extern int getnet(char *, naddr *, naddr *); @@ -538,9 +549,6 @@ extern naddr ripv1_mask_net(naddr, struct interface *); extern naddr ripv1_mask_host(naddr,struct interface *); #define on_net(a,net,mask) (((ntohl(a) ^ (net)) & (mask)) == 0) extern int check_dst(naddr); -#ifdef sgi -extern int sysctl(int *, u_int, void *, size_t *, void *, size_t); -#endif extern void addrouteforif(register struct interface *); extern void ifinit(void); extern int walk_bad(struct radix_node *, struct walkarg *); diff --git a/usr.sbin/routed/if.c b/usr.sbin/routed/if.c index 059b594..71b4ad5 100644 --- a/usr.sbin/routed/if.c +++ b/usr.sbin/routed/if.c @@ -31,9 +31,12 @@ * SUCH DAMAGE. */ -#if !defined(lint) && !defined(sgi) +#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93"; -#endif /* not lint */ +#elif defined(__NetBSD__) +static char rcsid[] = "$NetBSD$"; +#endif +#ident "$Revision: 1.1.3.3 $" #include "defs.h" #include "pathnames.h" @@ -60,10 +63,7 @@ ifwithaddr(naddr addr, struct interface *ifp, *possible = 0; for (ifp = ifnet; ifp; ifp = ifp->int_next) { - if ((ifp->int_addr == addr - && !(ifp->int_if_flags & IFF_POINTOPOINT)) - || (ifp->int_dstaddr == addr - && (ifp->int_if_flags & IFF_POINTOPOINT)) + if (ifp->int_addr == addr || ((ifp->int_if_flags & IFF_BROADCAST) && ifp->int_brdaddr == addr && bcast)) { @@ -169,7 +169,7 @@ std_mask(naddr addr) /* in network order */ } -/* Find The netmask that would be inferred by RIPv1 listeners +/* Find the netmask that would be inferred by RIPv1 listeners * on the given interface for a given network. * If no interface is specified, look for the best fitting interface. */ @@ -451,14 +451,15 @@ ifinit(void) static size_t sysctl_buf_size = 0; uint complaints = 0; static u_int prev_complaints = 0; -# define COMP_NOT_INET 0x01 -# define COMP_WIERD 0x02 -# define COMP_NOADDR 0x04 -# define COMP_NODST 0x08 -# define COMP_NOBADR 0x10 -# define COMP_NOMASK 0x20 -# define COMP_DUP 0x40 -# define COMP_BAD_METRIC 0x80 +# define COMP_NOT_INET 0x001 +# define COMP_WIERD 0x002 +# define COMP_NOADDR 0x004 +# define COMP_NODST 0x008 +# define COMP_NOBADR 0x010 +# define COMP_NOMASK 0x020 +# define COMP_DUP 0x040 +# define COMP_BAD_METRIC 0x080 +# define COMP_NETMASK 0x100 struct interface ifs, ifs0, *ifp, *ifp1; struct rt_entry *rt; @@ -496,7 +497,6 @@ ifinit(void) if ((needed = sysctl_buf_size) != 0) { if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0) break; - if (errno != ENOMEM && errno != EFAULT) BADERR(1, "ifinit: get interface table"); free(sysctl_buf); @@ -504,8 +504,7 @@ ifinit(void) } if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) BADERR(1,"ifinit: route-sysctl-estimate"); - if ((sysctl_buf = malloc(sysctl_buf_size = needed)) == 0) - BADERR(1,"ifinit: malloc"); + sysctl_buf = rtmalloc(sysctl_buf_size = needed, "ifinit"); } ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed); @@ -538,7 +537,7 @@ ifinit(void) continue; } if (ifam->ifam_type != RTM_NEWADDR) { - DBGERR(1,"ifinit: out of sync"); + logbad(1,"ifinit: out of sync"); continue; } @@ -703,6 +702,9 @@ ifinit(void) } if (ifp != 0) { + /* The primary representative of an alias worries + * about how things are working. + */ if (ifp->int_state & IS_ALIAS) continue; @@ -848,9 +850,7 @@ ifinit(void) /* Add it to the list of interfaces */ - ifp = (struct interface *)malloc(sizeof(*ifp)); - if (ifp == 0) - BADERR(1,"ifinit: out of memory"); + ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit"); bcopy(&ifs, ifp, sizeof(*ifp)); if (ifnet != 0) { ifp->int_next = ifnet; @@ -859,6 +859,32 @@ ifinit(void) ifnet = ifp; trace_if("Add", ifp); + /* Notice likely bad netmask. + */ + if (!(prev_complaints & COMP_NETMASK) + && !(ifp->int_if_flags & IFF_POINTOPOINT)) { + for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) { + if (ifp1->int_mask == ifp->int_mask) + continue; + if (ifp1->int_if_flags & IFF_POINTOPOINT) + continue; + if (on_net(ifp->int_addr, + ifp1->int_net, ifp1->int_mask) + || on_net(ifp1->int_addr, + ifp->int_net, ifp->int_mask)) { + msglog("possible netmask problem" + " betwen %s:%s and %s:%s", + ifp->int_name, + addrname(htonl(ifp->int_net), + ifp->int_mask, 1), + ifp1->int_name, + addrname(htonl(ifp1->int_net), + ifp1->int_mask, 1)); + complaints |= COMP_NETMASK; + } + } + } + /* Count the # of directly connected networks. */ if (!(ifp->int_state & IS_ALIAS)) { diff --git a/usr.sbin/routed/input.c b/usr.sbin/routed/input.c index 2a369d0..7df5988 100644 --- a/usr.sbin/routed/input.c +++ b/usr.sbin/routed/input.c @@ -31,13 +31,12 @@ * SUCH DAMAGE. */ -#if !defined(lint) && !defined(sgi) -/* +#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93"; -*/ -static const char rcsid[] = - "$Id$"; -#endif /* not lint */ +#elif defined(__NetBSD__) +static char rcsid[] = "$NetBSD$"; +#endif +#ident "$Revision: 1.1.3.3 $" #include "defs.h" @@ -203,10 +202,14 @@ input(struct sockaddr_in *from, /* received from this IP address */ && n == rip->rip_nets && n+1 == lim) { if (from->sin_port != htons(RIP_PORT)) { - /* query */ + /* query from `rtquery` or similar + */ supply(from, ifp, OUT_QUERY, 0, rip->rip_vers); } else if (supplier) { + /* a router trying to prime its + * tables. + */ supply(from, ifp, OUT_UNICAST, 0, rip->rip_vers); } @@ -236,34 +239,35 @@ input(struct sockaddr_in *from, /* received from this IP address */ } if (rip->rip_vers == RIPv1 - || 0 == (mask = ntohl(n->n_mask))) + || 0 == (mask = ntohl(n->n_mask)) + || 0 != (ntohl(dst) & ~mask)) mask = ripv1_mask_host(dst,ifp); rt = rtget(dst, mask); - if (!rt) + if (!rt && dst != RIP_DEFAULT) rt = rtfind(n->n_dst); n->n_tag = 0; n->n_nhop = 0; - if (!rt) { + if (rip->rip_vers == RIPv1) { + n->n_mask = 0; + } else { + n->n_mask = mask; + } + if (rt == 0) { n->n_metric = HOPCNT_INFINITY; } else { n->n_metric = rt->rt_metric+1; - if (ifp != 0) - n->n_metric += ifp->int_metric; + n->n_metric += (ifp!=0) ? ifp->int_metric : 1; if (n->n_metric > HOPCNT_INFINITY) n->n_metric = HOPCNT_INFINITY; - if (rip->rip_vers == RIPv1) { - n->n_mask = 0; - } else { + if (rip->rip_vers != RIPv1) { n->n_tag = rt->rt_tag; - if (!ifp - || !on_net(rt->rt_gate, + if (ifp != 0 + && on_net(rt->rt_gate, ifp->int_net, ifp->int_mask) - || rt->rt_gate != ifp->int_addr) - n->n_nhop = 0; - else + && rt->rt_gate != ifp->int_addr) n->n_nhop = rt->rt_gate; } } @@ -301,7 +305,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ } if (rip->rip_cmd == RIPCMD_TRACEON) { rip->rip_tracefile[size-4] = '\0'; - trace_on(rip->rip_tracefile, 0); + trace_on((char*)rip->rip_tracefile, 0); } else { trace_off("tracing turned off by %s\n", naddr_ntoa(FROM_NADDR)); @@ -387,20 +391,27 @@ input(struct sockaddr_in *from, /* received from this IP address */ return; } - /* Authenticate the packet. + /* Authenticate the packet if we have a secret. */ - if (ifp->int_passwd[0] != '\0' - && (n >= lim - || n->n_family != RIP_AF_AUTH - || ((struct netauth*)n)->a_type != RIP_AUTH_PW - || 0 != bcmp(((struct netauth*)n)->au.au_pw, - ifp->int_passwd, - sizeof(ifp->int_passwd)))) { - if (from->sin_addr.s_addr != use_auth) - msglog("missing authentication from %s", - naddr_ntoa(FROM_NADDR)); - use_auth = from->sin_addr.s_addr; - return; + if (ifp->int_passwd[0] != '\0') { + if (n >= lim + || n->n_family != RIP_AF_AUTH + || ((struct netauth*)n)->a_type != RIP_AUTH_PW) { + if (from->sin_addr.s_addr != use_auth) + msglog("missing password from %s", + naddr_ntoa(FROM_NADDR)); + use_auth = from->sin_addr.s_addr; + return; + + } else if (0 != bcmp(((struct netauth*)n)->au.au_pw, + ifp->int_passwd, + sizeof(ifp->int_passwd))) { + if (from->sin_addr.s_addr != use_auth) + msglog("bad password from %s", + naddr_ntoa(FROM_NADDR)); + use_auth = from->sin_addr.s_addr; + return; + } } for (; n < lim; n++) { @@ -527,15 +538,16 @@ input(struct sockaddr_in *from, /* received from this IP address */ || !(rt->rt_state & RS_NET_SYN)))) { ddst_h = v1_mask & -v1_mask; i = (v1_mask & ~mask)/ddst_h; - if (i >= 1024) { + if (i >= 511) { /* Punt if we would have to generate * an unreasonable number of routes. */ #ifdef DEBUG - msglog("accept %s from %s as-is" - " instead of as %d routes", + msglog("accept %s from %s as 1" + " instead of %d routes", addrname(dst,mask,0), - naddr_ntoa(FROM_NADDR), i); + naddr_ntoa(FROM_NADDR), + i+1); #endif i = 0; } else { @@ -598,7 +610,9 @@ input_route(struct interface *ifp, if (n->n_metric == HOPCNT_INFINITY) return; - rtadd(dst, mask, gate, from, n->n_metric, n->n_tag, 0, ifp); + if (total_routes < MAX_ROUTES) + rtadd(dst, mask, gate, from, n->n_metric, + n->n_tag, 0, ifp); return; } @@ -639,11 +653,12 @@ input_route(struct interface *ifp, */ int old_metric = rts->rts_metric; - /* Keep poisoned routes around only long - * enough to pass the poison on. + /* Keep poisoned routes around only long enough to pass + * the poison on. Get a new timestamp for good routes. */ - if (old_metric < HOPCNT_INFINITY) - new_time = now.tv_sec; + new_time =((old_metric == HOPCNT_INFINITY) + ? rts->rts_time + : now.tv_sec); /* If this is an update for the router we currently prefer, * then note it. diff --git a/usr.sbin/routed/main.c b/usr.sbin/routed/main.c index 20b72d8..b96fe71 100644 --- a/usr.sbin/routed/main.c +++ b/usr.sbin/routed/main.c @@ -34,9 +34,12 @@ char copyright[] = "@(#) Copyright (c) 1983, 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; -#if !defined(lint) && !defined(sgi) +#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93"; -#endif /* not lint */ +#elif defined(__NetBSD__) +static char rcsid[] = "$NetBSD$"; +#endif +#ident "$Revision: 1.1.3.3 $" #include "defs.h" #include "pathnames.h" @@ -272,14 +275,7 @@ usage: if (setsockopt(rt_sock, SOL_SOCKET,SO_USELOOPBACK, &off,sizeof(off)) < 0) LOGERR("setsockopt(SO_USELOOPBACK,0)"); - - /* prepare Router Discovery socket. - */ - rdisc_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); - if (rdisc_sock < 0) - BADERR(1,"rdisc_sock = socket()"); - fix_sock(rdisc_sock,"rdisc_sock"); - + fix_select(); @@ -733,6 +729,19 @@ rip_on(struct interface *ifp) } +/* die if malloc(3) fails + */ +void * +rtmalloc(size_t size, + char *msg) +{ + void *p = malloc(size); + if (p == 0) + logbad(1,"malloc() failed in %s", msg); + return p; +} + + /* get a random instant in an interval */ void diff --git a/usr.sbin/routed/output.c b/usr.sbin/routed/output.c index 3ae284f..5f646d8 100644 --- a/usr.sbin/routed/output.c +++ b/usr.sbin/routed/output.c @@ -31,9 +31,12 @@ * SUCH DAMAGE. */ -#if !defined(lint) && !defined(sgi) +#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93"; -#endif /* not lint */ +#elif defined(__NetBSD__) +static char rcsid[] = "$NetBSD$"; +#endif +#ident "$Revision: 1.1.3.3 $" #include "defs.h" @@ -59,6 +62,7 @@ struct { } v12, v2; char metric; /* adjust metrics by interface */ int npackets; + int gen_limit; u_int state; #define WS_ST_FLASH 0x001 /* send only changed routes */ #define WS_ST_RIP2_SAFE 0x002 /* send RIPv2 safe for RIPv1 */ @@ -168,6 +172,10 @@ output(enum output_type type, } sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP); } + + case NO_OUT_MULTICAST: + case NO_OUT_RIPV2: + break; } trace_rip(msg, "to", &sin, ifp, buf, size); @@ -295,20 +303,22 @@ supply_out(struct ag_info *ag) ddst_h = v1_mask & -v1_mask; i = (v1_mask & ~mask)/ddst_h; - if (i >= 1024) { + if (i > ws.gen_limit) { /* Punt if we would have to generate an * unreasonable number of routes. */ #ifdef DEBUG - msglog("sending %s to %s as-is instead" - " of as %d routes", - addrname(htonl(dst_h),mask,0), - naddr_ntoa(ws.to.sin_addr.s_addr), i); + msglog("sending %s to %s as 1 instead" + " of %d routes", + addrname(htonl(dst_h),mask,1), + naddr_ntoa(ws.to.sin_addr.s_addr), + i+1); #endif i = 0; } else { mask = v1_mask; + ws.gen_limit -= i; } } } @@ -537,6 +547,7 @@ supply(struct sockaddr_in *dst, ws.state = 0; + ws.gen_limit = 1024; ws.to = *dst; ws.to_std_mask = std_mask(ws.to.sin_addr.s_addr); diff --git a/usr.sbin/routed/pathnames.h b/usr.sbin/routed/pathnames.h index d539eb5..e9e6c48 100644 --- a/usr.sbin/routed/pathnames.h +++ b/usr.sbin/routed/pathnames.h @@ -31,6 +31,8 @@ * SUCH DAMAGE. * * @(#)pathnames.h 8.1 (Berkeley) 6/5/93 + * + * $NetBSD$ */ #include <paths.h> diff --git a/usr.sbin/routed/rdisc.c b/usr.sbin/routed/rdisc.c index f4cb219..489da11 100644 --- a/usr.sbin/routed/rdisc.c +++ b/usr.sbin/routed/rdisc.c @@ -31,10 +31,12 @@ * SUCH DAMAGE. */ -#if !defined(lint) && !defined(sgi) -static const char rcsid[] = - "$Id: rdisc.c,v 1.2 1996/06/15 17:10:27 wollman Exp $"; -#endif /* not lint */ +#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) +static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95"; +#elif defined(__NetBSD__) +static char rcsid[] = "$NetBSD$"; +#endif +#ident "$Revision: 1.1.3.3 $" #include "defs.h" #include <netinet/in_systm.h> @@ -43,12 +45,12 @@ static const char rcsid[] = /* router advertisement ICMP packet */ struct icmp_ad { - u_char icmp_type; /* type of message */ - u_char icmp_code; /* type sub code */ - u_short icmp_cksum; /* ones complement cksum of struct */ - u_char icmp_ad_num; /* # of following router addresses */ - u_char icmp_ad_asize; /* 2--words in each advertisement */ - u_short icmp_ad_life; /* seconds of validity */ + u_int8_t icmp_type; /* type of message */ + u_int8_t icmp_code; /* type sub code */ + u_int16_t icmp_cksum; /* ones complement cksum of struct */ + u_int8_t icmp_ad_num; /* # of following router addresses */ + u_int8_t icmp_ad_asize; /* 2--words in each advertisement */ + u_int16_t icmp_ad_life; /* seconds of validity */ struct icmp_ad_info { n_long icmp_ad_addr; n_long icmp_ad_pref; @@ -57,10 +59,10 @@ struct icmp_ad { /* router solicitation ICMP packet */ struct icmp_so { - u_char icmp_type; /* type of message */ - u_char icmp_code; /* type sub code */ - u_short icmp_cksum; /* ones complement cksum of struct */ - n_long icmp_so_rsvd; + u_int8_t icmp_type; /* type of message */ + u_int8_t icmp_code; /* type sub code */ + u_int16_t icmp_cksum; /* ones complement cksum of struct */ + n_long icmp_so_rsvd; }; union ad_u { @@ -126,7 +128,7 @@ trace_rdisc(char *act, lim = &wp[(len - sizeof(p->ad)) / sizeof(*wp)]; for (i = 0; i < p->ad.icmp_ad_num && wp <= lim; i++) { (void)fprintf(ftrace, "\t%s preference=%#x", - naddr_ntoa(wp[0]), ntohl(wp[1])); + naddr_ntoa(wp[0]), (int)ntohl(wp[1])); wp += p->ad.icmp_ad_asize; } (void)fputc('\n',ftrace); @@ -140,6 +142,20 @@ trace_rdisc(char *act, } } +/* prepare Router Discovery socket. + */ +static void +get_rdisc_sock(void) +{ + if (rdisc_sock < 0) { + rdisc_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (rdisc_sock < 0) + BADERR(1,"rdisc_sock = socket()"); + fix_sock(rdisc_sock,"rdisc_sock"); + fix_select(); + } +} + /* Pick multicast group for router-discovery socket */ @@ -148,8 +164,17 @@ set_rdisc_mg(struct interface *ifp, int on) { /* 0=turn it off */ struct ip_mreq m; - if (rdisc_sock == -1 - || !(ifp->int_if_flags & IFF_MULTICAST) + if (rdisc_sock < 0) { + /* Create the raw socket so that we can hear at least + * broadcast router discovery packets. + */ + if ((ifp->int_state & IS_NO_RDISC) == IS_NO_RDISC + || !on) + return; + get_rdisc_sock(); + } + + if (!(ifp->int_if_flags & IFF_MULTICAST) || (ifp->int_state & IS_ALIAS)) { ifp->int_state &= ~(IS_ALL_HOSTS | IS_ALL_ROUTERS); return; @@ -166,7 +191,8 @@ set_rdisc_mg(struct interface *ifp, if (supplier || (ifp->int_state & IS_NO_ADV_IN) || !on) { - /* stop listening to advertisements */ + /* stop listening to advertisements + */ if (ifp->int_state & IS_ALL_HOSTS) { m.imr_multiaddr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); if (setsockopt(rdisc_sock, IPPROTO_IP, @@ -177,7 +203,8 @@ set_rdisc_mg(struct interface *ifp, } } else if (!(ifp->int_state & IS_ALL_HOSTS)) { - /* start listening to advertisements */ + /* start listening to advertisements + */ m.imr_multiaddr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0) { @@ -190,7 +217,8 @@ set_rdisc_mg(struct interface *ifp, if (!supplier || (ifp->int_state & IS_NO_ADV_OUT) || !on) { - /* stop listening to solicitations */ + /* stop listening to solicitations + */ if (ifp->int_state & IS_ALL_ROUTERS) { m.imr_multiaddr.s_addr=htonl(INADDR_ALLROUTERS_GROUP); if (setsockopt(rdisc_sock, IPPROTO_IP, @@ -201,7 +229,8 @@ set_rdisc_mg(struct interface *ifp, } } else if (!(ifp->int_state & IS_ALL_ROUTERS)) { - /* start hearing solicitations */ + /* start hearing solicitations + */ m.imr_multiaddr.s_addr=htonl(INADDR_ALLROUTERS_GROUP); if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0) { @@ -540,12 +569,12 @@ parse_ad(naddr from, /* ignore pointers to ourself and routes via unreachable networks */ if (ifwithaddr(gate, 1, 0) != 0) { - trace_pkt("\tdiscard our own Router Discovery Ad\n"); + trace_pkt("\tdiscard Router Discovery Ad pointing at us\n"); return; } if (!on_net(gate, ifp->int_net, ifp->int_mask)) { trace_pkt("\tdiscard Router Discovery Ad" - " from unreachable net\n"); + " toward unreachable net\n"); return; } @@ -553,7 +582,7 @@ parse_ad(naddr from, * and later bias it by the metric of the interface. */ pref = ntohl(pref) ^ MIN_PreferenceLevel; - + if (pref == 0 || life == 0) { pref = 0; life = 0; @@ -656,6 +685,10 @@ send_rdisc(union ad_u *p, bzero(&sin, sizeof(sin)); sin.sin_addr.s_addr = dst; + sin.sin_family = AF_INET; +#ifdef _HAVE_SIN_LEN + sin.sin_len = sizeof(sin); +#endif flags = MSG_DONTROUTE; switch (type) { @@ -710,6 +743,9 @@ send_rdisc(union ad_u *p, break; } + if (rdisc_sock < 0) + get_rdisc_sock(); + trace_rdisc(msg, ifp->int_addr, sin.sin_addr.s_addr, ifp, p, p_size); diff --git a/usr.sbin/routed/rtquery/Makefile b/usr.sbin/routed/rtquery/Makefile index dd2419b..e748e73 100644 --- a/usr.sbin/routed/rtquery/Makefile +++ b/usr.sbin/routed/rtquery/Makefile @@ -1,6 +1,8 @@ -# @(#)Makefile 8.1 (Berkeley) 6/5/93 +# From: @(#)Makefile 8.1 (Berkeley) 6/5/93 +# $Id$ PROG= rtquery MAN8= rtquery.8 +#COPTS= -g -DDEBUG -Wall .include <bsd.prog.mk> diff --git a/usr.sbin/routed/table.c b/usr.sbin/routed/table.c index c181be4..aa7510c 100644 --- a/usr.sbin/routed/table.c +++ b/usr.sbin/routed/table.c @@ -31,9 +31,12 @@ * SUCH DAMAGE. */ -#if !defined(lint) && !defined(sgi) +#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) static char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93"; -#endif /* not lint */ +#elif defined(__NetBSD__) +static char rcsid[] = "$NetBSD$"; +#endif +#ident "$Revision: 1.1.3.3 $" #include "defs.h" @@ -52,6 +55,8 @@ struct timeval need_kern = { /* need to update kernel table */ int stopint; +int total_routes; + naddr age_bad_gate; @@ -724,12 +729,12 @@ static struct khash { u_short k_state; #define KS_NEW 0x001 #define KS_DELETE 0x002 -#define KS_ADD 0x004 -#define KS_CHANGE 0x008 -#define KS_DEL_ADD 0x010 -#define KS_STATIC 0x020 -#define KS_GATEWAY 0x040 -#define KS_DYNAMIC 0x080 +#define KS_ADD 0x004 /* add to the kernel */ +#define KS_CHANGE 0x008 /* tell kernel to change the route */ +#define KS_DEL_ADD 0x010 /* delete & add to change the kernel */ +#define KS_STATIC 0x020 /* Static flag in kernel */ +#define KS_GATEWAY 0x040 /* G flag in kernel */ +#define KS_DYNAMIC 0x080 /* result of redirect */ #define KS_DELETED 0x100 /* already deleted */ time_t k_keep; #define K_KEEP_LIM 30 @@ -767,7 +772,6 @@ kern_add(naddr dst, naddr mask) k->k_dst = dst; k->k_mask = mask; k->k_state = KS_NEW; - k->k_redirect_time = now.tv_sec; k->k_keep = now.tv_sec; *pk = k; @@ -775,8 +779,8 @@ kern_add(naddr dst, naddr mask) } -/* If it has a non-zero metric, check that it is still in the table, not - * having been deleted by interfaces coming and going. +/* If a kernel route has a non-zero metric, check that it is still in the + * daemon table, and not deleted by interfaces coming and going. */ static void kern_check_static(struct khash *k, @@ -846,22 +850,25 @@ rtm_add(struct rt_msghdr *rtm, k->k_state |= KS_GATEWAY; if (rtm->rtm_flags & RTF_STATIC) k->k_state |= KS_STATIC; - if (rtm->rtm_flags & RTF_DYNAMIC) { - k->k_state |= KS_DYNAMIC; - k->k_redirect_time = now.tv_sec; - /* Routers are not supposed to listen to redirects, - * so delete it. - */ + if (0 != (rtm->rtm_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { if (supplier) { - k->k_keep = now.tv_sec; + /* Routers are not supposed to listen to redirects, + * so delete it. + */ + k->k_state &= ~KS_DYNAMIC; + k->k_state |= KS_DELETE; trace_act("mark redirected %s --> %s for deletion" - "since this is a router\n", + " since this is a router\n", addrname(k->k_dst, k->k_mask, 0), naddr_ntoa(k->k_gate)); + } else { + k->k_state |= KS_DYNAMIC; + k->k_redirect_time = now.tv_sec; } } - /* If it is not a static route, quite until it is time to delete it. + /* If it is not a static route, quit until the next comparison + * between the kernel and daemon tables, when it will be deleted. */ if (!(k->k_state & KS_STATIC)) { k->k_state |= KS_DELETE; @@ -876,7 +883,8 @@ rtm_add(struct rt_msghdr *rtm, */ ifp = iflookup(k->k_gate); if (ifp == 0) { - /* if there is no interface, maybe it is new + /* if there is no known interface, + * maybe there is a new interface */ ifinit(); ifp = iflookup(k->k_gate); @@ -1096,11 +1104,11 @@ read_rt(void) ? HOST_MASK : std_mask(S_ADDR(INFO_DST(&info)))); - strp += sprintf(strp, " %s", + strp += sprintf(strp, ": %s", addrname(S_ADDR(INFO_DST(&info)), mask, 0)); if (IN_MULTICAST(ntohl(S_ADDR(INFO_DST(&info))))) { - trace_act("ignore %s for multicast %s\n", str); + trace_act("ignore multicast %s\n", str); continue; } @@ -1161,11 +1169,13 @@ kern_out(struct ag_info *ag) * This includes routes that had RS_NET_SYN for interfaces that * recently died. */ - if (ag->ag_metric == HOPCNT_INFINITY - && 0 == kern_find(htonl(ag->ag_dst_h), ag->ag_mask, 0)) - return; - - k = kern_add(htonl(ag->ag_dst_h), ag->ag_mask); + if (ag->ag_metric == HOPCNT_INFINITY) { + k = kern_find(htonl(ag->ag_dst_h), ag->ag_mask, 0); + if (k == 0) + return; + } else { + k = kern_add(htonl(ag->ag_dst_h), ag->ag_mask); + } if (k->k_state & KS_NEW) { /* will need to add new entry to the kernel table */ @@ -1181,7 +1191,6 @@ kern_out(struct ag_info *ag) return; /* modify existing kernel entry if necessary */ - k->k_state &= ~KS_DELETE; if (k->k_gate != ag->ag_gate || k->k_metric != ag->ag_metric) { k->k_gate = ag->ag_gate; @@ -1203,6 +1212,16 @@ kern_out(struct ag_info *ag) k->k_state |= KS_GATEWAY; k->k_state |= (KS_ADD | KS_DEL_ADD); } + + /* Deleting-and-adding is necessary to change aspects of a route. + * Just delete instead of deleting and then adding a bad route. + * Otherwise, we want to keep the route in the kernel. + */ + if (k->k_metric == HOPCNT_INFINITY + && (k->k_state & KS_DEL_ADD)) + k->k_state |= KS_DELETE; + else + k->k_state &= ~KS_DELETE; #undef RT } @@ -1296,31 +1315,40 @@ fix_kern(void) continue; } - if (k->k_state & KS_DELETE) { + if ((k->k_state & (KS_DELETE | KS_DYNAMIC)) + == KS_DELETE) { if (!(k->k_state & KS_DELETED)) rtioctl(RTM_DELETE, - k->k_dst,k->k_gate, - k->k_mask, 0, 0); + k->k_dst, k->k_gate, k->k_mask, + 0, 0); *pk = k->k_next; free(k); continue; } - if (k->k_state & KS_DEL_ADD) - rtioctl(RTM_DELETE, - k->k_dst,k->k_gate,k->k_mask, 0, 0); - - flags = (k->k_state & KS_GATEWAY) ? RTF_GATEWAY : 0; - if (k->k_state & KS_ADD) { - rtioctl(RTM_ADD, - k->k_dst, k->k_gate, k->k_mask, - k->k_metric, flags); - } else if (k->k_state & KS_CHANGE) { - rtioctl(RTM_CHANGE, - k->k_dst,k->k_gate,k->k_mask, - k->k_metric, flags); + if (0 != (k->k_state&(KS_ADD|KS_CHANGE|KS_DEL_ADD))) { + if (k->k_state & KS_DEL_ADD) { + rtioctl(RTM_DELETE, + k->k_dst,k->k_gate,k->k_mask, + 0, 0); + k->k_state &= ~KS_DYNAMIC; + } + + flags = 0; + if (0 != (k->k_state&(KS_GATEWAY|KS_DYNAMIC))) + flags |= RTF_GATEWAY; + + if (k->k_state & KS_ADD) { + rtioctl(RTM_ADD, + k->k_dst, k->k_gate, k->k_mask, + k->k_metric, flags); + } else if (k->k_state & KS_CHANGE) { + rtioctl(RTM_CHANGE, + k->k_dst,k->k_gate,k->k_mask, + k->k_metric, flags); + } + k->k_state &= ~(KS_ADD|KS_CHANGE|KS_DEL_ADD); } - k->k_state &= ~(KS_ADD | KS_CHANGE | KS_DEL_ADD); /* Mark this route to be deleted in the next cycle. * This deletes routes that disappear from the @@ -1354,7 +1382,7 @@ del_static(naddr dst, */ k = kern_find(dst, mask, 0); if (k != 0) { - k->k_state &= ~KS_STATIC; + k->k_state &= ~(KS_STATIC | KS_DYNAMIC); k->k_state |= KS_DELETE; if (gone) { k->k_state |= KS_DELETED; @@ -1368,8 +1396,8 @@ del_static(naddr dst, } -/* Delete all routes generated from ICMP Redirects that use a given - * gateway, as well as all old redirected routes. +/* Delete all routes generated from ICMP Redirects that use a given gateway, + * as well as old redirected routes. */ void del_redirects(naddr bad_gate, @@ -1391,6 +1419,7 @@ del_redirects(naddr bad_gate, continue; k->k_state |= KS_DELETE; + k->k_state &= ~KS_DYNAMIC; need_kern.tv_sec = now.tv_sec; trace_act("mark redirected %s --> %s for deletion\n", addrname(k->k_dst, k->k_mask, 0), @@ -1492,11 +1521,7 @@ rtadd(naddr dst, int i; struct rt_spare *rts; - rt = (struct rt_entry *)malloc(sizeof (*rt)); - if (rt == 0) { - BADERR(1,"rtadd malloc"); - return; - } + rt = (struct rt_entry *)rtmalloc(sizeof (*rt), "rtadd"); bzero(rt, sizeof(*rt)); for (rts = rt->rt_spares, i = NUM_SPARES; i != 0; i--, rts++) rts->rts_metric = HOPCNT_INFINITY; @@ -1525,6 +1550,8 @@ rtadd(naddr dst, rt->rt_ifp = ifp; rt->rt_seqno = update_seqno; + if (++total_routes == MAX_ROUTES) + msglog("have maximum (%d) routes", total_routes); if (TRACEACTIONS) trace_add_del("Add", rt); @@ -1672,6 +1699,7 @@ rtdelete(struct rt_entry *rt) msglog("rnh_deladdr() failed"); } else { free(rt); + total_routes--; } } @@ -1752,7 +1780,7 @@ rtbad_sub(struct rt_entry *rt) if (ifp1 != 0 || (state & RS_NET_SYN)) { rtchange(rt, ((rt->rt_state & ~(RS_NET_SYN | RS_LOCAL)) | state), - rt->rt_gate, rt->rt_router, 1, + rt->rt_gate, rt->rt_router, rt->rt_metric, rt->rt_tag, ifp1, rt->rt_time, 0); } else { rtbad(rt); diff --git a/usr.sbin/routed/trace.c b/usr.sbin/routed/trace.c index 8c66a9f..f38b393 100644 --- a/usr.sbin/routed/trace.c +++ b/usr.sbin/routed/trace.c @@ -31,9 +31,12 @@ * SUCH DAMAGE. */ -#if !defined(lint) && !defined(sgi) +#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; -#endif /* not lint */ +#elif defined(__NetBSD__) +static char rcsid[] = "$NetBSD$"; +#endif +#ident "$Revision: 1.1.3.3 $" #define RIPCMDS #include "defs.h" @@ -63,17 +66,18 @@ char * naddr_ntoa(naddr a) { #define NUM_BUFS 4 - static int i; + static int bufno; static struct { char str[16]; /* xxx.xxx.xxx.xxx\0 */ } bufs[NUM_BUFS]; - struct in_addr addr; char *s; + struct in_addr addr; addr.s_addr = a; - s = strcpy(bufs[i].str, inet_ntoa(addr)); - i = (i+1) % NUM_BUFS; + s = strcpy(bufs[bufno].str, inet_ntoa(addr)); + bufno = (bufno+1) % NUM_BUFS; return s; +#undef NUM_BUFS } @@ -318,12 +322,17 @@ addrname(naddr addr, /* in network byte order */ naddr mask, int force) /* 0=show mask if nonstandard, */ { /* 1=always show mask, 2=never */ - static char s[15+20]; - char *sp; +#define NUM_BUFS 4 + static int bufno; + static struct { + char str[15+20]; + } bufs[NUM_BUFS]; + char *s, *sp; naddr dmask; int i; - (void)strcpy(s, naddr_ntoa(addr)); + s = strcpy(bufs[bufno].str, naddr_ntoa(addr)); + bufno = (bufno+1) % NUM_BUFS; if (force == 1 || (force == 0 && mask != std_mask(addr))) { sp = &s[strlen(s)]; @@ -335,11 +344,12 @@ addrname(naddr addr, /* in network byte order */ (void)sprintf(sp, "/%d", 32-i); } else { - (void)sprintf(sp, " (mask %#x)", mask); + (void)sprintf(sp, " (mask %#x)", (u_int)mask); } } return s; +#undef NUM_BUFS } @@ -448,7 +458,7 @@ trace_bits(struct bits *tbl, c = '|'; } - if (c || force) + if (c != '<' || force) (void)fputs("> ", ftrace); } @@ -477,12 +487,14 @@ trace_if(char *act, lastlog(); (void)fprintf(ftrace, "%s interface %-4s ", act, ifp->int_name); - (void)fprintf(ftrace, "%-15s --> %s ", + (void)fprintf(ftrace, "%-15s-->%-15s ", naddr_ntoa(ifp->int_addr), - ((ifp->int_if_flags & IFF_POINTOPOINT) - ? naddr_ntoa(ifp->int_dstaddr) - : addrname(htonl(ifp->int_net), ifp->int_mask, 0))); - (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); + addrname(htonl((ifp->int_if_flags & IFF_POINTOPOINT) + ? ifp->int_dstaddr + : ifp->int_net), + ifp->int_mask, 1)); + if (ifp->int_metric != 0) + (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); trace_bits(if_bits, ifp->int_if_flags, 0); trace_bits(is_bits, ifp->int_state, 0); (void)fputc('\n',ftrace); @@ -517,7 +529,7 @@ trace_upslot(struct rt_entry *rt, (void)fprintf(ftrace, "router=%s ", naddr_ntoa(rts->rts_gate)); if (rts->rts_tag != 0) - (void)fprintf(ftrace, "tag=%#x ", rts->rts_tag); + (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); if (rts->rts_ifp != 0) (void)fprintf(ftrace, "%s ", @@ -530,7 +542,7 @@ trace_upslot(struct rt_entry *rt, if (gate != router) (void)fprintf(ftrace,"router=%s ",naddr_ntoa(router)); if (tag != rts->rts_tag) - (void)fprintf(ftrace, "tag=%#x ", tag); + (void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); if (metric != rts->rts_metric) (void)fprintf(ftrace, "metric=%-2d ", metric); if (ifp != rts->rts_ifp && ifp != 0 ) @@ -546,7 +558,7 @@ trace_upslot(struct rt_entry *rt, if (gate != router) (void)fprintf(ftrace, "router=%s ", naddr_ntoa(gate)); if (tag != 0) - (void)fprintf(ftrace, "tag=%#x ", tag); + (void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); (void)fprintf(ftrace, "metric=%-2d ", metric); if (ifp != 0) (void)fprintf(ftrace, "%s ", ifp->int_name); @@ -618,7 +630,7 @@ trace_change(struct rt_entry *rt, (void)fprintf(ftrace, "router=%s ", naddr_ntoa(rt->rt_router)); if (rt->rt_tag != 0) - (void)fprintf(ftrace, "tag=%#x ", rt->rt_tag); + (void)fprintf(ftrace, "tag=%#x ", ntohs(rt->rt_tag)); trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); (void)fprintf(ftrace, "%s ", rt->rt_ifp == 0 ? "?" : rt->rt_ifp->int_name); @@ -633,7 +645,7 @@ trace_change(struct rt_entry *rt, if (router != gate) (void)fprintf(ftrace, "router=%s ", naddr_ntoa(router)); if (rt->rt_tag != tag) - (void)fprintf(ftrace, "tag=%#x ", tag); + (void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); if (rt->rt_state != state) trace_bits(rs_bits, state, 1); if (rt->rt_ifp != ifp) @@ -663,10 +675,10 @@ trace_add_del(char * action, struct rt_entry *rt) (void)fprintf(ftrace, "router=%s ", naddr_ntoa(rt->rt_router)); if (rt->rt_tag != 0) - (void)fprintf(ftrace, "tag=%#x ", rt->rt_tag); + (void)fprintf(ftrace, "tag=%#x ", ntohs(rt->rt_tag)); trace_bits(rs_bits, state, 0); - if (rt->rt_ifp != 0) - (void)fprintf(ftrace, "%s ", rt->rt_ifp->int_name); + (void)fprintf(ftrace, "%s ", + rt->rt_ifp != 0 ? rt->rt_ifp->int_name : "?"); (void)fprintf(ftrace, "%s\n", ts(rt->rt_time)); } @@ -688,12 +700,12 @@ trace_rip(char *dir1, char *dir2, lastlog(); if (msg->rip_cmd >= RIPCMD_MAX || msg->rip_vers == 0) { - (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s %s.%d%s%s" - " size=%d msg=%#x\n", + (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" + " %s.%d size=%d\n", dir1, msg->rip_vers, msg->rip_cmd, dir2, naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), - size, msg); + size); return; } @@ -721,13 +733,13 @@ trace_rip(char *dir1, char *dir2, naddr_ntoa(n->n_dst)); if (n->n_mask != 0) (void)fprintf(ftrace, "mask=%#x ", - ntohl(n->n_mask)); + (u_int)ntohl(n->n_mask)); if (n->n_nhop != 0) (void)fprintf(ftrace, " nhop=%s ", naddr_ntoa(n->n_nhop)); if (n->n_tag != 0) (void)fprintf(ftrace, "tag=%#x", - n->n_tag); + ntohs(n->n_tag)); (void)fputc('\n',ftrace); continue; } @@ -751,7 +763,7 @@ trace_rip(char *dir1, char *dir2, "\t(af %d) %-18s mask=%#x", ntohs(n->n_family), naddr_ntoa(n->n_dst), - ntohl(n->n_mask)); + (u_int)ntohl(n->n_mask)); } else if (msg->rip_vers == RIPv1) { (void)fprintf(ftrace, "\t%-18s ", addrname(n->n_dst, @@ -764,13 +776,13 @@ trace_rip(char *dir1, char *dir2, n->n_mask==0 ? 2 : 0)); } (void)fprintf(ftrace, "metric=%-2d ", - ntohl(n->n_metric)); + (u_int)ntohl(n->n_metric)); if (n->n_nhop != 0) (void)fprintf(ftrace, " nhop=%s ", naddr_ntoa(n->n_nhop)); if (n->n_tag != 0) (void)fprintf(ftrace, "tag=%#x", - n->n_tag); + ntohs(n->n_tag)); (void)fputc('\n',ftrace); } if (size != (char *)n - (char *)msg) |