summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/in.c3
-rw-r--r--sys/netinet/in_proto.c2
-rw-r--r--sys/netinet/in_rmx.c50
-rw-r--r--sys/netinet/in_var.h2
-rw-r--r--sys/netinet/ip_var.h1
-rw-r--r--sys/netinet/raw_ip.c64
6 files changed, 117 insertions, 5 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index a52ec77..60bf97a 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -58,7 +58,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,
@@ -366,7 +365,7 @@ in_control(so, cmd, data, ifp)
/*
* Delete any existing route for an interface.
*/
-static void
+void
in_ifscrub(ifp, ia)
register struct ifnet *ifp;
register struct in_ifaddr *ia;
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index 5b66e0d..9a80959 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -116,7 +116,7 @@ struct protosw inetsw[] = {
&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,
},
diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c
index 095afc9..a302c1a 100644
--- a/sys/netinet/in_rmx.c
+++ b/sys/netinet/in_rmx.c
@@ -26,7 +26,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $Id$
*/
/*
@@ -382,3 +382,51 @@ in_inithead(void **head, int off)
return 1;
}
+
+/*
+ * This zaps old routes when the interface goes down.
+ * Currently it doesn't delete static routes; there are
+ * arguments one could make for both behaviors. For the moment,
+ * we will adopt the Principle of Least Surprise and leave them
+ * alone (with the knowledge that this will not be enough for some
+ * people). The ones we really want to get rid of are things like ARP
+ * entries, since the user might down the interface, walk over to a completely
+ * different network, and plug back in.
+ */
+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 && !(rt->rt_flags & RTF_STATIC)) {
+ 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;
+}
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index f760956..dfc08ca 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -219,6 +219,8 @@ void in_delmulti __P((struct in_multi *));
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 */
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 5f595b5..75a60fc 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -186,6 +186,7 @@ struct mbuf *
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));
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index c5382e0..0011ab2 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)raw_ip.c 8.7 (Berkeley) 5/15/95
- * $FreeBSD$
+ * $Id$
*/
#include <sys/param.h>
@@ -314,6 +314,68 @@ rip_ctloutput(op, so, level, optname, m)
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_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_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 ? */
OpenPOWER on IntegriCloud