diff options
| author | 2020-11-07 09:51:40 +0000 | |
|---|---|---|
| committer | 2020-11-07 09:51:40 +0000 | |
| commit | 6950b8803662d3b12a891d7ce6eb4321eeea0695 (patch) | |
| tree | ce7178bb9045b8455aae5b7e52ae62061fa6e1f0 /sys/net/rtsock.c | |
| parent | Add test for ilogb(3). (diff) | |
| download | wireguard-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.c | 47 |
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. */ |
