summaryrefslogtreecommitdiffstats
path: root/sys/net/rtsock.c
diff options
context:
space:
mode:
authordenis <denis@openbsd.org>2020-11-07 09:51:40 +0000
committerdenis <denis@openbsd.org>2020-11-07 09:51:40 +0000
commit6950b8803662d3b12a891d7ce6eb4321eeea0695 (patch)
treece7178bb9045b8455aae5b7e52ae62061fa6e1f0 /sys/net/rtsock.c
parentAdd test for ilogb(3). (diff)
downloadwireguard-openbsd-6950b8803662d3b12a891d7ce6eb4321eeea0695.tar.xz
wireguard-openbsd-6950b8803662d3b12a891d7ce6eb4321eeea0695.zip
Rework source IP address setting.
- Move most of the processing out of rtable.c (reasonnable tb@, ok bluhm@) - Remove memory allocation, store pointer to existing ifaddr - Fix tunnel interface handling looks fine mpi@
Diffstat (limited to 'sys/net/rtsock.c')
-rw-r--r--sys/net/rtsock.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index bed2efff028..65214a9dd1d 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsock.c,v 1.303 2020/10/29 21:15:27 denis Exp $ */
+/* $OpenBSD: rtsock.c,v 1.304 2020/11/07 09:51:40 denis Exp $ */
/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
/*
@@ -138,6 +138,8 @@ int sysctl_iflist(int, struct walkarg *);
int sysctl_ifnames(struct walkarg *);
int sysctl_rtable_rtstat(void *, size_t *, void *);
+int rt_setsource(unsigned int, struct sockaddr *);
+
/*
* Locks used to protect struct members
* I immutable after creation
@@ -860,7 +862,7 @@ route_output(struct mbuf *m, struct socket *so, struct sockaddr *dstaddr,
goto fail;
}
if ((error =
- rtable_setsource(tableid, info.rti_info[RTAX_IFA])) != 0)
+ rt_setsource(tableid, info.rti_info[RTAX_IFA])) != 0)
goto fail;
} else {
error = rtm_output(rtm, &rt, &info, prio, tableid);
@@ -2076,9 +2078,13 @@ sysctl_source(int af, u_int tableid, struct walkarg *w)
case AF_INET:
size = sizeof(struct sockaddr_in);
break;
+#ifdef INET6
case AF_INET6:
size = sizeof(struct sockaddr_in6);
break;
+#endif
+ default:
+ return (0);
}
w->w_needed += size;
if (w->w_where && w->w_needed <= 0) {
@@ -2307,6 +2313,43 @@ rtm_validate_proposal(struct rt_addrinfo *info)
return 0;
}
+int
+rt_setsource(unsigned int rtableid, struct sockaddr *src)
+{
+ struct ifaddr *ifa;
+ /*
+ * If source address is 0.0.0.0 or ::
+ * use automatic source selection
+ */
+ switch(src->sa_family) {
+ case AF_INET:
+ if(satosin(src)->sin_addr.s_addr == INADDR_ANY) {
+ rtable_setsource(rtableid, AF_INET, NULL);
+ return (0);
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (IN6_IS_ADDR_UNSPECIFIED(&satosin6(src)->sin6_addr)) {
+ rtable_setsource(rtableid, AF_INET6, NULL);
+ return (0);
+ }
+ break;
+#endif
+ default:
+ return (EAFNOSUPPORT);
+ }
+
+ /*
+ * Check if source address is assigned to an interface in the
+ * same rdomain
+ */
+ if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL)
+ return (EINVAL);
+
+ return (rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr));
+}
+
/*
* Definitions of protocols supported in the ROUTE domain.
*/