diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1997-07-30 23:28:59 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1997-07-30 23:28:59 +0000 |
commit | c8e8720d9608e1d404551392fa626de1242145cc (patch) | |
tree | 93650b27a6ea7ea404bf54a763998664b8899ff1 /sbin/routed/output.c | |
parent | 8f8968006824e23ac888c36b119b28a019d1faa2 (diff) |
new routed DOES NOT EVEN COMPILE LET ALONE WORK. TEST YOUR WORK!
Also, put back the damn security check in input.c that has been deleted
TWO SEPERATE TIMES NOW! I CURSE anyone who deletes that check again.
Diffstat (limited to 'sbin/routed/output.c')
-rw-r--r-- | sbin/routed/output.c | 463 |
1 files changed, 185 insertions, 278 deletions
diff --git a/sbin/routed/output.c b/sbin/routed/output.c index 7d74b07cba5..7c079a66f94 100644 --- a/sbin/routed/output.c +++ b/sbin/routed/output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: output.c,v 1.4 1997/07/30 22:24:43 mickey Exp $ */ +/* $OpenBSD: output.c,v 1.5 1997/07/30 23:28:43 deraadt Exp $ */ /* * Copyright (c) 1983, 1988, 1993 @@ -36,11 +36,10 @@ #if !defined(lint) static char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93"; #else -static char rcsid[] = "$OpenBSD: output.c,v 1.4 1997/07/30 22:24:43 mickey Exp $"; +static char rcsid[] = "$OpenBSD: output.c,v 1.5 1997/07/30 23:28:43 deraadt Exp $"; #endif #include "defs.h" -#include <md5.h> int update_seqno; @@ -55,45 +54,37 @@ struct { naddr to_std_mask; naddr to_std_net; struct interface *ifp; /* usually output interface */ - struct auth *a; + struct ws_buf { /* info for each buffer */ + struct rip *buf; + struct netinfo *n; + struct netinfo *base; + struct netinfo *lim; + enum output_type type; + } 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_ALL 0x002 /* send full featured RIPv2 */ -#define WS_ST_AG 0x004 /* ok to aggregate subnets */ -#define WS_ST_SUPER_AG 0x008 /* ok to aggregate networks */ -#define WS_ST_SUB_AG 0x010 /* aggregate subnets in odd case */ -#define WS_ST_QUERY 0x020 /* responding to a query */ -#define WS_ST_TO_ON_NET 0x040 /* sending onto one of our nets */ -#define WS_ST_DEFAULT 0x080 /* faking a default */ +#define WS_ST_RIP2_SAFE 0x002 /* send RIPv2 safe for RIPv1 */ +#define WS_ST_RIP2_ALL 0x004 /* send full featured RIPv2 */ +#define WS_ST_AG 0x008 /* ok to aggregate subnets */ +#define WS_ST_SUPER_AG 0x010 /* ok to aggregate networks */ +#define WS_ST_SUB_AG 0x020 /* aggregate subnets in odd case */ +#define WS_ST_QUERY 0x040 /* responding to a query */ +#define WS_ST_TO_ON_NET 0x080 /* sending onto one of our nets */ +#define WS_ST_DEFAULT 0x100 /* faking a default */ +#define WS_ST_PM_RDISC 0x200 /* poor-man's router discovery */ } ws; /* A buffer for what can be heard by both RIPv1 and RIPv2 listeners */ -struct ws_buf v12buf; union pkt_buf ripv12_buf; /* Another for only RIPv2 listeners */ -struct ws_buf v2buf; union pkt_buf rip_v2_buf; -void -bufinit(void) -{ - ripv12_buf.rip.rip_cmd = RIPCMD_RESPONSE; - v12buf.buf = &ripv12_buf.rip; - v12buf.base = &v12buf.buf->rip_nets[0]; - - rip_v2_buf.rip.rip_cmd = RIPCMD_RESPONSE; - rip_v2_buf.rip.rip_vers = RIPv2; - v2buf.buf = &rip_v2_buf.rip; - v2buf.base = &v2buf.buf->rip_nets[0]; -} - - /* Send the contents of the global buffer via the non-multicast socket */ int /* <0 on failure */ @@ -147,7 +138,7 @@ output(enum output_type type, msg = "Send pt-to-pt"; } else if (ifp->int_state & IS_DUP) { trace_act("abort multicast output via %s" - " with duplicate address", + " with duplicate address\n", ifp->int_name); return 0; } else { @@ -182,15 +173,10 @@ output(enum output_type type, } sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP); } - break; case NO_OUT_MULTICAST: case NO_OUT_RIPV2: - default: -#ifdef DEBUG - abort(); -#endif - return -1; + break; } trace_rip(msg, "to", &sin, ifp, buf, size); @@ -213,102 +199,23 @@ output(enum output_type type, } -/* Find the first key for a packet to send. - * Try for a key that is eligable and has not expired, but settle for - * the last key if they have all expired. - * If no key is ready yet, give up. +/* install authentication if appropriate */ -struct auth * -find_auth(struct interface *ifp) -{ - struct auth *ap, *res; - int i; - - - if (ifp == 0) - return 0; - - res = 0; - ap = ifp->int_auth; - for (i = 0; i < MAX_AUTH_KEYS; i++, ap++) { - /* stop looking after the last key */ - if (ap->type == RIP_AUTH_NONE) - break; - - /* ignore keys that are not ready yet */ - if ((u_long)ap->start > (u_long)clk.tv_sec) - continue; - - if ((u_long)ap->end < (u_long)clk.tv_sec) { - /* note best expired password as a fall-back */ - if (res == 0 || (u_long)ap->end > (u_long)res->end) - res = ap; - continue; - } - - /* note key with the best future */ - if (res == 0 || (u_long)res->end < (u_long)ap->end) - res = ap; - } - return res; -} - - -void -clr_ws_buf(struct ws_buf *wb, - struct auth *ap) +static void +set_auth(struct ws_buf *w) { - struct netauth *na; - - wb->lim = wb->base + NETS_LEN; - wb->n = wb->base; - bzero(wb->n, NETS_LEN*sizeof(*wb->n)); - - /* install authentication if appropriate - */ - if (ap == 0) - return; - na = (struct netauth*)wb->n; - if (ap->type == RIP_AUTH_PW) { - na->a_family = RIP_AF_AUTH; - na->a_type = RIP_AUTH_PW; - bcopy(ap->key, na->au.au_pw, sizeof(na->au.au_pw)); - wb->n++; - - } else if (ap->type == RIP_AUTH_MD5) { - na->a_family = RIP_AF_AUTH; - na->a_type = RIP_AUTH_MD5; - na->au.a_md5.md5_keyid = ap->keyid; - na->au.a_md5.md5_auth_len = RIP_AUTH_PW_LEN; - na->au.a_md5.md5_seqno = clk.tv_sec; - wb->n++; - wb->lim--; /* make room for trailer */ + if (ws.ifp != 0 + && ws.ifp->int_passwd[0] != '\0' + && (ws.state & WS_ST_RIP2_SAFE)) { + w->n->n_family = RIP_AF_AUTH; + ((struct netauth*)w->n)->a_type = RIP_AUTH_PW; + bcopy(ws.ifp->int_passwd, ((struct netauth*)w->n)->au.au_pw, + sizeof(((struct netauth*)w->n)->au.au_pw)); + w->n++; } } -void -end_md5_auth(struct ws_buf *wb, - struct auth *ap) -{ - struct netauth *na, *na2; - MD5_CTX md5_ctx; - - - na = (struct netauth*)wb->base; - na2 = (struct netauth*)wb->n; - na2->a_family = RIP_AF_AUTH; - na2->a_type = 1; - bcopy(ap->key, na2->au.au_pw, sizeof(na2->au.au_pw)); - na->au.a_md5.md5_pkt_len = (char *)na2-(char *)(na+1); - MD5Init(&md5_ctx); - MD5Update(&md5_ctx, (u_char *)na, - (char *)(na2+1) - (char *)na); - MD5Final(na2->au.au_pw, &md5_ctx); - wb->n++; -} - - /* Send the buffer */ static void @@ -320,14 +227,12 @@ supply_write(struct ws_buf *wb) */ switch (wb->type) { case NO_OUT_MULTICAST: - trace_pkt("skip multicast to %s because impossible", + trace_pkt("skip multicast to %s because impossible\n", naddr_ntoa(ws.to.sin_addr.s_addr)); break; case NO_OUT_RIPV2: break; default: - if (ws.a != 0 && ws.a->type == RIP_AUTH_MD5) - end_md5_auth(wb,ws.a); if (output(wb->type, &ws.to, ws.ifp, wb->buf, ((char *)wb->n - (char*)wb->buf)) < 0 && ws.ifp != 0) @@ -336,7 +241,9 @@ supply_write(struct ws_buf *wb) break; } - clr_ws_buf(wb,ws.a); + bzero(wb->n = wb->base, sizeof(*wb->n)*NETS_LEN); + if (wb->buf->rip_vers == RIPv2) + set_auth(wb); } @@ -346,7 +253,7 @@ static void supply_out(struct ag_info *ag) { int i; - naddr mask, v1_mask, dst_h, ddst_h = 0; + naddr mask, v1_mask, s_mask, dst_h, ddst_h; struct ws_buf *wb; @@ -366,6 +273,7 @@ supply_out(struct ag_info *ag) mask = ag->ag_mask; v1_mask = ripv1_mask_host(htonl(dst_h), (ws.state & WS_ST_TO_ON_NET) ? ws.ifp : 0); + s_mask = std_mask(htonl(dst_h)); i = 0; /* If we are sending RIPv2 packets that cannot (or must not) be @@ -373,16 +281,19 @@ supply_out(struct ag_info *ag) * Subnets (from other networks) can only be sent via multicast. * A pair of subnet routes might have been promoted so that they * are legal to send by RIPv1. - * If RIPv1 is off, use the multicast buffer. + * If RIPv1 is off, use the multicast buffer, unless this is the + * fake default route and it is acting as a poor-man's router- + * discovery mechanism. */ - if ((ws.state & WS_ST_RIP2_ALL) + if (((ws.state & WS_ST_RIP2_ALL) + && (dst_h != RIP_DEFAULT || !(ws.state & WS_ST_PM_RDISC))) || ((ag->ag_state & AGS_RIPV2) && v1_mask != mask)) { /* use the RIPv2-only buffer */ - wb = &v2buf; + wb = &ws.v2; } else { /* use the RIPv1-or-RIPv2 buffer */ - wb = &v12buf; + wb = &ws.v12; /* Convert supernet route into corresponding set of network * routes for RIPv1, but leave non-contiguous netmasks @@ -423,20 +334,18 @@ supply_out(struct ag_info *ag) ? HOPCNT_INFINITY : ag->ag_metric); HTONL(wb->n->n_metric); - /* Any non-zero bits in the supposedly unused RIPv1 fields - * cause the old `routed` to ignore the route. - * That means the mask and so forth cannot be sent - * in the hybrid RIPv1/RIPv2 mode. - */ - if (ws.state & WS_ST_RIP2_ALL) { + if (wb->buf->rip_vers == RIPv2) { if (ag->ag_nhop != 0 + && (ws.state & WS_ST_RIP2_SAFE) && ((ws.state & WS_ST_QUERY) || (ag->ag_nhop != ws.ifp->int_addr && on_net(ag->ag_nhop, ws.ifp->int_net, ws.ifp->int_mask)))) wb->n->n_nhop = ag->ag_nhop; - wb->n->n_mask = htonl(mask); + if ((ws.state & WS_ST_RIP2_ALL) + || mask != s_mask) + wb->n->n_mask = htonl(mask); wb->n->n_tag = ag->ag_tag; } dst_h += ddst_h; @@ -458,24 +367,22 @@ walk_supply(struct radix_node *rn, u_short ags; char metric, pref; naddr dst, nhop; - struct rt_spare *rts; - int i; - /* Do not advertise external remote interfaces or passive interfaces. + /* Do not advertise the loopback interface + * or external remote interfaces */ if ((RT->rt_state & RS_IF) && RT->rt_ifp != 0 - && (RT->rt_ifp->int_if_flags & IS_PASSIVE) + && ((RT->rt_ifp->int_if_flags & IFF_LOOPBACK) + || (RT->rt_ifp->int_state & IS_EXTERNAL)) && !(RT->rt_state & RS_MHOME)) return 0; /* If being quiet about our ability to forward, then - * do not say anything unless responding to a query, - * except about our main interface. + * do not say anything unless responding to a query. */ - if (!supplier && !(ws.state & WS_ST_QUERY) - && !(RT->rt_state & RS_MHOME)) + if (!supplier && !(ws.state & WS_ST_QUERY)) return 0; dst = RT->rt_dst; @@ -585,72 +492,51 @@ walk_supply(struct radix_node *rn, * forgotten. * * Include the routes for both ends of point-to-point interfaces - * among those suppressed by split-horizon, since the other side - * should knows them as well as we do. - * - * Notice spare routes with the same metric that we are about to - * advertise, to split the horizon on redunant, inactive paths. + * since the other side presumably knows them as well as we do. */ - if (ws.ifp != 0 + if (RT->rt_ifp == ws.ifp && ws.ifp != 0 && !(ws.state & WS_ST_QUERY) && (ws.state & WS_ST_TO_ON_NET) && (!(RT->rt_state & RS_IF) || ws.ifp->int_if_flags & IFF_POINTOPOINT)) { - for (rts = RT->rt_spares, i = NUM_SPARES; i != 0; i--, rts++) { - if (rts->rts_ifp == ws.ifp - && rts->rts_metric <= metric) - break; - } - if (i != 0) { - /* If we do not mark the route with AGS_SPLIT_HZ here, - * it will be poisoned-reverse, or advertised back - * toward its source with an infinite metric. - * If we have recently advertised the route with a - * better metric than we now have, then we should - * poison-reverse the route before suppressing it for - * split-horizon. - * - * In almost all cases, if there is no spare for the - * route then it is either old and dead or a brand - * new route. If it is brand new, there is no need - * for poison-reverse. If it is old and dead, it - * is already poisoned. - */ - if (RT->rt_poison_time < now_expire - || RT->rt_poison_metric >= metric - || RT->rt_spares[1].rts_gate == 0) { - ags |= AGS_SPLIT_HZ; - ags &= ~(AGS_PROMOTE | AGS_SUPPRESS); - } - metric = HOPCNT_INFINITY; + /* Poison-reverse the route instead of only not advertising it + * it is recently changed from some other route. + * In almost all cases, if there is no spare for the route + * then it is either old or a brand new route, and if it + * is brand new, there is no need for poison-reverse. + */ + metric = HOPCNT_INFINITY; + if (RT->rt_poison_time < now_expire + || RT->rt_spares[1].rts_gate ==0) { + ags |= AGS_SPLIT_HZ; + ags &= ~(AGS_PROMOTE | AGS_SUPPRESS); } } - /* Keep track of the best metric with which the - * route has been advertised recently. - */ - if (RT->rt_poison_metric >= metric - || RT->rt_poison_time < now_expire) { - RT->rt_poison_time = now.tv_sec; - RT->rt_poison_metric = metric; - } - /* Adjust the outgoing metric by the cost of the link. - * Avoid aggregation when a route is counting to infinity. - */ - pref = RT->rt_poison_metric + ws.metric; - metric += ws.metric; - - /* Do not advertise stable routes that will be ignored, - * unless we are answering a query. - * If the route recently was advertised with a metric that - * would have been less than infinity through this interface, - * we need to continue to advertise it in order to poison it. */ - if (metric >= HOPCNT_INFINITY) { - if (!(ws.state & WS_ST_QUERY) - && (pref >= HOPCNT_INFINITY - || RT->rt_poison_time < now_garbage)) + pref = metric + ws.metric; + if (pref < HOPCNT_INFINITY) { + /* Keep track of the best metric with which the + * route has been advertised recently. + */ + if (RT->rt_poison_metric >= metric + || RT->rt_poison_time < now_expire) { + RT->rt_poison_time = now.tv_sec; + RT->rt_poison_metric = metric; + } + metric = pref; + + } else { + /* Do not advertise stable routes that will be ignored, + * unless they are being held down and poisoned. If the + * route recently was advertised with a metric that would + * have been less than infinity through this interface, we + * need to continue to advertise it in order to poison it. + */ + pref = RT->rt_poison_metric + ws.metric; + if (pref >= HOPCNT_INFINITY + || RT->rt_poison_time < now_garbage ) return 0; metric = HOPCNT_INFINITY; @@ -671,11 +557,10 @@ supply(struct sockaddr_in *dst, struct interface *ifp, /* output interface */ enum output_type type, int flash, /* 1=flash update */ - int vers, /* RIP version */ - int passwd_ok) /* OK to include cleartext password */ + int vers) /* RIP version */ { + static int init = 1; struct rt_entry *rt; - int def_metric; ws.state = 0; @@ -714,79 +599,94 @@ supply(struct sockaddr_in *dst, ws.metric = ifp->int_metric+1; } + if (init) { + init = 0; + + bzero(&ripv12_buf, sizeof(ripv12_buf)); + ripv12_buf.rip.rip_cmd = RIPCMD_RESPONSE; + ws.v12.buf = &ripv12_buf.rip; + ws.v12.base = &ws.v12.buf->rip_nets[0]; + ws.v12.lim = ws.v12.base + NETS_LEN; + + bzero(&rip_v2_buf, sizeof(rip_v2_buf)); + rip_v2_buf.rip.rip_cmd = RIPCMD_RESPONSE; + rip_v2_buf.rip.rip_vers = RIPv2; + ws.v2.buf = &rip_v2_buf.rip; + ws.v2.base = &ws.v2.buf->rip_nets[0]; + ws.v2.lim = ws.v2.base + NETS_LEN; + } ripv12_buf.rip.rip_vers = vers; + ws.v12.n = ws.v12.base; + set_auth(&ws.v12); + ws.v2.n = ws.v2.base; + set_auth(&ws.v2); + switch (type) { case OUT_BROADCAST: - v2buf.type = ((ifp != 0 && (ifp->int_if_flags & IFF_MULTICAST)) + ws.v2.type = ((ws.ifp != 0 + && (ws.ifp->int_if_flags & IFF_MULTICAST)) ? OUT_MULTICAST : NO_OUT_MULTICAST); - v12buf.type = OUT_BROADCAST; + ws.v12.type = OUT_BROADCAST; break; case OUT_MULTICAST: - v2buf.type = ((ifp != 0 && (ifp->int_if_flags & IFF_MULTICAST)) + ws.v2.type = ((ws.ifp != 0 + && (ws.ifp->int_if_flags & IFF_MULTICAST)) ? OUT_MULTICAST : NO_OUT_MULTICAST); - v12buf.type = OUT_BROADCAST; + ws.v12.type = OUT_BROADCAST; break; case OUT_UNICAST: case OUT_QUERY: - v2buf.type = (vers == RIPv2) ? type : NO_OUT_RIPV2; - v12buf.type = type; + ws.v2.type = (vers == RIPv2) ? type : NO_OUT_RIPV2; + ws.v12.type = type; break; default: - v2buf.type = type; - v12buf.type = type; + ws.v2.type = type; + ws.v12.type = type; break; } if (vers == RIPv2) { + /* if asked to send RIPv2, send at least that which can + * be safely heard by RIPv1 listeners. + */ + ws.state |= WS_ST_RIP2_SAFE; + /* full RIPv2 only if cannot be heard by RIPv1 listeners */ if (type != OUT_BROADCAST) ws.state |= WS_ST_RIP2_ALL; if (!(ws.state & WS_ST_TO_ON_NET)) { ws.state |= (WS_ST_AG | WS_ST_SUPER_AG); - } else if (ifp == 0 || !(ifp->int_state & IS_NO_AG)) { + } else if (ws.ifp == 0 || !(ws.ifp->int_state & IS_NO_AG)) { ws.state |= WS_ST_AG; if (type != OUT_BROADCAST - && (ifp == 0 || !(ifp->int_state&IS_NO_SUPER_AG))) + && (ws.ifp == 0 + || !(ws.ifp->int_state & IS_NO_SUPER_AG))) ws.state |= WS_ST_SUPER_AG; } - } else if (ifp == 0 || !(ifp->int_state & IS_NO_AG)) { + } else if (ws.ifp == 0 || !(ws.ifp->int_state & IS_NO_AG)) { ws.state |= WS_ST_SUB_AG; } - ws.a = (vers == RIPv2) ? find_auth(ifp) : 0; - if (!passwd_ok && ws.a != 0 && ws.a->type == RIP_AUTH_PW) - ws.a = 0; - clr_ws_buf(&v12buf,ws.a); - clr_ws_buf(&v2buf,ws.a); - - /* Fake a default route if asked and if there is not already - * a better, real default route. - */ - if (supplier && (def_metric = ifp->int_d_metric) != 0) { - if (0 == (rt = rtget(RIP_DEFAULT, 0)) - || rt->rt_metric+ws.metric >= def_metric) { + if (supplier) { + /* Fake a default route if asked, and if there is not + * a better, real default route. + */ + if (ifp->int_d_metric != 0 + && (0 == (rt = rtget(RIP_DEFAULT, 0)) + || rt->rt_metric+ws.metric >= ifp->int_d_metric)) { ws.state |= WS_ST_DEFAULT; - ag_check(0, 0, 0, 0, def_metric, def_metric, + ag_check(0, 0, 0, 0, + ifp->int_d_metric,ifp->int_d_metric, 0, 0, 0, supply_out); - } else { - def_metric = rt->rt_metric+ws.metric; } - - /* If both RIPv2 and the poor-man's router discovery - * kludge are on, arrange to advertise an extra - * default route via RIPv1. - */ if ((ws.state & WS_ST_RIP2_ALL) && (ifp->int_state & IS_PM_RDISC)) { + ws.state |= WS_ST_PM_RDISC; ripv12_buf.rip.rip_vers = RIPv1; - v12buf.n->n_family = RIP_AF_INET; - v12buf.n->n_dst = htonl(RIP_DEFAULT); - v12buf.n->n_metric = htonl(def_metric); - v12buf.n++; } } @@ -796,21 +696,21 @@ supply(struct sockaddr_in *dst, /* Flush the packet buffers, provided they are not empty and * do not contain only the password. */ - if (v12buf.n != v12buf.base - && (v12buf.n > v12buf.base+1 - || v12buf.base->n_family != RIP_AF_AUTH)) - supply_write(&v12buf); - if (v2buf.n != v2buf.base - && (v2buf.n > v2buf.base+1 - || v2buf.base->n_family != RIP_AF_AUTH)) - supply_write(&v2buf); + if (ws.v12.n != ws.v12.base + && (ws.v12.n > ws.v12.base+1 + || ws.v12.n->n_family != RIP_AF_AUTH)) + supply_write(&ws.v12); + if (ws.v2.n != ws.v2.base + && (ws.v2.n > ws.v2.base+1 + || ws.v2.n->n_family != RIP_AF_AUTH)) + supply_write(&ws.v2); /* If we sent nothing and this is an answer to a query, send * an empty buffer. */ if (ws.npackets == 0 && (ws.state & WS_ST_QUERY)) - supply_write(&v12buf); + supply_write(&ws.v12); } @@ -838,28 +738,36 @@ rip_bcast(int flash) if (rip_sock < 0) return; - trace_act("send %s and inhibit dynamic updates for %.3f sec", + trace_act("send %s and inhibit dynamic updates for %.3f sec\n", flash ? "dynamic update" : "all routes", rtime.tv_sec + ((float)rtime.tv_usec)/1000000.0); for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) { - /* Skip interfaces not doing RIP. - * Do try broken interfaces to see if they have healed. + /* skip interfaces not doing RIP, those already queried, + * and aliases. Do try broken interfaces to see + * if they have healed. */ - if (IS_RIP_OUT_OFF(ifp->int_state)) + if (0 != (ifp->int_state & (IS_PASSIVE | IS_ALIAS))) continue; /* skip turned off interfaces */ if (!iff_alive(ifp->int_if_flags)) continue; - vers = (ifp->int_state & IS_NO_RIPV1_OUT) ? RIPv2 : RIPv1; + /* default to RIPv1 output */ + if (ifp->int_state & IS_NO_RIPV1_OUT) { + /* Say nothing if this interface is turned off */ + if (ifp->int_state & IS_NO_RIPV2_OUT) + continue; + vers = RIPv2; + } else { + vers = RIPv1; + } if (ifp->int_if_flags & IFF_BROADCAST) { /* ordinary, hardware interface */ dst.sin_addr.s_addr = ifp->int_brdaddr; - - /* If RIPv1 is not turned off, then broadcast so + /* if RIPv1 is not turned off, then broadcast so * that RIPv1 listeners can hear. */ if (vers == RIPv2 @@ -874,17 +782,13 @@ rip_bcast(int flash) dst.sin_addr.s_addr = ifp->int_dstaddr; type = OUT_UNICAST; - } else if (ifp->int_state & IS_REMOTE) { + } else { /* remote interface */ dst.sin_addr.s_addr = ifp->int_addr; type = OUT_UNICAST; - - } else { - /* ATM, HIPPI, etc. */ - continue; } - supply(&dst, ifp, type, flash, vers, 1); + supply(&dst, ifp, type, flash, vers); } update_seqno++; /* all routes are up to date */ @@ -914,21 +818,28 @@ rip_query(void) bzero(&buf, sizeof(buf)); for (ifp = ifnet; ifp; ifp = ifp->int_next) { - /* Skip interfaces those already queried. - * Do not ask via interfaces through which we don't - * accept input. Do not ask via interfaces that cannot - * send RIP packets. - * Do try broken interfaces to see if they have healed. + /* skip interfaces not doing RIP, those already queried, + * and aliases. Do try broken interfaces to see + * if they have healed. */ - if (IS_RIP_IN_OFF(ifp->int_state) - || ifp->int_query_time != NEVER) + if (0 != (ifp->int_state & (IS_RIP_QUERIED + | IS_PASSIVE | IS_ALIAS))) continue; /* skip turned off interfaces */ if (!iff_alive(ifp->int_if_flags)) continue; - buf.rip_vers = (ifp->int_state&IS_NO_RIPV1_OUT) ? RIPv2:RIPv1; + /* default to RIPv1 output */ + if (ifp->int_state & IS_NO_RIPV2_OUT) { + /* Say nothing if this interface is turned off */ + if (ifp->int_state & IS_NO_RIPV1_OUT) + continue; + buf.rip_vers = RIPv1; + } else { + buf.rip_vers = RIPv2; + } + buf.rip_cmd = RIPCMD_REQUEST; buf.rip_nets[0].n_family = RIP_AF_UNSPEC; buf.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY); @@ -951,17 +862,13 @@ rip_query(void) dst.sin_addr.s_addr = ifp->int_dstaddr; type = OUT_UNICAST; - } else if (ifp->int_state & IS_REMOTE) { + } else { /* remote interface */ dst.sin_addr.s_addr = ifp->int_addr; type = OUT_UNICAST; - - } else { - /* ATM, HIPPI, etc. */ - continue; } - ifp->int_query_time = now.tv_sec+SUPPLY_INTERVAL; + ifp->int_state |= IS_RIP_QUERIED; if (output(type, &dst, ifp, &buf, sizeof(buf)) < 0) if_sick(ifp); } |