diff options
author | Mark Murray <markm@FreeBSD.org> | 1999-05-02 10:51:54 +0000 |
---|---|---|
committer | Mark Murray <markm@FreeBSD.org> | 1999-05-02 10:51:54 +0000 |
commit | 2c7a97817b8e83a80ed67bbeb294334140b7d26d (patch) | |
tree | c0dd10cc2471be0527b6700410ae4edfbb6d940c /sbin/routed/if.c | |
parent | cdb877c33d6cc233b12f3f889f372a15d70559e4 (diff) | |
download | src-2c7a97817b8e83a80ed67bbeb294334140b7d26d.tar.gz src-2c7a97817b8e83a80ed67bbeb294334140b7d26d.zip |
Latest-and-greatest routed.vendor/SGI/vjs_990324vendor/SGI/v_2_17
Includes RIPv2 and Router Discovery.
Submitted by: Vernon Schryver <vjs@calcite.rhyolite.com>
Notes
Notes:
svn path=/vendor/SGI/dist2/; revision=46286
svn path=/vendor/SGI/tags/v_2_17/; revision=46287; tag=vendor/SGI/v_2_17
svn path=/vendor/SGI/vjs_990324/; revision=46288; tag=vendor/SGI/vjs_990324
Diffstat (limited to 'sbin/routed/if.c')
-rw-r--r-- | sbin/routed/if.c | 225 |
1 files changed, 142 insertions, 83 deletions
diff --git a/sbin/routed/if.c b/sbin/routed/if.c index b68ff52a9134..54228ce24aa8 100644 --- a/sbin/routed/if.c +++ b/sbin/routed/if.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 @@ -31,16 +31,17 @@ * SUCH DAMAGE. */ -#if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) -static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93"; -#elif defined(__NetBSD__) -static char rcsid[] = "$NetBSD$"; -#endif -#ident "$Revision: 1.23 $" - #include "defs.h" #include "pathnames.h" +#if !defined(sgi) && !defined(__NetBSD__) +static char sccsid[] __attribute__((unused)) = "@(#)if.c 8.1 (Berkeley) 6/5/93"; +#elif defined(__NetBSD__) +#include <sys/cdefs.h> +__RCSID("$NetBSD$"); +#endif +#ident "$Revision: 2.17 $" + struct interface *ifnet; /* all interfaces */ /* hash table for all interfaces, big enough to tolerate ridiculous @@ -69,18 +70,22 @@ int tot_interfaces; /* # of remote and local interfaces */ int rip_interfaces; /* # of interfaces doing RIP */ int foundloopback; /* valid flag for loopaddr */ naddr loopaddr; /* our address on loopback */ +struct rt_spare loop_rts; struct timeval ifinit_timer; static struct timeval last_ifinit; +#define IF_RESCAN_DELAY() (last_ifinit.tv_sec == now.tv_sec \ + && last_ifinit.tv_usec == now.tv_usec \ + && timercmp(&ifinit_timer, &now, >)) int have_ripv1_out; /* have a RIPv1 interface */ int have_ripv1_in; static struct interface** -nhash(register char *p) +nhash(char *p) { - register u_int i; + u_int i; for (i = 0; *p != '\0'; p++) { i = ((i<<1) & 0x7fffffff) | ((i>>31) & 1); @@ -199,8 +204,7 @@ ifwithname(char *name, /* "ec0" or whatever */ /* If there is no known interface, maybe there is a * new interface. So just once look for new interfaces. */ - if (last_ifinit.tv_sec == now.tv_sec - && last_ifinit.tv_usec == now.tv_usec) + if (IF_RESCAN_DELAY()) return 0; ifinit(); } @@ -208,16 +212,25 @@ ifwithname(char *name, /* "ec0" or whatever */ struct interface * -ifwithindex(u_short index) +ifwithindex(u_short index, + int rescan_ok) { struct interface *ifp; + for (;;) { + for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) { + if (ifp->int_index == index) + return ifp; + } - for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) { - if (ifp->int_index == index) - return ifp; + /* If there is no known interface, maybe there is a + * new interface. So just once look for new interfaces. + */ + if (!rescan_ok + || IF_RESCAN_DELAY()) + return 0; + ifinit(); } - return 0; } @@ -253,8 +266,7 @@ iflookup(naddr addr) } if (maybe != 0 - || (last_ifinit.tv_sec == now.tv_sec - && last_ifinit.tv_usec == now.tv_usec)) + || IF_RESCAN_DELAY()) return maybe; /* If there is no known interface, maybe there is a @@ -290,12 +302,13 @@ naddr ripv1_mask_net(naddr addr, /* in network byte order */ struct interface *ifp) /* as seen on this interface */ { + struct r1net *r1p; naddr mask = 0; if (addr == 0) /* default always has 0 mask */ return mask; - if (ifp != 0) { + if (ifp != 0 && ifp->int_ripv1_mask != HOST_MASK) { /* If the target network is that of the associated interface * on which it arrived, then use the netmask of the interface. */ @@ -311,15 +324,26 @@ ripv1_mask_net(naddr addr, /* in network byte order */ */ for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) { if (on_net(addr, ifp->int_std_net, ifp->int_std_mask) - && ifp->int_ripv1_mask > mask) + && ifp->int_ripv1_mask > mask + && ifp->int_ripv1_mask != HOST_MASK) mask = ifp->int_ripv1_mask; } + } - /* Otherwise, make the classic A/B/C guess. - */ - if (mask == 0) - mask = std_mask(addr); + /* check special definitions */ + if (mask == 0) { + for (r1p = r1nets; r1p != 0; r1p = r1p->r1net_next) { + if (on_net(addr, r1p->r1net_net, r1p->r1net_match) + && r1p->r1net_mask > mask) + mask = r1p->r1net_mask; + } + + /* Otherwise, make the classic A/B/C guess. + */ + if (mask == 0) + mask = std_mask(addr); + } return mask; } @@ -374,11 +398,11 @@ check_dup(naddr addr, /* IP address, so network byte order */ if (ifp->int_mask != mask) continue; - if (!iff_alive(ifp->int_if_flags)) + if (!iff_up(ifp->int_if_flags)) continue; - /* The local address can only be shared with a point-to- - * point link. + /* The local address can only be shared with a point-to-point + * link. */ if (ifp->int_addr == addr && (((if_flags|ifp->int_if_flags) & IFF_POINTOPOINT) == 0)) @@ -495,8 +519,8 @@ ifdel(struct interface *ifp) rip_interfaces--; /* Zap all routes associated with this interface. - * Assume routes just using gateways beyond this interface will - * timeout naturally, and have probably already died. + * Assume routes just using gateways beyond this interface + * will timeout naturally, and have probably already died. */ (void)rn_walktree(rhead, walk_bad, 0); @@ -539,7 +563,7 @@ if_bad(struct interface *ifp) ifp->int_state |= (IS_BROKE | IS_SICK); ifp->int_act_time = NEVER; ifp->int_query_time = NEVER; - ifp->int_data.ts = 0; + ifp->int_data.ts = now.tv_sec; trace_if("Chg", ifp); @@ -559,7 +583,7 @@ if_bad(struct interface *ifp) */ int /* 1=it was dead */ if_ok(struct interface *ifp, - char *type) + const char *type) { struct interface *ifp1; @@ -617,7 +641,7 @@ rt_xaddrs(struct rt_addrinfo *info, #endif - bzero(info, sizeof(*info)); + memset(info, 0, sizeof(*info)); info->rti_addrs = addrs; for (i = 0; i < RTAX_MAX && sa < lim; i++) { if ((addrs & (1 << i)) == 0) @@ -675,7 +699,7 @@ ifinit(void) ? CHECK_ACT_INTERVAL : CHECK_QUIET_INTERVAL); - /* mark all interfaces so we can get rid of thost that disappear */ + /* mark all interfaces so we can get rid of those that disappear */ for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) ifp->int_state &= ~(IS_CHECKED | IS_DUP); @@ -692,14 +716,16 @@ ifinit(void) if ((needed = sysctl_buf_size) != 0) { if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0) break; + /* retry if the table grew */ if (errno != ENOMEM && errno != EFAULT) - BADERR(1, "ifinit: get interface table"); + BADERR(1, "ifinit: sysctl(RT_IFLIST)"); free(sysctl_buf); needed = 0; } if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) - BADERR(1,"ifinit: route-sysctl-estimate"); - sysctl_buf = rtmalloc(sysctl_buf_size = needed, "ifinit"); + BADERR(1,"ifinit: sysctl(RT_IFLIST) estimate"); + sysctl_buf = rtmalloc(sysctl_buf_size = needed, + "ifinit sysctl"); } ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed); @@ -715,7 +741,7 @@ ifinit(void) ifm = (struct if_msghdr *)ifam; /* make prototype structure for the IP aliases */ - bzero(&ifs0, sizeof(ifs0)); + memset(&ifs0, 0, sizeof(ifs0)); ifs0.int_rip_sock = -1; ifs0.int_index = ifm->ifm_index; ifs0.int_if_flags = ifm->ifm_flags; @@ -748,11 +774,11 @@ ifinit(void) * will be an alias. * Do not output RIP or Router-Discovery packets via aliases. */ - bcopy(&ifs0, &ifs, sizeof(ifs)); - ifs0.int_state |= (IS_ALIAS | IS_NO_RIP | IS_NO_RDISC); + memcpy(&ifs, &ifs0, sizeof(ifs)); + ifs0.int_state |= (IS_ALIAS | IS_NO_RIP_OUT | IS_NO_RDISC); if (INFO_IFA(&info) == 0) { - if (iff_alive(ifs.int_if_flags)) { + if (iff_up(ifs.int_if_flags)) { if (!(prev_complaints & COMP_NOADDR)) msglog("%s has no address", ifs.int_name); @@ -761,7 +787,7 @@ ifinit(void) continue; } if (INFO_IFA(&info)->sa_family != AF_INET) { - if (iff_alive(ifs.int_if_flags)) { + if (iff_up(ifs.int_if_flags)) { if (!(prev_complaints & COMP_NOT_INET)) trace_act("%s: not AF_INET", ifs.int_name); @@ -774,7 +800,7 @@ ifinit(void) if (ntohl(ifs.int_addr)>>24 == 0 || ntohl(ifs.int_addr)>>24 == 0xff) { - if (iff_alive(ifs.int_if_flags)) { + if (iff_up(ifs.int_if_flags)) { if (!(prev_complaints & COMP_BADADDR)) msglog("%s has a bad address", ifs.int_name); @@ -793,12 +819,14 @@ ifinit(void) if (!foundloopback) { foundloopback = 1; loopaddr = ifs.int_addr; + loop_rts.rts_gate = loopaddr; + loop_rts.rts_router = loopaddr; } } else if (ifs.int_if_flags & IFF_POINTOPOINT) { if (INFO_BRD(&info) == 0 || INFO_BRD(&info)->sa_family != AF_INET) { - if (iff_alive(ifs.int_if_flags)) { + if (iff_up(ifs.int_if_flags)) { if (!(prev_complaints & COMP_NODST)) msglog("%s has a bad" " destination address", @@ -810,7 +838,7 @@ ifinit(void) ifs.int_dstaddr = S_ADDR(INFO_BRD(&info)); if (ntohl(ifs.int_dstaddr)>>24 == 0 || ntohl(ifs.int_dstaddr)>>24 == 0xff) { - if (iff_alive(ifs.int_if_flags)) { + if (iff_up(ifs.int_if_flags)) { if (!(prev_complaints & COMP_NODST)) msglog("%s has a bad" " destination address", @@ -826,7 +854,7 @@ ifinit(void) } else { if (INFO_MASK(&info) == 0) { - if (iff_alive(ifs.int_if_flags)) { + if (iff_up(ifs.int_if_flags)) { if (!(prev_complaints & COMP_NOMASK)) msglog("%s has no netmask", ifs.int_name); @@ -844,7 +872,7 @@ ifinit(void) if (ifs.int_if_flags & IFF_BROADCAST) { if (INFO_BRD(&info) == 0) { - if (iff_alive(ifs.int_if_flags)) { + if (iff_up(ifs.int_if_flags)) { if (!(prev_complaints & COMP_NOBADR)) msglog("%s has" @@ -881,7 +909,7 @@ ifinit(void) if (ifs.int_metric > HOPCNT_INFINITY) { ifs.int_metric = 0; if (!(prev_complaints & COMP_BAD_METRIC) - && iff_alive(ifs.int_if_flags)) { + && iff_up(ifs.int_if_flags)) { complaints |= COMP_BAD_METRIC; msglog("%s has a metric of %d", ifs.int_name, ifs.int_metric); @@ -930,19 +958,26 @@ ifinit(void) /* note interfaces that have been turned off */ - if (!iff_alive(ifs.int_if_flags)) { - if (iff_alive(ifp->int_if_flags)) { + if (!iff_up(ifs.int_if_flags)) { + if (iff_up(ifp->int_if_flags)) { msglog("interface %s to %s turned off", ifp->int_name, naddr_ntoa(ifp->int_dstaddr)); if_bad(ifp); - ifp->int_if_flags &= ~IFF_UP_RUNNING; + ifp->int_if_flags &= ~IFF_UP; + } else if (now.tv_sec>(ifp->int_data.ts + + CHECK_BAD_INTERVAL)) { + trace_act("interface %s has been off" + " %ld seconds; forget it", + ifp->int_name, + now.tv_sec-ifp->int_data.ts); + ifdel(ifp); } continue; } /* or that were off and are now ok */ - if (!iff_alive(ifp->int_if_flags)) { - ifp->int_if_flags |= IFF_UP_RUNNING; + if (!iff_up(ifp->int_if_flags)) { + ifp->int_if_flags |= IFF_UP; (void)if_ok(ifp, ""); } @@ -958,7 +993,7 @@ ifinit(void) oerr = ifs.int_data.oerrors - ifp->int_data.oerrors; #ifdef sgi /* Through at least IRIX 6.2, PPP and SLIP - * count packets dropped by the filters. + * count packets dropped by the filters. * But FDDI rings stuck non-operational count * dropped packets as they wait for improvement. */ @@ -974,7 +1009,7 @@ ifinit(void) } ifp->int_data = ifs.int_data; - /* Withhold judgement when the short error + /* Withhold judgment when the short error * counters wrap or the interface is reset. */ if (ierr < 0 || in < 0 || oerr < 0 || out < 0) { @@ -1024,7 +1059,7 @@ ifinit(void) /* This is a new interface. * If it is dead, forget it. */ - if (!iff_alive(ifs.int_if_flags)) + if (!iff_up(ifs.int_if_flags)) continue; /* If it duplicates an existing interface, @@ -1034,6 +1069,12 @@ ifinit(void) ifp = check_dup(ifs.int_addr,ifs.int_dstaddr,ifs.int_mask, ifs.int_if_flags); if (ifp != 0) { + /* Ignore duplicates of itself, caused by having + * IP aliases on the same network. + */ + if (!strcmp(ifp->int_name, ifs.int_name)) + continue; + if (!(prev_complaints & COMP_DUP)) { complaints |= COMP_DUP; msglog("%s (%s%s%s) is duplicated by" @@ -1067,8 +1108,8 @@ ifinit(void) /* It is new and ok. Add it to the list of interfaces */ - ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit"); - bcopy(&ifs, ifp, sizeof(*ifp)); + ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit ifp"); + memcpy(ifp, &ifs, sizeof(*ifp)); get_parms(ifp); if_link(ifp); trace_if("Add", ifp); @@ -1138,14 +1179,18 @@ ifinit(void) rtdelete(rt); rt = 0; } else { + loop_rts.rts_ifp = ifp; + loop_rts.rts_metric = 0; + loop_rts.rts_time = rt->rt_time; rtchange(rt, rt->rt_state | RS_MHOME, - loopaddr, loopaddr, - 0, 0, ifp, rt->rt_time, 0); + &loop_rts, 0); } } - if (rt == 0) - rtadd(myaddr, HOST_MASK, loopaddr, loopaddr, - 0, 0, RS_MHOME, ifp); + if (rt == 0) { + loop_rts.rts_ifp = ifp; + loop_rts.rts_metric = 0; + rtadd(myaddr, HOST_MASK, RS_MHOME, &loop_rts); + } } for (ifp = ifnet; ifp != 0; ifp = ifp1) { @@ -1190,7 +1235,7 @@ ifinit(void) /* Delete any routes to the network address through * foreign routers. Remove even static routes. */ - del_static(ifp->int_addr, HOST_MASK, 0); + del_static(ifp->int_addr, HOST_MASK, 0, 0); rt = rtget(ifp->int_addr, HOST_MASK); if (rt != 0 && rt->rt_router != loopaddr) { rtdelete(rt); @@ -1203,14 +1248,17 @@ ifinit(void) } else { ifp1 = rt->rt_ifp; } - rtchange(rt,((rt->rt_state & ~RS_NET_SYN) - | (RS_IF|RS_LOCAL)), - loopaddr, loopaddr, - 0, 0, ifp1, rt->rt_time, 0); + loop_rts.rts_ifp = ifp1; + loop_rts.rts_metric = 0; + loop_rts.rts_time = rt->rt_time; + rtchange(rt, ((rt->rt_state & ~RS_NET_SYN) + | (RS_IF|RS_LOCAL)), + &loop_rts, 0); } else { + loop_rts.rts_ifp = ifp; + loop_rts.rts_metric = 0; rtadd(ifp->int_addr, HOST_MASK, - loopaddr, loopaddr, - 0, 0, (RS_IF | RS_LOCAL), ifp); + (RS_IF | RS_LOCAL), &loop_rts); } } } @@ -1224,10 +1272,12 @@ ifinit(void) rtdelete(rt); rt = 0; } - if (rt == 0) + if (rt == 0) { + loop_rts.rts_ifp = 0; + loop_rts.rts_metric = intnetp->intnet_metric-1; rtadd(intnetp->intnet_addr, intnetp->intnet_mask, - loopaddr, loopaddr, intnetp->intnet_metric-1, - 0, RS_NET_SYN | RS_NET_INT, 0); + RS_NET_SYN | RS_NET_INT, &loop_rts); + } } prev_complaints = complaints; @@ -1238,6 +1288,7 @@ static void check_net_syn(struct interface *ifp) { struct rt_entry *rt; + static struct rt_spare new; /* Turn on the need to automatically synthesize a network route @@ -1254,10 +1305,14 @@ check_net_syn(struct interface *ifp) rtdelete(rt); rt = 0; } - if (rt == 0) + if (rt == 0) { + new.rts_ifp = ifp; + new.rts_gate = ifp->int_addr; + new.rts_router = ifp->int_addr; + new.rts_metric = ifp->int_metric; rtadd(ifp->int_std_addr, ifp->int_std_mask, - ifp->int_addr, ifp->int_addr, - ifp->int_metric, 0, RS_NET_SYN, ifp); + RS_NET_SYN, &new); + } } else { ifp->int_state &= ~IS_NEED_NET_SYN; @@ -1280,7 +1335,8 @@ int /* 0=bad interface */ addrouteforif(struct interface *ifp) { struct rt_entry *rt; - naddr dst, gate; + static struct rt_spare new; + naddr dst; /* skip sick interfaces @@ -1294,11 +1350,16 @@ addrouteforif(struct interface *ifp) if (ifp->int_state & IS_SUBNET) check_net_syn(ifp); - gate = ifp->int_addr; dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) ? ifp->int_dstaddr : htonl(ifp->int_net)); + new.rts_ifp = ifp; + new.rts_router = ifp->int_addr; + new.rts_gate = ifp->int_addr; + new.rts_metric = ifp->int_metric; + new.rts_time = now.tv_sec; + /* If we are going to send packets to the gateway, * it must be reachable using our physical interfaces */ @@ -1311,7 +1372,7 @@ addrouteforif(struct interface *ifp) * The right route must be for the right interface, not synthesized * from a subnet, be a "gateway" or not as appropriate, and so forth. */ - del_static(dst, ifp->int_mask, 0); + del_static(dst, ifp->int_mask, 0, 0); rt = rtget(dst, ifp->int_mask); if (rt != 0) { if ((rt->rt_ifp != ifp @@ -1324,8 +1385,7 @@ addrouteforif(struct interface *ifp) } else { rtchange(rt, ((rt->rt_state | RS_IF) & ~(RS_NET_SYN | RS_LOCAL)), - ifp->int_addr, ifp->int_addr, - ifp->int_metric, 0, ifp, now.tv_sec, 0); + &new, 0); } } if (rt == 0) { @@ -1333,8 +1393,7 @@ addrouteforif(struct interface *ifp) trace_act("re-install interface %s", ifp->int_name); - rtadd(dst, ifp->int_mask, gate, gate, - ifp->int_metric, 0, RS_IF, ifp); + rtadd(dst, ifp->int_mask, RS_IF, &new); } return 1; |