summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2005-06-07 18:21:45 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2005-06-07 18:21:45 +0000
commitb7e47a80cdc66f2726bd38e4b86ede0e27c29d02 (patch)
treeaed7102a128bb77122f71da6681450c9a562f482
parentf3618e3949557b2911745765284653291329f89d (diff)
introduce a default "external" interface group, containing the interface(s)
the the default route(s) point to. handles IPv4 and IPv6 as well as multipath routes. follows default route changes, of course. eases writing pf rulesets especially on laptops etc. that use different interfaces depending on the environment (wired, wireless, ...) ok theo ryan
-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);