summaryrefslogtreecommitdiffstats
path: root/sys/net/rtsock.c
diff options
context:
space:
mode:
authoritojun <itojun@openbsd.org>1999-12-08 06:50:14 +0000
committeritojun <itojun@openbsd.org>1999-12-08 06:50:14 +0000
commit287546ea80ee896bda0c88b8a8c85a1dc6ff37f9 (patch)
treecef428e54b6d2bca56fb9b461aa0667c7fb5f6a2 /sys/net/rtsock.c
parentadd GENERIC.v6 (IPv6 test configuration). to be integrated into GENREIC. (diff)
downloadwireguard-openbsd-287546ea80ee896bda0c88b8a8c85a1dc6ff37f9.tar.xz
wireguard-openbsd-287546ea80ee896bda0c88b8a8c85a1dc6ff37f9.zip
bring in KAME IPv6 code, dated 19991208.
replaces NRL IPv6 layer. reuses NRL pcb layer. no IPsec-on-v6 support. see sys/netinet6/{TODO,IMPLEMENTATION} for more details. GENERIC configuration should work fine as before. GENERIC.v6 works fine as well, but you'll need KAME userland tools to play with IPv6 (will be bringed into soon).
Diffstat (limited to 'sys/net/rtsock.c')
-rw-r--r--sys/net/rtsock.c126
1 files changed, 123 insertions, 3 deletions
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index f842f8be969..57303703912 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1,7 +1,36 @@
-/* $OpenBSD: rtsock.c,v 1.7 1998/08/24 20:39:40 downsj Exp $ */
+/* $OpenBSD: rtsock.c,v 1.8 1999/12/08 06:50:18 itojun Exp $ */
/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
* Copyright (c) 1988, 1991, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -68,6 +97,8 @@ static struct mbuf *
static int rt_msg2 __P((int,
struct rt_addrinfo *, caddr_t, struct walkarg *));
static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
+static void rt_setif __P((struct rtentry *, struct sockaddr *,
+ struct sockaddr *, struct sockaddr *));
/* Sleazy use of local variables throughout file, warning!!!! */
#define dst info.rti_info[RTAX_DST]
@@ -99,6 +130,8 @@ route_usrreq(so, req, m, nam, control)
int af = rp->rcb_proto.sp_protocol;
if (af == AF_INET)
route_cb.ip_count--;
+ else if (af == AF_INET6)
+ route_cb.ip6_count--;
else if (af == AF_NS)
route_cb.ns_count--;
else if (af == AF_ISO)
@@ -129,6 +162,8 @@ route_usrreq(so, req, m, nam, control)
}
if (af == AF_INET)
route_cb.ip_count++;
+ else if (af == AF_INET6)
+ route_cb.ip6_count++;
else if (af == AF_NS)
route_cb.ns_count++;
else if (af == AF_ISO)
@@ -159,7 +194,6 @@ route_output(m, va_alist)
struct rt_addrinfo info;
int len, error = 0;
struct ifnet *ifp = 0;
- struct ifaddr *ifa = 0;
struct socket *so;
va_list ap;
@@ -167,7 +201,7 @@ route_output(m, va_alist)
so = va_arg(ap, struct socket *);
va_end(ap);
-
+ bzero(&info, sizeof(info));
#define senderr(e) { error = e; goto flush;}
if (m == 0 || ((m->m_len < sizeof(int32_t)) &&
(m = m_pullup(m, sizeof(int32_t))) == 0))
@@ -219,6 +253,35 @@ route_output(m, va_alist)
error = rtrequest(RTM_ADD, dst, gate, netmask,
rtm->rtm_flags, &saved_nrt);
if (error == 0 && saved_nrt) {
+ /*
+ * If the route request specified an interface with
+ * IFA and/or IFP, we set the requested interface on
+ * the route with rt_setif. It would be much better
+ * to do this inside rtrequest, but that would
+ * require passing the desired interface, in some
+ * form, to rtrequest. Since rtrequest is called in
+ * so many places (roughly 40 in our source), adding
+ * a parameter is to much for us to swallow; this is
+ * something for the FreeBSD developers to tackle.
+ * Instead, we let rtrequest compute whatever
+ * interface it wants, then come in behind it and
+ * stick in the interface that we really want. This
+ * works reasonably well except when rtrequest can't
+ * figure out what interface to use (with
+ * ifa_withroute) and returns ENETUNREACH. Ideally
+ * it shouldn't matter if rtrequest can't figure out
+ * the interface if we're going to explicitly set it
+ * ourselves anyway. But practically we can't
+ * recover here because rtrequest will not do any of
+ * the work necessary to add the route if it can't
+ * find an interface. As long as there is a default
+ * route that leads to some interface, rtrequest will
+ * find an interface, so this problem should be
+ * rarely encountered.
+ * dwiggins@bbn.com
+ */
+
+ rt_setif(saved_nrt, ifpaddr, ifaaddr, gate);
rt_setmetrics(rtm->rtm_inits,
&rtm->rtm_rmx, &saved_nrt->rt_rmx);
saved_nrt->rt_refcnt--;
@@ -287,6 +350,10 @@ route_output(m, va_alist)
case RTM_CHANGE:
if (gate && rt_setgate(rt, rt_key(rt), gate))
senderr(EDQUOT);
+
+#if 1
+ rt_setif(rt, ifpaddr, ifaaddr, gate);
+#else
/* new gateway could require new ifaddr, ifp;
flags may also be different; ifp may be specified
by ll sockaddr when protocol address is ambiguous */
@@ -310,10 +377,13 @@ route_output(m, va_alist)
rt->rt_ifp = ifp;
}
}
+#endif
rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
&rt->rt_rmx);
+#if 0
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
+#endif
if (genmask)
rt->rt_genmask = genmask;
/*
@@ -387,6 +457,56 @@ rt_setmetrics(which, in, out)
#undef metric
}
+/*
+ * Set route's interface given ifpaddr, ifaaddr, and gateway.
+ */
+static void
+rt_setif(rt, Ifpaddr, Ifaaddr, Gate)
+ struct rtentry *rt;
+ struct sockaddr *Ifpaddr, *Ifaaddr, *Gate;
+{
+ struct ifaddr *ifa = 0;
+ struct ifnet *ifp = 0;
+
+ /* new gateway could require new ifaddr, ifp;
+ flags may also be different; ifp may be specified
+ by ll sockaddr when protocol address is ambiguous */
+ if (Ifpaddr && (ifa = ifa_ifwithnet(Ifpaddr)) &&
+ (ifp = ifa->ifa_ifp) && (Ifaaddr || Gate))
+ ifa = ifaof_ifpforaddr(Ifaaddr ? Ifaaddr : Gate,
+ ifp);
+ else if (Ifpaddr && (ifp = if_withname(Ifpaddr)) ) {
+ ifa = Gate ? ifaof_ifpforaddr(Gate, ifp) :
+ TAILQ_FIRST(&ifp->if_addrlist);
+ }
+ else if ((Ifaaddr && (ifa = ifa_ifwithaddr(Ifaaddr))) ||
+ (Gate && (ifa = ifa_ifwithroute(rt->rt_flags,
+ rt_key(rt), Gate))))
+ ifp = ifa->ifa_ifp;
+ if (ifa) {
+ register struct ifaddr *oifa = rt->rt_ifa;
+ if (oifa != ifa) {
+ if (oifa && oifa->ifa_rtrequest)
+ oifa->ifa_rtrequest(RTM_DELETE,
+ rt, Gate);
+ IFAFREE(rt->rt_ifa);
+ rt->rt_ifa = ifa;
+ ifa->ifa_refcnt++;
+ rt->rt_ifp = ifp;
+ rt->rt_rmx.rmx_mtu = ifp->if_mtu;
+ if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
+ rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
+ } else
+ goto call_ifareq;
+ return;
+ }
+ call_ifareq:
+ /* XXX: to reset gateway to correct value, at RTM_CHANGE */
+ if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
+ rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
+}
+
+
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))