From owner-freebsd-hackers Wed Feb 26 15:49:38 1997 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.5/8.8.5) id PAA12244 for hackers-outgoing; Wed, 26 Feb 1997 15:49:38 -0800 (PST) Received: from alpo.whistle.com (alpo.whistle.com [207.76.204.38]) by freefall.freebsd.org (8.8.5/8.8.5) with ESMTP id PAA12158 for ; Wed, 26 Feb 1997 15:49:18 -0800 (PST) Received: from current1.whistle.com (current1.whistle.com [207.76.205.22]) by alpo.whistle.com (8.8.5/8.8.4) with SMTP id PAA21587; Wed, 26 Feb 1997 15:41:54 -0800 (PST) Message-ID: <3314C9BE.4487EB71@whistle.com> Date: Wed, 26 Feb 1997 15:39:42 -0800 From: Julian Elischer Organization: Whistle Communications X-Mailer: Mozilla 3.0Gold (X11; I; FreeBSD 2.2-CURRENT i386) MIME-Version: 1.0 To: hackers@freebsd.org CC: julian@alpo.whistle.com Subject: [RFC] Networking diffs Content-Type: multipart/mixed; boundary="------------62319AC452BFA1D76201DD56" Sender: owner-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk This is a multi-part message in MIME format. --------------62319AC452BFA1D76201DD56 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Since we got the ability of having many addresses per interface, (with the creation of the ifaddr struct) there has been a gradual cleanup of things that were affected. Here is another set. Basically the rtentry structure has (now had) an entry rt_ifp. this is a problem because what it REALLY is linked to is an ifaddr, which (usually) is linked to an ifnet. In the case where an address if taken away from an interface, there can remain floating references to this ifaddr, which can be cleaned up as encountered, however the ifnet pointer bypases this and continues to point to the ifnet that the adress was originally made on. This may no longer be a valid assumption, especially in the light of interfaces becoming transient opjects. (due to removable hardware, or virtual interfaces on multiple channnel links e.g. frame relay). This set of patches totally removes the (historical) ifnet direct pointer from the rtentry struct, (replacing it with a dummy for spacing) and uses the sequence rt_ifa->ifa_ifp instead.. there are several problems: 1/ rt_ifa must not be null for this to not core-dump.. I have added many test for this case, and hopefully they make sense.. (I NEED FEEDBACK ON WHAT I HAVE DONE HERE) 2/ rtalloc (and friends) now ensure that when they return an entry they check to see that this is valid, so immediatly after an rtalloc(), it is safe to assume that it is non NULL. comments? --------------62319AC452BFA1D76201DD56 Content-Type: text/plain; charset=us-ascii; name="netdiffs" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="netdiffs" ? netgraph/copyright ? netgraph/rm_interface.patches Index: net/if.c =================================================================== RCS file: /cvs/freebsd/src/sys/net/if.c,v retrieving revision 1.36 diff -u -r1.36 if.c --- 1.36 1996/08/07 04:09:05 +++ if.c 1997/02/26 23:26:47 @@ -363,15 +363,12 @@ if_up(ifp) register struct ifnet *ifp; { + register struct ifaddr *ifa; ifp->if_flags |= IFF_UP; microtime(&ifp->if_lastchange); -#ifdef notyet - register struct ifaddr *ifa; - /* this has no effect on IP, and will kill all iso connections XXX */ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) pfctlinput(PRC_IFUP, ifa->ifa_addr); -#endif rt_ifmsg(ifp); } Index: net/if_loop.c =================================================================== RCS file: /cvs/freebsd/src/sys/net/if_loop.c,v retrieving revision 1.22 diff -u -r1.22 if_loop.c --- 1.22 1996/06/19 16:24:10 +++ if_loop.c 1997/02/26 23:26:47 @@ -233,8 +233,8 @@ struct rtentry *rt; struct sockaddr *sa; { - if (rt) { - rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */ + if (rt) { /* XXX should check for null pointers here */ + rt->rt_rmx.rmx_mtu = rt->rt_ifa->ifa_ifp->if_mtu; /* for ISO */ /* * For optimal performance, the send and receive buffers * should be at least twice the MTU plus a little more for Index: net/if_tun.h =================================================================== RCS file: /cvs/freebsd/src/sys/net/if_tun.h,v retrieving revision 1.6.2.2 diff -u -r1.6.2.2 if_tun.h --- 1.6.2.2 1996/12/04 19:07:52 +++ if_tun.h 1997/02/26 23:26:47 @@ -39,7 +39,7 @@ }; /* Maximum packet size */ -#define TUNMTU 1500 +#define TUNMTU 1600 struct tuninfo { int baudrate; /* linespeed */ Index: net/route.c =================================================================== RCS file: /cvs/freebsd/src/sys/net/route.c,v retrieving revision 1.37 diff -u -r1.37 route.c --- 1.37 1996/09/10 07:10:05 +++ route.c 1997/02/26 23:26:47 @@ -93,8 +93,19 @@ rtalloc(ro) register struct route *ro; { - if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) + if (ro->ro_rt && ro->ro_rt->rt_ifa + && (ro->ro_rt->rt_ifa->ifa_ifp) + && (ro->ro_rt->rt_flags & RTF_UP)) return; /* XXX */ + /* + * check to see if the reason we got here was due to an + * out of date route/ifaddr. + */ + if(ro->ro_rt && ro->ro_rt->rt_ifa + && (ro->ro_rt->rt_ifa->ifa_ifp == NULL)) { + IFAFREE(ro->ro_rt->rt_ifa); + /* XXX shouldn't we free the rt? */ + } ro->ro_rt = rtalloc1(&ro->ro_dst, 1, 0UL); } @@ -103,8 +114,19 @@ register struct route *ro; u_long ignore; { - if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) + if (ro->ro_rt && ro->ro_rt->rt_ifa + && (ro->ro_rt->rt_ifa->ifa_ifp) + && (ro->ro_rt->rt_flags & RTF_UP)) return; /* XXX */ + /* + * check to see if the reason we got here was due to an + * out of date route/ifaddr. + */ + if(ro->ro_rt && ro->ro_rt->rt_ifa + && (ro->ro_rt->rt_ifa->ifa_ifp == NULL)) { + IFAFREE(ro->ro_rt->rt_ifa); + /* XXX shouldn't we free the rt? */ + } ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore); } @@ -113,22 +135,23 @@ * Or, at least try.. Create a cloned route if needed. */ struct rtentry * -rtalloc1(dst, report, ignflags) - register struct sockaddr *dst; - int report; - u_long ignflags; +rtalloc1(struct sockaddr *dst, int report, u_long ignflags) { register struct radix_node_head *rnh = rt_tables[dst->sa_family]; register struct rtentry *rt; register struct radix_node *rn; - struct rtentry *newrt = 0; + struct rtentry *newrt; struct rt_addrinfo info; u_long nflags; - int s = splnet(), err = 0, msgtype = RTM_MISS; + int s, err = 0, msgtype = RTM_MISS; + + s = splnet(); /* * Look up the address in the table for that Address Family */ +retry: + newrt = NULL; if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) && ((rn->rn_flags & RNF_ROOT) == 0)) { /* @@ -136,6 +159,22 @@ * get a refernce on the rtentry associated. */ newrt = rt = (struct rtentry *)rn; + /* + * hosekeeping: + * Check that this doesn't refer to an ifaddr + * that is now invalid. + */ + if ((rt->rt_ifa == NULL) || (rt->rt_ifa->ifa_ifp == NULL)) { + if ( rt->rt_ifa ) { + IFAFREE( rt->rt_ifa ); + rt->rt_ifa = NULL; + } + /* + * throw this out of the tree! + */ + rtfree(rt); + goto retry; + } nflags = rt->rt_flags & ~ignflags; if (report && (nflags & (RTF_CLONING | RTF_PRCLONING))) { /* @@ -533,7 +572,8 @@ */ ifa->ifa_refcnt++; rt->rt_ifa = ifa; - rt->rt_ifp = ifa->ifa_ifp; + rt->rt_ifx = NULL; + /* rt->rt_ifp = ifa->ifa_ifp; */ /* XXX get rid of this */ rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask, rnh, rt->rt_nodes); @@ -940,7 +980,7 @@ * we are adding. */ rt->rt_ifa = ifa; - rt->rt_ifp = ifa->ifa_ifp; + rt->rt_ifx = NULL ; /* get rid of this asap */ /*XXX*/ ifa->ifa_refcnt++; /* * Now add it to the routing table Index: net/route.h =================================================================== RCS file: /cvs/freebsd/src/sys/net/route.h,v retrieving revision 1.23 diff -u -r1.23 route.h --- 1.23 1996/10/09 18:35:10 +++ route.h 1997/02/26 23:26:47 @@ -104,7 +104,7 @@ short rt_filler; /* was short flags field */ short rt_refcnt; /* # held references */ u_long rt_flags; /* up/down?, host/net */ - struct ifnet *rt_ifp; /* the answer: interface to use */ + struct ifnet *rt_ifx; /* the answer: interface to use */ struct ifaddr *rt_ifa; /* the answer: interface to use */ struct sockaddr *rt_genmask; /* for generation of cloned routes */ caddr_t rt_llinfo; /* pointer to link level info cache */ Index: net/rtsock.c =================================================================== RCS file: /cvs/freebsd/src/sys/net/rtsock.c,v retrieving revision 1.20 diff -u -r1.20 rtsock.c --- 1.20 1996/07/10 01:34:36 +++ rtsock.c 1997/02/26 23:26:47 @@ -233,7 +233,9 @@ netmask = rt_mask(rt); genmask = rt->rt_genmask; if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) { - ifp = rt->rt_ifp; + ifp = NULL; + if (rt->rt_ifa) + ifp = rt->rt_ifa->ifa_ifp; if (ifp) { ifpaddr = ifp->if_addrlist->ifa_addr; ifaaddr = rt->rt_ifa->ifa_addr; @@ -294,7 +296,7 @@ IFAFREE(rt->rt_ifa); rt->rt_ifa = ifa; ifa->ifa_refcnt++; - rt->rt_ifp = ifp; + rt->rt_ifx = NULL; /* XXX kill me */ } } rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx, @@ -665,7 +667,8 @@ rtm->rtm_flags = rt->rt_flags; rtm->rtm_use = rt->rt_use; rtm->rtm_rmx = rt->rt_rmx; - rtm->rtm_index = rt->rt_ifp->if_index; + rtm->rtm_index = ((rt->rt_ifa)? + (rt->rt_ifa->ifa_ifp->if_index) : (0)); rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0; rtm->rtm_addrs = info.rti_addrs; error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size); Index: netatalk/at_extern.h =================================================================== RCS file: /cvs/freebsd/src/sys/netatalk/at_extern.h,v retrieving revision 1.1 diff -u -r1.1 at_extern.h --- 1.1 1996/05/24 01:35:23 +++ at_extern.h 1997/02/26 23:26:47 @@ -27,7 +27,9 @@ extern struct ifaddr *at_ifawithnet __P((struct sockaddr_at *, struct ifaddr *)); #ifdef _NETATALK_DDP_VAR_H_ -extern int ddp_output __P(( struct ddpcb *ddp, struct mbuf *m)); +extern int ddp_output __P((struct mbuf *m, struct socket *so)); + +/*extern int ddp_output __P(( struct ddpcb *ddp, struct mbuf *m));*/ #endif #if defined (_NETATALK_DDP_VAR_H_) && defined(_NETATALK_AT_VAR_H_) extern struct ddpcb *ddp_search __P((struct sockaddr_at *, Index: netatalk/at_proto.c =================================================================== RCS file: /cvs/freebsd/src/sys/netatalk/at_proto.c,v retrieving revision 1.4 diff -u -r1.4 at_proto.c --- 1.4 1996/09/10 08:23:10 +++ at_proto.c 1997/02/26 23:26:47 @@ -54,7 +54,10 @@ * pr_output can be used by higher level appletalk protocols, should * they be included in the kernel. */ - 0, ddp_output, 0, 0, + 0, +ddp_output, +0, +0, /* socket-protocol interface. */ ddp_usrreq, /* utility routines. */ Index: netatalk/ddp_input.c =================================================================== RCS file: /cvs/freebsd/src/sys/netatalk/ddp_input.c,v retrieving revision 1.3 diff -u -r1.3 ddp_input.c --- 1.3 1996/09/10 08:23:11 +++ ddp_input.c 1997/02/26 23:26:47 @@ -253,7 +253,8 @@ forwro.ro_rt = (struct rtentry *)0; } if ( forwro.ro_rt == (struct rtentry *)0 || - forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) { + forwro.ro_rt->rt_ifa == (struct ifaddr *)0 || + forwro.ro_rt->rt_ifa->ifa_ifp == (struct ifnet *)0 ) { forwro.ro_dst.sa_len = sizeof( struct sockaddr_at ); forwro.ro_dst.sa_family = AF_APPLETALK; satosat( &forwro.ro_dst )->sat_addr.s_net = to.sat_addr.s_net; @@ -268,7 +269,9 @@ } if ( ddp_firewall && - ( forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp != ifp )) { + ( forwro.ro_rt == NULL + || forwro.ro_rt->rt_ifa == NULL + || forwro.ro_rt->rt_ifa->ifa_ifp != ifp )) { m_freem( m ); return; } Index: netatalk/ddp_output.c =================================================================== RCS file: /cvs/freebsd/src/sys/netatalk/ddp_output.c,v retrieving revision 1.3 diff -u -r1.3 ddp_output.c --- 1.3 1996/09/10 08:23:13 +++ ddp_output.c 1997/02/26 23:26:47 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -46,9 +47,11 @@ int ddp_cksum = 1; int -ddp_output( struct ddpcb *ddp, struct mbuf *m) +/*ddp_output( struct ddpcb *ddp, struct mbuf *m)*/ +ddp_output( struct mbuf *m, struct socket *so) { struct ddpehdr *deh; + struct ddpcb *ddp = sotoddpcb( so ); M_PREPEND( m, sizeof( struct ddpehdr ), M_WAIT ); @@ -116,7 +119,8 @@ struct ifnet *ifp = NULL; u_short net; - if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) { + if ( ro->ro_rt && ro->ro_rt->rt_ifa + && (ifp = ro->ro_rt->rt_ifa->ifa_ifp )) { net = satosat( ro->ro_rt->rt_gateway )->sat_addr.s_net; for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { if ( aa->aa_ifp == ifp && Index: netatalk/ddp_usrreq.c =================================================================== RCS file: /cvs/freebsd/src/sys/netatalk/ddp_usrreq.c,v retrieving revision 1.4 diff -u -r1.4 ddp_usrreq.c --- 1.4 1996/09/10 08:23:15 +++ ddp_usrreq.c 1997/02/26 23:26:48 @@ -133,7 +133,7 @@ } } - error = ddp_output( ddp, m ); + error = ddp_output( m, so ); m = NULL; if ( addr ) { at_pcbdisconnect( ddp ); @@ -331,7 +331,8 @@ net = sat->sat_addr.s_net; } aa = 0; - if ( ifp = ro->ro_rt->rt_ifp ) { + if ( ro->ro_rt && ro->ro_rt->rt_ifa + && (ifp = ro->ro_rt->rt_ifa->ifa_ifp)) { for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { if ( aa->aa_ifp == ifp && ntohs( net ) >= ntohs( aa->aa_firstnet ) && @@ -352,8 +353,9 @@ /* * If we've got no route for this interface, try to find one. */ - if ( ro->ro_rt == (struct rtentry *)0 || - ro->ro_rt->rt_ifp == (struct ifnet *)0 ) { + if ( ro->ro_rt == NULL || + ro->ro_rt->rt_ifa == NULL || + ro->ro_rt->rt_ifa->ifa_ifp == NULL ) { ro->ro_dst.sa_len = sizeof( struct sockaddr_at ); ro->ro_dst.sa_family = AF_APPLETALK; if ( hintnet ) { @@ -369,7 +371,8 @@ * Make sure any route that we have has a valid interface. */ aa = 0; - if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) { + if ( ro->ro_rt && ro->ro_rt->rt_ifa + && ( ifp = ro->ro_rt->rt_ifa->ifa_ifp )) { for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { if ( aa->aa_ifp == ifp ) { break; Index: netinet/if_ether.c =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/if_ether.c,v retrieving revision 1.34.2.1 diff -u -r1.34.2.1 if_ether.c --- 1.34.2.1 1996/11/16 21:17:49 +++ if_ether.c 1997/02/26 23:26:48 @@ -154,6 +154,16 @@ } if (rt->rt_flags & RTF_GATEWAY) return; + /* XXX + * not sure what to do here.. + * We've come in here with an rt that points ot an invalid ifaddr.. + * if we don't do this here, we need to test it in 7 places below. + */ + if (rt->rt_ifa->ifa_ifp == NULL ) { + IFAFREE(rt->rt_ifa); + rt->rt_ifa = NULL; + req = RTM_DELETE; /* XXX */ + } switch (req) { case RTM_ADD: @@ -172,14 +182,14 @@ rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl); gate = rt->rt_gateway; - SDL(gate)->sdl_type = rt->rt_ifp->if_type; - SDL(gate)->sdl_index = rt->rt_ifp->if_index; + SDL(gate)->sdl_type = rt->rt_ifa->ifa_ifp->if_type; + SDL(gate)->sdl_index = rt->rt_ifa->ifa_ifp->if_index; rt->rt_expire = time.tv_sec; break; } /* Announce a new entry if requested. */ if (rt->rt_flags & RTF_ANNOUNCE) - arprequest((struct arpcom *)rt->rt_ifp, + arprequest((struct arpcom *)rt->rt_ifa->ifa_ifp, &SIN(rt_key(rt))->sin_addr.s_addr, &SIN(rt_key(rt))->sin_addr.s_addr, (u_char *)LLADDR(SDL(gate))); @@ -190,8 +200,8 @@ log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n"); break; } - SDL(gate)->sdl_type = rt->rt_ifp->if_type; - SDL(gate)->sdl_index = rt->rt_ifp->if_index; + SDL(gate)->sdl_type = rt->rt_ifa->ifa_ifp->if_type; + SDL(gate)->sdl_index = rt->rt_ifa->ifa_ifp->if_index; if (la != 0) break; /* This happens on a route change */ /* @@ -221,7 +231,8 @@ SDL(gate)->sdl_alen = 6; rt->rt_expire = 0; } - if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) { + if (in_broadcast(SIN(rt_key(rt))->sin_addr, + rt->rt_ifa->ifa_ifp)) { memcpy(LLADDR(SDL(gate)), etherbroadcastaddr, 6); SDL(gate)->sdl_alen = 6; rt->rt_expire = 0; @@ -240,11 +251,10 @@ * the route to force traffic out to the hardware. */ rt->rt_expire = 0; - Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr, + Bcopy(((struct arpcom *)rt->rt_ifa->ifa_ifp)->ac_enaddr, LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6); if (useloopback) - rt->rt_ifp = loif; - + rt->rt_ifa = loif->if_addrlist; /* XXX */ } break; @@ -535,7 +545,7 @@ * as this one came out of, or we'll get into a fight * over who claims what Ether address. */ - if (rt->rt_ifp == &ac->ac_if) { + if (rt->rt_ifa && (rt->rt_ifa->ifa_ifp == &ac->ac_if)) { rtfree(rt); m_freem(m); return; Index: netinet/in.c =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/in.c,v retrieving revision 1.25 diff -u -r1.25 in.c --- 1.25 1996/09/09 20:17:24 +++ in.c 1997/02/26 23:26:48 @@ -70,7 +70,6 @@ static void in_socktrim __P((struct sockaddr_in *)); static int in_ifinit __P((struct ifnet *, struct in_ifaddr *, struct sockaddr_in *, int)); -static void in_ifscrub __P((struct ifnet *, struct in_ifaddr *)); static int subnetsarelocal = 0; SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW, @@ -453,7 +452,7 @@ /* * Delete any existing route for an interface. */ -static void +void in_ifscrub(ifp, ia) register struct ifnet *ifp; register struct in_ifaddr *ia; Index: netinet/in_pcb.c =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/in_pcb.c,v retrieving revision 1.23 diff -u -r1.23 in_pcb.c --- 1.23 1996/10/30 06:13:09 +++ in_pcb.c 1997/02/26 23:26:48 @@ -324,7 +324,8 @@ } if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ (ro->ro_rt == (struct rtentry *)0 || - ro->ro_rt->rt_ifp == (struct ifnet *)0)) { + ro->ro_rt->rt_ifa == (struct ifaddr *)0 || + ro->ro_rt->rt_ifa->ifa_ifp == (struct ifnet *)0)) { /* No route yet, so try to acquire one */ ro->ro_dst.sa_family = AF_INET; ro->ro_dst.sa_len = sizeof(struct sockaddr_in); @@ -338,7 +339,8 @@ * unless it is the loopback (in case a route * to our address on another net goes to loopback). */ - if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK)) + if (ro->ro_rt && + !(ro->ro_rt->rt_ifa->ifa_ifp->if_flags & IFF_LOOPBACK)) ia = ifatoia(ro->ro_rt->rt_ifa); if (ia == 0) { u_short fport = sin->sin_port; Index: netinet/in_proto.c =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/in_proto.c,v retrieving revision 1.33 diff -u -r1.33 in_proto.c --- 1.33 1996/07/11 16:32:31 +++ in_proto.c 1997/02/26 23:26:48 @@ -110,7 +110,7 @@ &tcp_usrreqs }, { SOCK_RAW, &inetdomain, IPPROTO_RAW, PR_ATOMIC|PR_ADDR, - rip_input, 0, 0, rip_ctloutput, + rip_input, 0, rip_ctlinput, rip_ctloutput, rip_usrreq, 0, 0, 0, 0, }, Index: netinet/in_rmx.c =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/in_rmx.c,v retrieving revision 1.26 diff -u -r1.26 in_rmx.c --- 1.26 1996/06/20 15:41:23 +++ in_rmx.c 1997/02/26 23:26:48 @@ -108,7 +108,7 @@ * is done above.) */ if (rt->rt_flags & RTF_HOST) { - if (in_broadcast(sin->sin_addr, rt->rt_ifp)) { + if (in_broadcast(sin->sin_addr, rt->rt_ifa->ifa_ifp)) { rt->rt_flags |= RTF_BROADCAST; } else { #define satosin(sa) ((struct sockaddr_in *)sa) @@ -137,8 +137,8 @@ rt->rt_rmx.rmx_recvpipe = tcp_recvspace; if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU) - && rt->rt_ifp) - rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; + && rt->rt_ifa && rt->rt_ifa->ifa_ifp ) + rt->rt_rmx.rmx_mtu = rt->rt_ifa->ifa_ifp->if_mtu; ret = rn_addroute(v_arg, n_arg, head, treenodes); if (ret == NULL && rt->rt_flags & RTF_HOST) { @@ -382,3 +382,44 @@ return 1; } + +/* + * This zaps old routes when the interface goes down. + */ +struct in_ifadown_arg { + struct radix_node_head *rnh; + struct ifaddr *ifa; +}; + +static int +in_ifadownkill(struct radix_node *rn, void *xap) +{ + struct in_ifadown_arg *ap = xap; + struct rtentry *rt = (struct rtentry *)rn; + int err; + + if (rt->rt_ifa == ap->ifa) { + err = rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), + rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); + if (err) { + log(LOG_WARNING, "in_ifadownkill: error %d\n", err); + } + } + return 0; +} + +int +in_ifadown(struct ifaddr *ifa) +{ + struct in_ifadown_arg arg; + struct radix_node_head *rnh; + + if (ifa->ifa_addr->sa_family != AF_INET) + return 1; + + arg.rnh = rnh = rt_tables[AF_INET]; + arg.ifa = ifa; + rnh->rnh_walktree(rnh, in_ifadownkill, &arg); + ifa->ifa_flags &= ~IFA_ROUTE; + return 0; +} Index: netinet/in_var.h =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/in_var.h,v retrieving revision 1.17 diff -u -r1.17 in_var.h --- 1.17 1996/03/14 16:59:19 +++ in_var.h 1997/02/26 23:26:48 @@ -229,6 +229,8 @@ int in_control __P((struct socket *, u_long, caddr_t, struct ifnet *)); void in_rtqdrain __P((void)); void ip_input __P((struct mbuf *)); +int in_ifadown __P((struct ifaddr *ifa)); +void in_ifscrub __P((struct ifnet *, struct in_ifaddr *)); #endif /* KERNEL */ Index: netinet/ip_icmp.c =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/ip_icmp.c,v retrieving revision 1.22 diff -u -r1.22 ip_icmp.c --- 1.22 1996/09/20 08:23:54 +++ ip_icmp.c 1997/02/26 23:26:48 @@ -350,7 +350,8 @@ #endif if (mtu < 296) { /* rt->rt_rmx.rmx_mtu = - rt->rt_ifp->if_mtu; */ + rt->rt_ifa->ifa_ifp->if_mtu; */ +/*XXX what if rt->rt_ifa->ifa_ifp is NULL? */ rt->rt_rmx.rmx_locks |= RTV_MTU; } else if (rt->rt_rmx.rmx_mtu > mtu) { rt->rt_rmx.rmx_mtu = mtu; Index: netinet/ip_input.c =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/ip_input.c,v retrieving revision 1.50.2.1 diff -u -r1.50.2.1 ip_input.c --- 1.50.2.1 1996/11/11 23:40:45 +++ ip_input.c 1997/02/26 23:26:48 @@ -1244,7 +1244,7 @@ * or a route modified by a redirect. */ #define satosin(sa) ((struct sockaddr_in *)(sa)) - if (rt->rt_ifp == m->m_pkthdr.rcvif && + if (rt->rt_ifa && (rt->rt_ifa->ifa_ifp == m->m_pkthdr.rcvif) && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && satosin(rt_key(rt))->sin_addr.s_addr != 0 && ipsendredirects && !srcrt) { @@ -1303,8 +1303,8 @@ case EMSGSIZE: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; - if (ipforward_rt.ro_rt) - destifp = ipforward_rt.ro_rt->rt_ifp; + if (ipforward_rt.ro_rt && ipforward_rt.ro_rt->rt_ifa) + destifp = ipforward_rt.ro_rt->rt_ifa->ifa_ifp; ipstat.ips_cantfrag++; break; Index: netinet/ip_output.c =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/ip_output.c,v retrieving revision 1.44.2.1 diff -u -r1.44.2.1 ip_output.c --- 1.44.2.1 1996/11/11 23:40:49 +++ ip_output.c 1997/02/26 23:26:48 @@ -171,7 +171,8 @@ * the link layer, as this is probably required in all cases * for correct operation (as it is for ARP). */ - if (ro->ro_rt == 0) + if (ro->ro_rt == 0 || ro->ro_rt->rt_ifa == NULL || + ro->ro_rt->rt_ifa->ifa_ifp == NULL) rtalloc_ign(ro, RTF_PRCLONING); if (ro->ro_rt == 0) { ipstat.ips_noroute++; @@ -179,7 +180,7 @@ goto bad; } ia = ifatoia(ro->ro_rt->rt_ifa); - ifp = ro->ro_rt->rt_ifp; + ifp = ro->ro_rt->rt_ifa->ifa_ifp; ro->ro_rt->rt_use++; if (ro->ro_rt->rt_flags & RTF_GATEWAY) dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; @@ -1052,10 +1053,9 @@ splx(s); break; } - ifp = ro.ro_rt->rt_ifp; + ifp = ro.ro_rt->rt_ifa->ifa_ifp; rtfree(ro.ro_rt); - } - else { + } else { INADDR_TO_IFP(mreq->imr_interface, ifp); } Index: netinet/ip_var.h =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/ip_var.h,v retrieving revision 1.24.2.2 diff -u -r1.24.2.2 ip_var.h --- 1.24.2.2 1996/11/12 11:28:59 +++ ip_var.h 1997/02/26 23:26:48 @@ -185,6 +185,7 @@ ip_srcroute __P((void)); void ip_stripoptions __P((struct mbuf *, struct mbuf *)); int rip_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); +void rip_ctlinput __P((int, struct sockaddr *, void *)); void rip_init __P((void)); void rip_input __P((struct mbuf *, int)); int rip_output __P((struct mbuf *, struct socket *, u_long)); Index: netinet/raw_ip.c =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/raw_ip.c,v retrieving revision 1.37.2.1 diff -u -r1.37.2.1 raw_ip.c --- 1.37.2.1 1996/11/11 23:40:55 +++ raw_ip.c 1997/02/26 23:26:48 @@ -314,6 +314,70 @@ return (ip_ctloutput(op, so, level, optname, m)); } +/* + * This function exists solely to receive the PRC_IFDOWN messages which + * are sent by if_down(). It looks for an ifaddr whose ifa_addr is sa, + * and calls in_ifadown() to remove all routes corresponding to that address. + * It also receives the PRC_IFUP messages from if_up() and reinstalls the + * interface routes. + */ +void +rip_ctlinput(cmd, sa, vip) + int cmd; + struct sockaddr *sa; + void *vip; +{ + struct in_ifaddr *ia; + struct ifnet *ifp; + int err; + int flags; + + switch(cmd) { + case PRC_IFDOWN: + for (ia = in_ifaddr; ia; ia = ia->ia_next) + /*for (ia = in_ifaddrhead.tqh_first; ia; + ia = ia->ia_link.tqe_next)*/ { + if (ia->ia_ifa.ifa_addr == sa + && (ia->ia_flags & IFA_ROUTE)) { + /* + * in_ifscrub kills the interface route. + */ + in_ifscrub(ia->ia_ifp, ia); + /* + * in_ifadown gets rid of all the rest of + * the routes. This is not quite the right + * thing to do, but at least if we are running + * a routing process they will come back. + */ + in_ifadown(&ia->ia_ifa); + break; + } + } + break; + + case PRC_IFUP: + for (ia = in_ifaddr; ia; ia = ia->ia_next) + /*for (ia = in_ifaddrhead.tqh_first; ia; + ia = ia->ia_link.tqe_next)*/ { + if (ia->ia_ifa.ifa_addr == sa) + break; + } + if (ia == 0 || (ia->ia_flags & IFA_ROUTE)) + return; + flags = RTF_UP; + ifp = ia->ia_ifa.ifa_ifp; + + if ((ifp->if_flags & IFF_LOOPBACK) + || (ifp->if_flags & IFF_POINTOPOINT)) + flags |= RTF_HOST; + + err = rtinit(&ia->ia_ifa, RTM_ADD, flags); + if (err == 0) + ia->ia_flags |= IFA_ROUTE; + break; + } +} + static u_long rip_sendspace = RIPSNDQ; /* XXX sysctl ? */ static u_long rip_recvspace = RIPRCVQ; /* XXX sysctl ? */ Index: netinet/tcp_input.c =================================================================== RCS file: /cvs/freebsd/src/sys/netinet/tcp_input.c,v retrieving revision 1.54.2.1 diff -u -r1.54.2.1 tcp_input.c --- 1.54.2.1 1996/11/11 23:40:57 +++ tcp_input.c 1997/02/26 23:26:48 @@ -1971,7 +1971,8 @@ tp->t_maxopd = tp->t_maxseg = tcp_mssdflt; return; } - ifp = rt->rt_ifp; +/* XXX assume at this time that tcp_rtlookup() will ensure thai is safe */ + ifp = rt->rt_ifa->ifa_ifp; so = inp->inp_socket; taop = rmx_taop(rt->rt_rmx); @@ -2124,9 +2125,9 @@ struct rtentry *rt; rt = tcp_rtlookup(tp->t_inpcb); - if (rt == NULL) + if (rt == NULL || rt->rt_ifa->ifa_ifp == NULL) return tcp_mssdflt; - return rt->rt_ifp->if_mtu - sizeof(struct tcpiphdr); + return rt->rt_ifa->ifa_ifp->if_mtu - sizeof(struct tcpiphdr); } #endif /* TUBA_INCLUDE */ Index: netipx/ipx_input.c =================================================================== RCS file: /cvs/freebsd/src/sys/netipx/ipx_input.c,v retrieving revision 1.9 diff -u -r1.9 ipx_input.c --- 1.9 1996/08/18 08:38:15 +++ ipx_input.c 1997/02/26 23:26:48 @@ -390,9 +390,11 @@ goto cleanup; } if (ipx_droute.ro_rt && - (ifp=ipx_droute.ro_rt->rt_ifp) && + ipx_droute.ro_rt->rt_ifa && + (ifp=ipx_droute.ro_rt->rt_ifa->ifa_ifp) && ipx_sroute.ro_rt && - (ifp!=ipx_sroute.ro_rt->rt_ifp)) { + ipx_sroute.ro_rt->rt_ifa && + (ifp!=ipx_sroute.ro_rt->rt_ifa->ifa_ifp)) { flags |= IPX_ALLOWBROADCAST; } else { type = IPX_ERR_UNREACH_HOST, code = 0; @@ -476,7 +478,8 @@ dst->sipx_addr = *src; dst->sipx_addr.x_port = 0; rtalloc(ro); - if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) { + if (ro->ro_rt == 0 || ro->ro_rt->rt_ifa == 0 + || ro->ro_rt->rt_ifa->ifa_ifp ) { return (0); } ro->ro_rt->rt_use++; Index: netipx/ipx_ip.c =================================================================== RCS file: /cvs/freebsd/src/sys/netipx/ipx_ip.c,v retrieving revision 1.9 diff -u -r1.9 ipx_ip.c --- 1.9 1996/06/12 05:10:27 +++ ipx_ip.c 1997/02/26 23:26:48 @@ -322,7 +322,8 @@ bzero((caddr_t)&ro, sizeof (ro)); ro.ro_dst = *(struct sockaddr *)ip_dst; rtalloc(&ro); - if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) { + if (ro.ro_rt == 0 || ro.ro_rt->rt_ifa == 0 + || ro.ro_rt->rt_ifa->ifa_ifp == 0) { return (ENETUNREACH); } @@ -332,7 +333,7 @@ */ { register struct in_ifaddr *ia; - struct ifnet *ifp = ro.ro_rt->rt_ifp; + struct ifnet *ifp = ro.ro_rt->rt_ifa->ifa_ifp; for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) Index: netipx/ipx_outputfl.c =================================================================== RCS file: /cvs/freebsd/src/sys/netipx/ipx_outputfl.c,v retrieving revision 1.4 diff -u -r1.4 ipx_outputfl.c --- 1.4 1996/03/11 15:13:52 +++ ipx_outputfl.c 1997/02/26 23:26:49 @@ -115,7 +115,8 @@ ro->ro_rt = NULL; rtalloc(ro); } - if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { + if (ro->ro_rt == 0 || ro->ro_rt->rt_ifa == 0 + || (ifp = ro->ro_rt->rt_ifa->ifa_ifp) == 0) { error = ENETUNREACH; goto bad; } Index: netipx/ipx_pcb.c =================================================================== RCS file: /cvs/freebsd/src/sys/netipx/ipx_pcb.c,v retrieving revision 1.5 diff -u -r1.5 ipx_pcb.c --- 1.5 1996/03/11 15:13:53 +++ ipx_pcb.c 1997/02/26 23:26:49 @@ -173,7 +173,8 @@ ipxp->ipxp_lastdst = sipx->sipx_addr; if ((ipxp->ipxp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ (ro->ro_rt == (struct rtentry *)0 || - ro->ro_rt->rt_ifp == (struct ifnet *)0)) { + ro->ro_rt->rt_ifa == (struct ifaddr *)0 || + ro->ro_rt->rt_ifa->ifa_ifp == (struct ifnet *)0)) { /* No route yet, so try to acquire one */ ro->ro_dst.sa_family = AF_IPX; ro->ro_dst.sa_len = sizeof(ro->ro_dst); @@ -192,7 +193,8 @@ * If we found a route, use the address * corresponding to the outgoing interface */ - if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp)) + if (ro->ro_rt && ro->ro_rt->rt_ifa + && (ifp = ro->ro_rt->rt_ifa->ifa_ifp)) for (ia = ipx_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; Index: netkey/key_debug.c =================================================================== RCS file: /cvs/freebsd/src/sys/netkey/key_debug.c,v retrieving revision 1.1 diff -u -r1.1 key_debug.c --- 1.1 1996/06/14 17:22:05 +++ key_debug.c 1997/02/26 23:26:49 @@ -539,8 +539,6 @@ printf("rt_rmx.rmx_mtu = %d ",rt->rt_rmx.rmx_mtu); printf("rt_refcnt = %d ",rt->rt_refcnt); printf("rt_flags = 0x%x\n",rt->rt_flags); - printf("rt_ifp is:\n"); - dump_ifp(rt->rt_ifp); printf("rt_ifa is:\n"); dump_ifa(rt->rt_ifa); } Index: netns/ns_input.c =================================================================== RCS file: /cvs/freebsd/src/sys/netns/ns_input.c,v retrieving revision 1.8 diff -u -r1.8 ns_input.c --- 1.8 1996/10/17 18:41:59 +++ ns_input.c 1997/02/26 23:26:49 @@ -367,9 +367,11 @@ goto cleanup; } if (idp_droute.ro_rt && - (ifp=idp_droute.ro_rt->rt_ifp) && + idp_droute.ro_rt->rt_ifa && + (ifp=idp_droute.ro_rt->rt_ifa->ifa_ifp) && idp_sroute.ro_rt && - (ifp!=idp_sroute.ro_rt->rt_ifp)) { + idp_sroute.ro_rt->rt_ifa && + (ifp!=idp_sroute.ro_rt->rt_ifa->ifa_ifp)) { flags |= NS_ALLOWBROADCAST; } else { type = NS_ERR_UNREACH_HOST, code = 0; @@ -442,7 +444,7 @@ dst->sns_addr = *src; dst->sns_addr.x_port = 0; rtalloc(ro); - if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) { + if (ro->ro_rt == 0 || ro->ro_rt->rt_ifa->ifa_ifp == 0) { return (0); } ro->ro_rt->rt_use++; Index: netns/ns_ip.c =================================================================== RCS file: /cvs/freebsd/src/sys/netns/ns_ip.c,v retrieving revision 1.6 diff -u -r1.6 ns_ip.c --- 1.6 1996/10/17 18:42:02 +++ ns_ip.c 1997/02/26 23:26:49 @@ -330,7 +330,7 @@ bzero((caddr_t)&ro, sizeof (ro)); ro.ro_dst = *(struct sockaddr *)ip_dst; rtalloc(&ro); - if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) { + if (ro.ro_rt == 0 || ro.ro_rt->rt_ifa->ifa_ifp == 0) { return (ENETUNREACH); } @@ -340,7 +340,7 @@ */ { register struct in_ifaddr *ia; - struct ifnet *ifp = ro.ro_rt->rt_ifp; + struct ifnet *ifp = ro.ro_rt->rt_ifa->ifa_ifp; for (ia = in_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) Index: netns/ns_output.c =================================================================== RCS file: /cvs/freebsd/src/sys/netns/ns_output.c,v retrieving revision 1.4 diff -u -r1.4 ns_output.c --- 1.4 1996/10/17 18:42:06 +++ ns_output.c 1997/02/26 23:26:49 @@ -111,7 +111,8 @@ ro->ro_rt = NULL; rtalloc(ro); } - if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) { + if (ro->ro_rt == 0 || ro->ro_rt->rt_ifa == 0 + || (ifp = ro->ro_rt->rt_ifa->ifa_ifp) == 0) { error = ENETUNREACH; goto bad; } Index: netns/ns_pcb.c =================================================================== RCS file: /cvs/freebsd/src/sys/netns/ns_pcb.c,v retrieving revision 1.6 diff -u -r1.6 ns_pcb.c --- 1.6 1996/10/17 18:42:11 +++ ns_pcb.c 1997/02/26 23:26:49 @@ -167,7 +167,8 @@ nsp->nsp_lastdst = sns->sns_addr; if ((nsp->nsp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/ (ro->ro_rt == (struct rtentry *)0 || - ro->ro_rt->rt_ifp == (struct ifnet *)0)) { + ro->ro_rt->rt_ifa == (struct ifaddr *)0 || + ro->ro_rt->rt_ifa->ifa_ifp == (struct ifnet *)0)) { /* No route yet, so try to acquire one */ ro->ro_dst.sa_family = AF_NS; ro->ro_dst.sa_len = sizeof(ro->ro_dst); @@ -186,7 +187,8 @@ * If we found a route, use the address * corresponding to the outgoing interface */ - if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp)) + if (ro->ro_rt && ro->ro_rt->rt_ifa && + (ifp = ro->ro_rt->rt_ifa->ifa_ifp)) for (ia = ns_ifaddr; ia; ia = ia->ia_next) if (ia->ia_ifp == ifp) break; --------------62319AC452BFA1D76201DD56--