diff options
author | markm <markm@FreeBSD.org> | 1999-05-02 13:14:16 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 1999-05-02 13:14:16 +0000 |
commit | c74fc4e83b599157005f6adfcfebde46851bd0d4 (patch) | |
tree | e8f3c95ddb4dcfbbc332816196635e042e72873b /sbin/routed/rdisc.c | |
parent | a60c9cfa3a8359247f7ca33b3ebc8574c5c7194a (diff) | |
download | FreeBSD-src-c74fc4e83b599157005f6adfcfebde46851bd0d4.zip FreeBSD-src-c74fc4e83b599157005f6adfcfebde46851bd0d4.tar.gz |
Merge-o-matic and add a bunch of $Id's
Diffstat (limited to 'sbin/routed/rdisc.c')
-rw-r--r-- | sbin/routed/rdisc.c | 166 |
1 files changed, 96 insertions, 70 deletions
diff --git a/sbin/routed/rdisc.c b/sbin/routed/rdisc.c index 89efd2c..4d54b33 100644 --- a/sbin/routed/rdisc.c +++ b/sbin/routed/rdisc.c @@ -11,7 +11,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: + * must display the following acknowledgment: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors @@ -29,21 +29,22 @@ * 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. + * + * $Id$ */ -#ifndef lint -#if 0 -static char sccsid[] = "@(#)rdisc.c 8.1 (Berkeley) x/y/95"; -#endif -static const char rcsid[] = - "$Id$"; -#endif /* not lint */ - #include "defs.h" #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> +#if !defined(sgi) && !defined(__NetBSD__) +static char sccsid[] __attribute__((unused)) = "@(#)rdisc.c 8.1 (Berkeley) x/y/95"; +#elif defined(__NetBSD__) +__RCSID"$NetBSD$"); +#endif +#ident "$Revision: 2.17 $" + /* router advertisement ICMP packet */ struct icmp_ad { u_int8_t icmp_type; /* type of message */ @@ -80,7 +81,7 @@ struct timeval rdisc_timer; int rdisc_ok; /* using solicited route */ -#define MAX_ADS 5 +#define MAX_ADS 16 /* at least one per interface */ struct dr { /* accumulated advertisements */ struct interface *dr_ifp; naddr dr_gate; /* gateway */ @@ -90,8 +91,13 @@ struct dr { /* accumulated advertisements */ n_long dr_pref; /* preference adjusted by metric */ } *cur_drp, drs[MAX_ADS]; -/* adjust preference by interface metric without driving it to infinity */ -#define PREF(p, ifp) ((p) <= (ifp)->int_metric ? ((p) != 0 ? 1 : 0) \ +/* convert between signed, balanced around zero, + * and unsigned zero-based preferences */ +#define SIGN_PREF(p) ((p) ^ MIN_PreferenceLevel) +#define UNSIGN_PREF(p) SIGN_PREF(p) +/* adjust unsigned preference by interface metric, + * without driving it to infinity */ +#define PREF(p, ifp) ((int)(p) <= (ifp)->int_metric ? ((p) != 0 ? 1 : 0) \ : (p) - ((ifp)->int_metric)) static void rdisc_sort(void); @@ -100,7 +106,7 @@ static void rdisc_sort(void); /* dump an ICMP Router Discovery Advertisement Message */ static void -trace_rdisc(char *act, +trace_rdisc(const char *act, naddr from, naddr to, struct interface *ifp, @@ -138,7 +144,7 @@ trace_rdisc(char *act, trace_act("%s Router Solic. from %s to %s via %s value=%#x", act, naddr_ntoa(from), naddr_ntoa(to), ifp ? ifp->int_name : "?", - ntohl(p->so.icmp_so_rsvd)); + (int)ntohl(p->so.icmp_so_rsvd)); } } @@ -184,7 +190,7 @@ set_rdisc_mg(struct interface *ifp, if (ifp->int_if_flags & IFF_POINTOPOINT) return; #endif - bzero(&m, sizeof(m)); + memset(&m, 0, sizeof(m)); m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT) ? ifp->int_dstaddr : ifp->int_addr); @@ -297,7 +303,7 @@ rdisc_age(naddr bad_gate) /* If only advertising, then do only that. */ if (supplier) { - /* if switching from client to server, get rid of old + /* If switching from client to server, get rid of old * default routes. */ if (cur_drp != 0) @@ -337,14 +343,17 @@ rdisc_age(naddr bad_gate) } } - /* delete old redirected routes to keep the kernel table small - */ - sec = (cur_drp == 0) ? MaxMaxAdvertiseInterval : cur_drp->dr_life; - del_redirects(bad_gate, now.tv_sec-sec); - rdisc_sol(); - rdisc_sort(); + + /* Delete old redirected routes to keep the kernel table small, + * and to prevent black holes. Check that the kernel table + * matches the daemon table (i.e. has the default route). + * But only if RIP is not running and we are not dealing with + * a bad gateway, since otherwise age() will be called. + */ + if (rip_sock < 0 && bad_gate == 0) + age(0); } @@ -360,10 +369,12 @@ if_bad_rdisc(struct interface *ifp) if (drp->dr_ifp != ifp) continue; drp->dr_recv_pref = 0; + drp->dr_ts = 0; drp->dr_life = 0; } - rdisc_sort(); + /* make a note to re-solicit, turn RIP on or off, etc. */ + rdisc_timer.tv_sec = 0; } @@ -389,10 +400,11 @@ static void del_rdisc(struct dr *drp) { struct interface *ifp; + naddr gate; int i; - del_redirects(drp->dr_gate, 0); + del_redirects(gate = drp->dr_gate, 0); drp->dr_ts = 0; drp->dr_life = 0; @@ -411,13 +423,21 @@ del_rdisc(struct dr *drp) * then solicit a new one. * This is contrary to RFC 1256, but defends against black holes. */ - if (i == 0 - && ifp->int_rdisc_cnt >= MAX_SOLICITATIONS) { - trace_act("discovered route is bad--re-solicit routers via %s", - ifp->int_name); + if (i != 0) { + trace_act("discovered router %s via %s" + " is bad--have %d remaining", + naddr_ntoa(gate), ifp->int_name, i); + } else if (ifp->int_rdisc_cnt >= MAX_SOLICITATIONS) { + trace_act("last discovered router %s via %s" + " is bad--re-solicit", + naddr_ntoa(gate), ifp->int_name); ifp->int_rdisc_cnt = 0; ifp->int_rdisc_timer.tv_sec = 0; rdisc_sol(); + } else { + trace_act("last discovered router %s via %s" + " is bad--wait to solicit", + naddr_ntoa(gate), ifp->int_name); } } @@ -430,9 +450,10 @@ rdisc_sort(void) { struct dr *drp, *new_drp; struct rt_entry *rt; + struct rt_spare new; struct interface *ifp; - u_int new_st; - n_long new_pref; + u_int new_st = 0; + n_long new_pref = 0; /* Find the best discovered route. @@ -490,23 +511,20 @@ rdisc_sort(void) if (rt != 0 && (rt->rt_state & RS_RDISC)) { + new = rt->rt_spares[0]; + new.rts_metric = HOPCNT_INFINITY; + new.rts_time = now.tv_sec - GARBAGE_TIME; rtchange(rt, rt->rt_state & ~RS_RDISC, - rt->rt_gate, rt->rt_router, - HOPCNT_INFINITY, 0, rt->rt_ifp, - now.tv_sec - GARBAGE_TIME, 0); + &new, 0); rtswitch(rt, 0); } - /* turn on RIP if permitted */ - rip_on(0); - } else { if (cur_drp == 0) { trace_act("turn on Router Discovery client" " using %s via %s", naddr_ntoa(new_drp->dr_gate), new_drp->dr_ifp->int_name); - rdisc_ok = 1; } else { @@ -518,27 +536,28 @@ rdisc_sort(void) new_drp->dr_ifp->int_name); } + memset(&new, 0, sizeof(new)); + new.rts_ifp = new_drp->dr_ifp; + new.rts_gate = new_drp->dr_gate; + new.rts_router = new_drp->dr_gate; + new.rts_metric = HOPCNT_INFINITY-1; + new.rts_time = now.tv_sec; if (rt != 0) { - rtchange(rt, rt->rt_state | RS_RDISC, - new_drp->dr_gate, new_drp->dr_gate, - 0,0, new_drp->dr_ifp, - now.tv_sec, 0); + rtchange(rt, rt->rt_state | RS_RDISC, &new, 0); } else { - rtadd(RIP_DEFAULT, 0, - new_drp->dr_gate, new_drp->dr_gate, - HOPCNT_INFINITY-1, 0, - RS_RDISC, new_drp->dr_ifp); + rtadd(RIP_DEFAULT, 0, RS_RDISC, &new); } - - /* Now turn off RIP and delete RIP routes, - * which might otherwise include the default - * we just modified. - */ - rip_off(); } cur_drp = new_drp; } + + /* turn RIP on or off */ + if (!rdisc_ok || rip_interfaces > 1) { + rip_on(0); + } else { + rip_off(); + } } @@ -547,7 +566,7 @@ rdisc_sort(void) static void parse_ad(naddr from, naddr gate, - n_long pref, + n_long pref, /* signed and in network order */ u_short life, struct interface *ifp) { @@ -578,9 +597,9 @@ parse_ad(naddr from, /* Convert preference to an unsigned value * and later bias it by the metric of the interface. */ - pref = ntohl(pref) ^ MIN_PreferenceLevel; + pref = UNSIGN_PREF(ntohl(pref)); - if (pref == 0 || life == 0) { + if (pref == 0 || life < MinMaxAdvertiseInterval) { pref = 0; life = 0; } @@ -671,16 +690,16 @@ static void send_rdisc(union ad_u *p, int p_size, struct interface *ifp, - naddr dst, /* 0 or UNICAST destination */ + naddr dst, /* 0 or unicast destination */ int type) /* 0=unicast, 1=bcast, 2=mcast */ { struct sockaddr_in sin; int flags; - char *msg; + const char *msg; naddr tgt_mcast; - bzero(&sin, sizeof(sin)); + memset(&sin, 0, sizeof(sin)); sin.sin_addr.s_addr = dst; sin.sin_family = AF_INET; #ifdef _HAVE_SIN_LEN @@ -689,7 +708,7 @@ send_rdisc(union ad_u *p, flags = MSG_DONTROUTE; switch (type) { - case 0: /* UNICAST */ + case 0: /* unicast */ default: msg = "Send"; break; @@ -765,23 +784,27 @@ send_rdisc(union ad_u *p, */ static void send_adv(struct interface *ifp, - naddr dst, /* 0 or UNICAST destination */ + naddr dst, /* 0 or unicast destination */ int type) /* 0=unicast, 1=bcast, 2=mcast */ { union ad_u u; n_long pref; - bzero(&u,sizeof(u.ad)); + memset(&u, 0, sizeof(u.ad)); u.ad.icmp_type = ICMP_ROUTERADVERT; u.ad.icmp_ad_num = 1; u.ad.icmp_ad_asize = sizeof(u.ad.icmp_ad_info[0])/4; u.ad.icmp_ad_life = stopint ? 0 : htons(ifp->int_rdisc_int*3); - pref = ifp->int_rdisc_pref ^ MIN_PreferenceLevel; - pref = PREF(pref, ifp) ^ MIN_PreferenceLevel; - u.ad.icmp_ad_info[0].icmp_ad_pref = htonl(pref); + + /* Convert the configured preference to an unsigned value, + * bias it by the interface metric, and then send it as a + * signed, network byte order value. + */ + pref = UNSIGN_PREF(ifp->int_rdisc_pref); + u.ad.icmp_ad_info[0].icmp_ad_pref = htonl(SIGN_PREF(PREF(pref, ifp))); u.ad.icmp_ad_info[0].icmp_ad_addr = ifp->int_addr; @@ -851,7 +874,7 @@ rdisc_sol(void) continue; if (!timercmp(&ifp->int_rdisc_timer, &now, >)) { - bzero(&u,sizeof(u.so)); + memset(&u, 0, sizeof(u.so)); u.so.icmp_type = ICMP_ROUTERSOLICIT; u.so.icmp_cksum = in_cksum((u_short*)&u.so, sizeof(u.so)); @@ -875,14 +898,14 @@ rdisc_sol(void) /* check the IP header of a possible Router Discovery ICMP packet */ static struct interface * /* 0 if bad */ -ck_icmp(char *act, +ck_icmp(const char *act, naddr from, struct interface *ifp, naddr to, union ad_u *p, u_int len) { - char *type; + const char *type; if (p->icmp.icmp_type == ICMP_ROUTERADVERT) { @@ -988,7 +1011,7 @@ read_d(void) switch (p->icmp.icmp_type) { case ICMP_ROUTERADVERT: if (p->ad.icmp_ad_asize*4 - < sizeof(p->ad.icmp_ad_info[0])) { + < (int)sizeof(p->ad.icmp_ad_info[0])) { msglim(&bad_asize, from.sin_addr.s_addr, "intolerable rdisc address size=%d", p->ad.icmp_ad_asize); @@ -998,9 +1021,10 @@ read_d(void) trace_pkt(" empty?"); continue; } - if (cc != (sizeof(p->ad) - sizeof(p->ad.icmp_ad_info) - + (p->ad.icmp_ad_num - * sizeof(p->ad.icmp_ad_info[0])))) { + if (cc != (int)(sizeof(p->ad) + - sizeof(p->ad.icmp_ad_info) + + (p->ad.icmp_ad_num + * sizeof(p->ad.icmp_ad_info[0])))) { msglim(&bad_len, from.sin_addr.s_addr, "rdisc length %d does not match ad_num" " %d", cc, p->ad.icmp_ad_num); @@ -1027,6 +1051,8 @@ read_d(void) continue; if (ifp->int_state & IS_NO_ADV_OUT) continue; + if (stopint) + continue; /* XXX * We should handle messages from address 0. |