Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Feb 1997 15:39:42 -0800
From:      Julian Elischer <julian@whistle.com>
To:        hackers@freebsd.org
Cc:        julian@alpo.whistle.com
Subject:   [RFC] Networking diffs 
Message-ID:  <3314C9BE.4487EB71@whistle.com>

next in thread | raw e-mail | index | archive | help
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 <sys/systm.h>
 #include <sys/mbuf.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 #include <sys/errno.h>
 #include <sys/syslog.h>
 
@@ -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--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3314C9BE.4487EB71>