diff options
Diffstat (limited to 'sbin/routed/input.c')
-rw-r--r-- | sbin/routed/input.c | 131 |
1 files changed, 69 insertions, 62 deletions
diff --git a/sbin/routed/input.c b/sbin/routed/input.c index 85010a9f1f4..db66da6398b 100644 --- a/sbin/routed/input.c +++ b/sbin/routed/input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: input.c,v 1.6 1996/09/06 13:22:07 deraadt Exp $ */ +/* $OpenBSD: input.c,v 1.7 1996/10/02 06:51:44 mickey Exp $ */ /* * Copyright (c) 1983, 1988, 1993 @@ -36,7 +36,7 @@ #if !defined(lint) static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93"; #else -static char rcsid[] = "$OpenBSD: input.c,v 1.6 1996/09/06 13:22:07 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: input.c,v 1.7 1996/10/02 06:51:44 mickey Exp $"; #endif #include "defs.h" @@ -70,9 +70,7 @@ read_rip(int sock, logbad(1,"impossible recvfrom(rip) fromlen=%d", fromlen); - input(&from, - (ifp != 0) ? ifp : iflookup(from.sin_addr.s_addr), - &inbuf.rip, cc); + input(&from, ifp, &inbuf.rip, cc); } } @@ -81,7 +79,7 @@ read_rip(int sock, */ static void input(struct sockaddr_in *from, /* received from this IP address */ - struct interface *ifp, + struct interface *sifp, /* interface by which it arrived */ struct rip *rip, int size) { @@ -89,17 +87,21 @@ input(struct sockaddr_in *from, /* received from this IP address */ static naddr use_auth, bad_len, bad_mask; static naddr unk_router, bad_router, bad_nhop; + struct interface *aifp; /* interface if via 1 hop */ struct rt_entry *rt; struct netinfo *n, *lim; struct interface *ifp1; naddr gate, mask, v1_mask, dst, ddst_h; int i; + aifp = iflookup(from->sin_addr.s_addr); + if (sifp == 0) + sifp = aifp; - if (ifp != 0) - ifp->int_state |= IS_ACTIVE; + if (sifp != 0) + sifp->int_state |= IS_ACTIVE; - trace_rip("Recv", "from", from, ifp, rip, size); + trace_rip("Recv", "from", from, sifp, rip, size); if (rip->rip_vers == 0) { if (from->sin_addr.s_addr != bad_router) @@ -108,6 +110,8 @@ input(struct sockaddr_in *from, /* received from this IP address */ rip->rip_cmd, naddr_ntoa(FROM_NADDR)); bad_router = from->sin_addr.s_addr; return; + } else if (rip->rip_vers > RIPv2) { + rip->rip_vers = RIPv2; } if (size > MAXPACKETSIZE) { if (from->sin_addr.s_addr != bad_router) @@ -132,7 +136,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ * RIPv1 systems will listen? Crazy! */ if (!auth_ok - && rip->rip_vers >= RIPv2 + && rip->rip_vers == RIPv2 && n < lim && n->n_family == RIP_AF_AUTH) { if (from->sin_addr.s_addr != use_auth) msglog("RIPv2 message with authentication" @@ -188,32 +192,42 @@ input(struct sockaddr_in *from, /* received from this IP address */ * We respond to routers only if we are acting * as a supplier, or to anyone other than a router * (i.e. a query). - * - * Answer a query from a stray program with all - * we know. Filter the answer to a query from a - * router in the about same way broadcasts are - * filtered. - * - * Only answer a router if we are a supplier - * to keep an unwary host that is just starting - * from picking us as a router. */ if (n->n_family == RIP_AF_UNSPEC && n->n_metric == HOPCNT_INFINITY && n == rip->rip_nets && n+1 == lim) { if (from->sin_port != htons(RIP_PORT)) { - /* query from `rtquery` or similar - */ - supply(from, ifp, - OUT_QUERY, 0, rip->rip_vers); - } else if (supplier) { - /* a router trying to prime its - * tables. + /* Answer a query from a utility + * program with all we know. */ - supply(from, ifp, - OUT_UNICAST, 0, rip->rip_vers); + supply(from, sifp, OUT_QUERY, 0, + rip->rip_vers); + return; } + /* A router trying to prime its tables. + * Filter the answer in the about same way + * broadcasts are filtered. + * + * Only answer a router if we are a supplier + * to keep an unwary host that is just starting + * from picking us as a router. Respond with + * RIPv1 instead of RIPv2 if that is what we + * are broadcasting on the interface to keep + * the remote router from getting the wrong + * initial idea of the routes we send. + */ + if (!supplier + || aifp == 0 + || (aifp->int_state & IS_PASSIVE) + || (aifp->int_state & IS_ALIAS) + || ((aifp->int_state & IS_NO_RIPV1_OUT) + && (aifp->int_state&IS_NO_RIPV2_OUT))) + return; + + supply(from, aifp, OUT_UNICAST, 0, + (aifp->int_state&IS_NO_RIPV1_OUT) + ? RIPv2 : RIPv1); return; } @@ -242,7 +256,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ if (rip->rip_vers == RIPv1 || 0 == (mask = ntohl(n->n_mask)) || 0 != (ntohl(dst) & ~mask)) - mask = ripv1_mask_host(dst,ifp); + mask = ripv1_mask_host(dst,sifp); rt = rtget(dst, mask); if (!rt && dst != RIP_DEFAULT) @@ -259,16 +273,16 @@ input(struct sockaddr_in *from, /* received from this IP address */ n->n_metric = HOPCNT_INFINITY; } else { n->n_metric = rt->rt_metric+1; - n->n_metric += (ifp!=0) ? ifp->int_metric : 1; + n->n_metric += (sifp!=0)?sifp->int_metric : 1; if (n->n_metric > HOPCNT_INFINITY) n->n_metric = HOPCNT_INFINITY; if (rip->rip_vers != RIPv1) { n->n_tag = rt->rt_tag; - if (ifp != 0 + if (sifp != 0 && on_net(rt->rt_gate, - ifp->int_net, - ifp->int_mask) - && rt->rt_gate != ifp->int_addr) + sifp->int_net, + sifp->int_mask) + && rt->rt_gate != sifp->int_addr) n->n_nhop = rt->rt_gate; } } @@ -285,9 +299,9 @@ input(struct sockaddr_in *from, /* received from this IP address */ rip->rip_vers = RIPv2; if (from->sin_port != htons(RIP_PORT)) { /* query */ - (void)output(OUT_QUERY, from, ifp, rip, size); + (void)output(OUT_QUERY, from, sifp, rip, size); } else if (supplier) { - (void)output(OUT_UNICAST, from, ifp, rip, size); + (void)output(OUT_UNICAST, from, sifp, rip, size); } return; @@ -299,12 +313,11 @@ input(struct sockaddr_in *from, /* received from this IP address */ naddr_ntoa(FROM_NADDR)); return; } - if (ifp == 0) { + if (aifp == 0) { msglog("trace command from unknown router %s", naddr_ntoa(FROM_NADDR)); return; } -#if PERMIT_TRACE if (rip->rip_cmd == RIPCMD_TRACEON) { rip->rip_tracefile[size-4] = '\0'; trace_on((char*)rip->rip_tracefile, 0); @@ -312,10 +325,6 @@ input(struct sockaddr_in *from, /* received from this IP address */ trace_off("tracing turned off by %s\n", naddr_ntoa(FROM_NADDR)); } -#else - msglog("trace command from %s ignored: %s\n", - rip->rip_tracefile); -#endif return; case RIPCMD_RESPONSE: @@ -363,7 +372,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ * broadcast or point-to-point networks, and from * those listed in /etc/gateways. */ - if (!ifp) { + if (!aifp) { if (from->sin_addr.s_addr != unk_router) msglog("discard packet from unknown router %s" " or via unidentified interface", @@ -371,19 +380,19 @@ input(struct sockaddr_in *from, /* received from this IP address */ unk_router = from->sin_addr.s_addr; return; } - if (ifp->int_state & IS_PASSIVE) { + if (aifp->int_state & IS_PASSIVE) { trace_act("discard packet from %s" " via passive interface %s\n", naddr_ntoa(FROM_NADDR), - ifp->int_name); + aifp->int_name); return; } /* Check required version */ - if (((ifp->int_state & IS_NO_RIPV1_IN) + if (((aifp->int_state & IS_NO_RIPV1_IN) && rip->rip_vers == RIPv1) - || ((ifp->int_state & IS_NO_RIPV2_IN) + || ((aifp->int_state & IS_NO_RIPV2_IN) && rip->rip_vers != RIPv1)) { trace_pkt("discard RIPv%d response\n", rip->rip_vers); @@ -392,15 +401,15 @@ input(struct sockaddr_in *from, /* received from this IP address */ /* Ignore routes via dead interface. */ - if (ifp->int_state & IS_BROKE) { + if (aifp->int_state & IS_BROKE) { trace_pkt("discard response via broken interface %s\n", - ifp->int_name); + aifp->int_name); return; } /* Authenticate the packet if we have a secret. */ - if (ifp->int_passwd[0] != '\0') { + if (aifp->int_passwd[0] != '\0') { if (n >= lim || n->n_family != RIP_AF_AUTH || ((struct netauth*)n)->a_type != RIP_AUTH_PW) { @@ -411,8 +420,8 @@ input(struct sockaddr_in *from, /* received from this IP address */ return; } else if (0 != bcmp(((struct netauth*)n)->au.au_pw, - ifp->int_passwd, - sizeof(ifp->int_passwd))) { + aifp->int_passwd, + sizeof(aifp->int_passwd))) { if (from->sin_addr.s_addr != use_auth) msglog("bad password from %s", naddr_ntoa(FROM_NADDR)); @@ -469,7 +478,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ } else { /* Use it only if it is valid. */ if (on_net(n->n_nhop, - ifp->int_net, ifp->int_mask) + aifp->int_net, aifp->int_mask) && check_dst(n->n_nhop)) { gate = n->n_nhop; } else { @@ -487,7 +496,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ if (rip->rip_vers == RIPv1 || 0 == (mask = ntohl(n->n_mask))) { - mask = ripv1_mask_host(dst,ifp); + mask = ripv1_mask_host(dst,aifp); } else if ((ntohl(dst) & ~mask) != 0) { if (bad_mask != from->sin_addr.s_addr) { msglog("router %s sent bad netmask" @@ -504,7 +513,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ /* Adjust metric according to incoming interface.. */ - n->n_metric += ifp->int_metric; + n->n_metric += aifp->int_metric; if (n->n_metric > HOPCNT_INFINITY) n->n_metric = HOPCNT_INFINITY; @@ -514,9 +523,9 @@ input(struct sockaddr_in *from, /* received from this IP address */ * Be a little more paranoid than that, and reject * default routes with the same metric we advertised. */ - if (ifp->int_d_metric != 0 + if (aifp->int_d_metric != 0 && dst == RIP_DEFAULT - && n->n_metric >= ifp->int_d_metric) + && n->n_metric >= aifp->int_d_metric) continue; /* We can receive aggregated RIPv2 routes that must @@ -565,7 +574,7 @@ input(struct sockaddr_in *from, /* received from this IP address */ } for (;;) { - input_route(ifp, FROM_NADDR, + input_route(aifp, FROM_NADDR, dst, mask, gate, n); if (i-- == 0) break; @@ -645,10 +654,8 @@ input_route(struct interface *ifp, * synthetic, RIPv1 network route of our own. * The worst is that both kinds of routes might be * received, and the bad one might have the smaller - * metric. Partly solve this problem by faking the - * RIPv1 route with a metric that reflects the most - * distant part of the subnet. Also never - * aggregate into such a route. Also keep it + * metric. Partly solve this problem by never + * aggregating into such a route. Also keep it * around as long as the interface exists. */ |