summaryrefslogtreecommitdiff
path: root/sbin/routed/output.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1997-07-30 23:28:59 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1997-07-30 23:28:59 +0000
commitc8e8720d9608e1d404551392fa626de1242145cc (patch)
tree93650b27a6ea7ea404bf54a763998664b8899ff1 /sbin/routed/output.c
parent8f8968006824e23ac888c36b119b28a019d1faa2 (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.c463
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);
}