summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if.c81
-rw-r--r--sys/net/if.h6
-rw-r--r--sys/net/route.c4
-rw-r--r--sys/net/rtsock.c3
4 files changed, 89 insertions, 5 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 12767ea05ee..f6b668015ae 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.127 2005/06/07 02:45:11 henning Exp $ */
+/* $OpenBSD: if.c,v 1.128 2005/06/07 18:21:44 henning Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -140,6 +140,7 @@ int if_clone_list(struct if_clonereq *);
struct if_clone *if_clone_lookup(const char *, int *);
void if_congestion_clear(void *);
+int if_group_ext_build(void);
TAILQ_HEAD(, ifg_group) ifg_head;
LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
@@ -1717,6 +1718,84 @@ if_getgroup(caddr_t data, struct ifnet *ifp)
return (0);
}
+void
+if_group_routechange(struct sockaddr *dst, struct sockaddr *mask)
+{
+ switch (dst->sa_family) {
+ case AF_INET:
+ if (satosin(dst)->sin_addr.s_addr == INADDR_ANY &&
+ satosin(mask)->sin_addr.s_addr == INADDR_ANY)
+ if_group_ext_build();
+ break;
+ case AF_INET6:
+ if (IN6_ARE_ADDR_EQUAL(&(satosin6(dst))->sin6_addr,
+ &in6addr_any) &&
+ IN6_ARE_ADDR_EQUAL(&(satosin6(mask))->sin6_addr,
+ &in6addr_any))
+ if_group_ext_build();
+ break;
+ }
+}
+
+int
+if_group_ext_build(void)
+{
+ struct ifg_group *ifg;
+ struct ifg_member *ifgm, *next;
+ struct sockaddr_in sa_in;
+ struct sockaddr_in6 sa_in6;
+ struct radix_node_head *rnh;
+ struct radix_node *rn;
+ struct rtentry *rt;
+
+ TAILQ_FOREACH(ifg, &ifg_head, ifg_next)
+ if (!strcmp(ifg->ifg_group, IFG_EXTERNAL))
+ break;
+
+ if (ifg != NULL)
+ for (ifgm = TAILQ_FIRST(&ifg->ifg_members); ifgm; ifgm = next) {
+ next = TAILQ_NEXT(ifgm, ifgm_next);
+ if_delgroup(ifgm->ifgm_ifp, IFG_EXTERNAL);
+ }
+
+ if ((rnh = rt_tables[AF_INET]) == NULL)
+ return (-1);
+
+ bzero(&sa_in, sizeof(sa_in));
+ sa_in.sin_len = sizeof(sa_in);
+ sa_in.sin_family = AF_INET;
+ if ((rn = rnh->rnh_lookup(&sa_in, &sa_in, rnh))) {
+ do {
+ rt = (struct rtentry *)rn;
+ if (rt->rt_ifp)
+ if_addgroup(rt->rt_ifp, IFG_EXTERNAL);
+ if (rn_mpath_capable(rnh))
+ rn = rn_mpath_next(rn);
+ else
+ rn = NULL;
+ } while (rn != NULL);
+ }
+
+#ifdef INET6
+ if ((rnh = rt_tables[AF_INET6]) == NULL)
+ return (-1);
+
+ bcopy(&sa6_any, &sa_in6, sizeof(sa_in6));
+ if ((rn = rnh->rnh_lookup(&sa_in6, &sa_in6, rnh))) {
+ do {
+ rt = (struct rtentry *)rn;
+ if (rt->rt_ifp)
+ if_addgroup(rt->rt_ifp, IFG_EXTERNAL);
+ if (rn_mpath_capable(rnh))
+ rn = rn_mpath_next(rn);
+ else
+ rn = NULL;
+ } while (rn != NULL);
+ }
+#endif
+
+ return (0);
+}
/*
* Set/clear promiscuous mode on interface ifp based on the truth value
diff --git a/sys/net/if.h b/sys/net/if.h
index 96a8f974b7e..97207738034 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.h,v 1.72 2005/06/06 03:44:21 henning Exp $ */
+/* $OpenBSD: if.h,v 1.73 2005/06/07 18:21:44 henning Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -425,7 +425,8 @@ struct if_announcemsghdr {
* interface groups
*/
-#define IFG_ALL "all" /* group containing all interfaces */
+#define IFG_ALL "all" /* group contains all interfaces */
+#define IFG_EXTERNAL "external" /* if(s) default route(s) point to */
struct ifg_group {
char ifg_group[IFNAMSIZ];
@@ -690,6 +691,7 @@ int ifpromisc(struct ifnet *, int);
int if_addgroup(struct ifnet *, const char *);
int if_delgroup(struct ifnet *, const char *);
int if_getgroup(caddr_t, struct ifnet *);
+void if_group_routechange(struct sockaddr *, struct sockaddr *);
struct ifnet *ifunit(const char *);
struct ifaddr *ifa_ifwithaddr(struct sockaddr *);
diff --git a/sys/net/route.c b/sys/net/route.c
index c5864cbcbd0..c5f8baa38a4 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.51 2005/05/15 16:40:09 henning Exp $ */
+/* $OpenBSD: route.c,v 1.52 2005/06/07 18:21:44 henning Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -804,6 +804,8 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
/* clean up any cloned children */
rtflushclone(rnh, rt);
}
+
+ if_group_routechange(dst, netmask);
break;
}
bad:
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 2b52966aac8..9fecef9a33d 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsock.c,v 1.46 2005/05/27 22:37:46 mcbride Exp $ */
+/* $OpenBSD: rtsock.c,v 1.47 2005/06/07 18:21:44 henning Exp $ */
/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
/*
@@ -416,6 +416,7 @@ report:
rt->rt_labelid =
rtlabel_name2id(rtlabel);
}
+ if_group_routechange(dst, netmask);
/* fallthrough */
case RTM_LOCK:
rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);