-/* $OpenBSD: route.c,v 1.428 2024/02/05 23:16:39 bluhm Exp $ */
+/* $OpenBSD: route.c,v 1.429 2024/02/07 23:40:40 bluhm Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
satosin(&ro->ro_dst)->sin_addr = addr;
}
+void
+route6_cache(struct route_in6 *ro, const struct in6_addr *addr,
+ u_int rtableid)
+{
+ u_long gen;
+
+ gen = atomic_load_long(&rtgeneration);
+ membar_consumer();
+
+ if (rtisvalid(ro->ro_rt) &&
+ ro->ro_generation == gen &&
+ ro->ro_tableid == rtableid &&
+ ro->ro_dst.sin6_family == AF_INET6 &&
+ IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, addr)) {
+ ip6stat_inc(ip6s_rtcachehit);
+ return;
+ }
+
+ ip6stat_inc(ip6s_rtcachemiss);
+ rtfree(ro->ro_rt);
+ ro->ro_rt = NULL;
+ ro->ro_generation = gen;
+ ro->ro_tableid = rtableid;
+
+ memset(&ro->ro_dst, 0, sizeof(ro->ro_dst));
+ ro->ro_dst.sin6_family = AF_INET6;
+ ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6);
+ ro->ro_dst.sin6_addr = *addr;
+}
+
/*
* Returns 1 if the (cached) ``rt'' entry is still valid, 0 otherwise.
*/
-/* $OpenBSD: in_pcb.c,v 1.289 2024/02/02 15:39:23 bluhm Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.290 2024/02/07 23:40:40 bluhm Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
ro = &inp->inp_route;
- /* check if route is still valid */
- if (!rtisvalid(ro->ro_rt)) {
- rtfree(ro->ro_rt);
- ro->ro_rt = NULL;
- }
-
- /*
- * No route yet, so try to acquire one.
- */
+ if (inp->inp_faddr.s_addr == INADDR_ANY)
+ return (NULL);
+ route_cache(ro, inp->inp_faddr, inp->inp_rtableid);
if (ro->ro_rt == NULL) {
- memset(ro, 0, sizeof(struct route));
-
- if (inp->inp_faddr.s_addr == INADDR_ANY)
- return (NULL);
- ro->ro_dst.sa_family = AF_INET;
- ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
- satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr;
- ro->ro_tableid = inp->inp_rtableid;
ro->ro_rt = rtalloc_mpath(&ro->ro_dst,
&inp->inp_laddr.s_addr, ro->ro_tableid);
}
-/* $OpenBSD: in6.h,v 1.113 2024/01/31 14:56:43 bluhm Exp $ */
+/* $OpenBSD: in6.h,v 1.114 2024/02/07 23:40:40 bluhm Exp $ */
/* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */
/*
int in6_nam2sin6(const struct mbuf *, struct sockaddr_in6 **);
int in6_sa2sin6(struct sockaddr *, struct sockaddr_in6 **);
+void route6_cache(struct route_in6 *, const struct in6_addr *, u_int);
+
struct ip6_pktopts;
struct ip6_moptions;
-/* $OpenBSD: in6_pcb.c,v 1.134 2024/01/31 12:27:57 bluhm Exp $ */
+/* $OpenBSD: in6_pcb.c,v 1.135 2024/02/07 23:40:40 bluhm Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
{
struct route_in6 *ro = &inp->inp_route6;
- /* check if route is still valid */
- if (!rtisvalid(ro->ro_rt)) {
- rtfree(ro->ro_rt);
- ro->ro_rt = NULL;
- }
-
- /*
- * No route yet, so try to acquire one.
- */
+ if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
+ return (NULL);
+ route6_cache(ro, &inp->inp_faddr6, inp->inp_rtableid);
if (ro->ro_rt == NULL) {
- memset(ro, 0, sizeof(struct route_in6));
-
- if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
- return (NULL);
- ro->ro_dst.sin6_family = AF_INET6;
- ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6);
- ro->ro_dst.sin6_addr = inp->inp_faddr6;
- ro->ro_tableid = inp->inp_rtableid;
ro->ro_rt = rtalloc_mpath(sin6tosa(&ro->ro_dst),
&inp->inp_laddr6.s6_addr32[0], ro->ro_tableid);
}
-/* $OpenBSD: in6_src.c,v 1.91 2024/01/09 19:57:01 bluhm Exp $ */
+/* $OpenBSD: in6_src.c,v 1.92 2024/02/07 23:40:40 bluhm Exp $ */
/* $KAME: in6_src.c,v 1.36 2001/02/06 04:08:17 itojun Exp $ */
/*
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
-int in6_selectif(struct sockaddr_in6 *, struct ip6_pktopts *,
+int in6_selectif(const struct in6_addr *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **, u_int);
/*
struct sockaddr_in6 sa6;
/* get the outgoing interface */
- error = in6_selectif(dstsock, opts, mopts, ro, &ifp, rtableid);
+ error = in6_selectif(dst, opts, mopts, ro, &ifp, rtableid);
if (error)
return (error);
* If route is known or can be allocated now,
* our src addr is taken from the i/f, else punt.
*/
- if (!rtisvalid(ro->ro_rt) || (ro->ro_tableid != rtableid) ||
- !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst)) {
- rtfree(ro->ro_rt);
- ro->ro_rt = NULL;
- }
+ route6_cache(ro, dst, rtableid);
if (ro->ro_rt == NULL) {
- struct sockaddr_in6 *sa6;
-
- /* No route yet, so try to acquire one */
- bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
- ro->ro_tableid = rtableid;
- sa6 = &ro->ro_dst;
- sa6->sin6_family = AF_INET6;
- sa6->sin6_len = sizeof(struct sockaddr_in6);
- sa6->sin6_addr = *dst;
- sa6->sin6_scope_id = dstsock->sin6_scope_id;
ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst),
RT_RESOLVE, ro->ro_tableid);
}
}
struct rtentry *
-in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
+in6_selectroute(const struct in6_addr *dst, struct ip6_pktopts *opts,
struct route_in6 *ro, unsigned int rtableid)
{
- struct in6_addr *dst;
-
- dst = &dstsock->sin6_addr;
-
/*
* Use a cached route if it exists and is valid, else try to allocate
* a new one.
*/
if (ro) {
- if (rtisvalid(ro->ro_rt))
- KASSERT(sin6tosa(&ro->ro_dst)->sa_family == AF_INET6);
- if (!rtisvalid(ro->ro_rt) ||
- !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst)) {
- rtfree(ro->ro_rt);
- ro->ro_rt = NULL;
- }
+ route6_cache(ro, dst, rtableid);
if (ro->ro_rt == NULL) {
- struct sockaddr_in6 *sa6;
-
/* No route yet, so try to acquire one */
- bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
- ro->ro_tableid = rtableid;
- sa6 = &ro->ro_dst;
- *sa6 = *dstsock;
- sa6->sin6_scope_id = 0;
- ro->ro_tableid = rtableid;
ro->ro_rt = rtalloc_mpath(sin6tosa(&ro->ro_dst),
NULL, ro->ro_tableid);
}
}
int
-in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
+in6_selectif(const struct in6_addr *dst, struct ip6_pktopts *opts,
struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp,
u_int rtableid)
{
* If the destination address is a multicast address and the outgoing
* interface for the address is specified by the caller, use it.
*/
- if (IN6_IS_ADDR_MULTICAST(&dstsock->sin6_addr) &&
+ if (IN6_IS_ADDR_MULTICAST(dst) &&
mopts != NULL && (*retifp = if_get(mopts->im6o_ifidx)) != NULL)
return (0);
- rt = in6_selectroute(dstsock, opts, ro, rtableid);
+ rt = in6_selectroute(dst, opts, ro, rtableid);
if (rt == NULL)
return (EHOSTUNREACH);
-/* $OpenBSD: ip6_forward.c,v 1.112 2023/07/07 08:05:02 bluhm Exp $ */
+/* $OpenBSD: ip6_forward.c,v 1.113 2024/02/07 23:40:40 bluhm Exp $ */
/* $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $ */
/*
ip6_forward(struct mbuf *m, struct rtentry *rt, int srcrt)
{
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
- struct sockaddr_in6 *sin6;
+ struct sockaddr *dst;
struct route_in6 ro;
struct ifnet *ifp = NULL;
int error = 0, type = 0, code = 0, destmtu = 0;
}
#endif /* IPSEC */
- memset(&ro, 0, sizeof(ro));
- sin6 = &ro.ro_dst;
- sin6->sin6_family = AF_INET6;
- sin6->sin6_len = sizeof(*sin6);
- sin6->sin6_addr = ip6->ip6_dst;
-
+ ro.ro_rt = NULL;
+ route6_cache(&ro, &ip6->ip6_dst, m->m_pkthdr.ph_rtableid);
+ dst = sin6tosa(&ro.ro_dst);
if (!rtisvalid(rt)) {
rtfree(rt);
- rt = rtalloc_mpath(sin6tosa(sin6), &ip6->ip6_src.s6_addr32[0],
+ rt = rtalloc_mpath(dst, &ip6->ip6_src.s6_addr32[0],
m->m_pkthdr.ph_rtableid);
if (rt == NULL) {
ip6stat_inc(ip6s_noroute);
goto out;
}
}
+ ro.ro_rt = rt;
/*
* Scope check: if a packet can't be delivered to its destination
*/
if (tdb != NULL) {
/* Callee frees mbuf */
- ro.ro_rt = rt;
- ro.ro_tableid = m->m_pkthdr.ph_rtableid;
error = ip6_output_ipsec_send(tdb, m, &ro, 0, 1);
rt = ro.ro_rt;
if (error)
#endif /* IPSEC */
if (rt->rt_flags & RTF_GATEWAY)
- sin6 = satosin6(rt->rt_gateway);
+ dst = rt->rt_gateway;
/*
* If we are to forward the packet using the same interface
}
#endif
- error = if_output_tso(ifp, &m, sin6tosa(sin6), rt, ifp->if_mtu);
+ error = if_output_tso(ifp, &m, dst, rt, ifp->if_mtu);
if (error)
ip6stat_inc(ip6s_cantforward);
else if (m == NULL)
-/* $OpenBSD: ip6_output.c,v 1.284 2024/01/31 12:27:57 bluhm Exp $ */
+/* $OpenBSD: ip6_output.c,v 1.285 2024/02/07 23:40:40 bluhm Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
int hlen, tlen;
struct route_in6 ip6route;
struct rtentry *rt = NULL;
- struct sockaddr_in6 *dst, dstsock;
+ struct sockaddr_in6 *dst;
int error = 0;
u_long mtu;
int dontfrag;
}
#endif /* IPSEC */
- bzero(&dstsock, sizeof(dstsock));
- dstsock.sin6_family = AF_INET6;
- dstsock.sin6_addr = ip6->ip6_dst;
- dstsock.sin6_len = sizeof(dstsock);
- ro->ro_tableid = m->m_pkthdr.ph_rtableid;
-
- if (IN6_IS_ADDR_MULTICAST(&dstsock.sin6_addr)) {
+ if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
struct in6_pktinfo *pi = NULL;
/*
}
if (ifp == NULL) {
- rt = in6_selectroute(&dstsock, opt, ro, ro->ro_tableid);
+ rt = in6_selectroute(&ip6->ip6_dst, opt, ro,
+ m->m_pkthdr.ph_rtableid);
if (rt == NULL) {
ip6stat_inc(ip6s_noroute);
error = EHOSTUNREACH;
goto bad;
}
} else {
- *dst = dstsock;
+ route6_cache(ro, &ip6->ip6_dst, m->m_pkthdr.ph_rtableid);
}
if (rt && (rt->rt_flags & RTF_GATEWAY) &&
-/* $OpenBSD: ip6_var.h,v 1.111 2024/02/05 23:16:39 bluhm Exp $ */
+/* $OpenBSD: ip6_var.h,v 1.112 2024/02/07 23:40:40 bluhm Exp $ */
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
/*
struct inpcb *, struct ip6_pktopts *);
int in6_selectsrc(const struct in6_addr **, struct sockaddr_in6 *,
struct ip6_moptions *, unsigned int);
-struct rtentry *in6_selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
+struct rtentry *in6_selectroute(const struct in6_addr *, struct ip6_pktopts *,
struct route_in6 *, unsigned int rtableid);
u_int32_t ip6_randomflowlabel(void);