summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/icmp6.h4
-rw-r--r--sys/netinet/in_pcb.c42
-rw-r--r--sys/netinet/ip_fastfwd.c41
-rw-r--r--sys/netinet/ip_icmp.c24
-rw-r--r--sys/netinet6/icmp6.c13
-rw-r--r--sys/netinet6/ip6_fastfwd.c45
-rw-r--r--sys/netinet6/ip6_forward.c2
7 files changed, 87 insertions, 84 deletions
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
index abd1f18bbd37..2544fc733b08 100644
--- a/sys/netinet/icmp6.h
+++ b/sys/netinet/icmp6.h
@@ -693,7 +693,7 @@ void kmod_icmp6stat_inc(int statnum);
#ifdef _KERNEL
# ifdef __STDC__
-struct rtentry;
+struct nhop_object;
struct rttimer;
struct in6_multi;
# endif
@@ -705,7 +705,7 @@ void icmp6_fasttimo(void);
void icmp6_slowtimo(void);
void icmp6_prepare(struct mbuf *);
void icmp6_redirect_input(struct mbuf *, int);
-void icmp6_redirect_output(struct mbuf *, struct rtentry *);
+void icmp6_redirect_output(struct mbuf *, struct nhop_object *);
struct ip6ctlparam;
void icmp6_mtudisc_update(struct ip6ctlparam *, int);
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 24a18f06c943..d9df083ab369 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -88,6 +88,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_pcb.h>
#ifdef INET
#include <netinet/in_var.h>
+#include <netinet/in_fib.h>
#endif
#include <netinet/ip_var.h>
#include <netinet/tcp_var.h>
@@ -102,6 +103,7 @@ __FBSDID("$FreeBSD$");
#include <netinet6/in6_var.h>
#include <netinet6/ip6_var.h>
#endif /* INET6 */
+#include <net/route/nhop.h>
#endif
#include <netipsec/ipsec_support.h>
@@ -1033,8 +1035,8 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
{
struct ifaddr *ifa;
struct sockaddr *sa;
- struct sockaddr_in *sin;
- struct route sro;
+ struct sockaddr_in *sin, dst;
+ struct nhop_object *nh;
int error;
NET_EPOCH_ASSERT();
@@ -1047,9 +1049,10 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
return (0);
error = 0;
- bzero(&sro, sizeof(sro));
- sin = (struct sockaddr_in *)&sro.ro_dst;
+ nh = NULL;
+ bzero(&dst, sizeof(dst));
+ sin = &dst;
sin->sin_family = AF_INET;
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_addr.s_addr = faddr->s_addr;
@@ -1061,7 +1064,8 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
* Find out route to destination.
*/
if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0)
- in_rtalloc_ign(&sro, 0, inp->inp_inc.inc_fibnum);
+ nh = fib4_lookup(inp->inp_inc.inc_fibnum, *faddr,
+ 0, NHR_NONE, 0);
/*
* If we found a route, use the address corresponding to
@@ -1071,7 +1075,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
* network and try to find a corresponding interface to take
* the source address from.
*/
- if (sro.ro_rt == NULL || sro.ro_rt->rt_ifp == NULL) {
+ if (nh == NULL || nh->nh_ifp == NULL) {
struct in_ifaddr *ia;
struct ifnet *ifp;
@@ -1124,22 +1128,22 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
* belonging to this jail. If so use it.
* 3. as a last resort return the 'default' jail address.
*/
- if ((sro.ro_rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) {
+ if ((nh->nh_ifp->if_flags & IFF_LOOPBACK) == 0) {
struct in_ifaddr *ia;
struct ifnet *ifp;
/* If not jailed, use the default returned. */
if (cred == NULL || !prison_flag(cred, PR_IP4)) {
- ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa;
+ ia = (struct in_ifaddr *)nh->nh_ifa;
laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
goto done;
}
/* Jailed. */
/* 1. Check if the iface address belongs to the jail. */
- sin = (struct sockaddr_in *)sro.ro_rt->rt_ifa->ifa_addr;
+ sin = (struct sockaddr_in *)nh->nh_ifa->ifa_addr;
if (prison_check_ip4(cred, &sin->sin_addr) == 0) {
- ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa;
+ ia = (struct in_ifaddr *)nh->nh_ifa;
laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
goto done;
}
@@ -1149,7 +1153,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
* belonging to this jail.
*/
ia = NULL;
- ifp = sro.ro_rt->rt_ifp;
+ ifp = nh->nh_ifp;
CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
sa = ifa->ifa_addr;
if (sa->sa_family != AF_INET)
@@ -1179,22 +1183,16 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
* In case of jails, check that it is an address of the jail
* and if we cannot find, fall back to the 'default' jail address.
*/
- if ((sro.ro_rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
- struct sockaddr_in sain;
+ if ((nh->nh_ifp->if_flags & IFF_LOOPBACK) != 0) {
struct in_ifaddr *ia;
- bzero(&sain, sizeof(struct sockaddr_in));
- sain.sin_family = AF_INET;
- sain.sin_len = sizeof(struct sockaddr_in);
- sain.sin_addr.s_addr = faddr->s_addr;
-
- ia = ifatoia(ifa_ifwithdstaddr(sintosa(&sain),
+ ia = ifatoia(ifa_ifwithdstaddr(sintosa(&dst),
inp->inp_socket->so_fibnum));
if (ia == NULL)
- ia = ifatoia(ifa_ifwithnet(sintosa(&sain), 0,
+ ia = ifatoia(ifa_ifwithnet(sintosa(&dst), 0,
inp->inp_socket->so_fibnum));
if (ia == NULL)
- ia = ifatoia(ifa_ifwithaddr(sintosa(&sain)));
+ ia = ifatoia(ifa_ifwithaddr(sintosa(&dst)));
if (cred == NULL || !prison_flag(cred, PR_IP4)) {
if (ia == NULL) {
@@ -1234,8 +1232,6 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
}
done:
- if (sro.ro_rt != NULL)
- RTFREE(sro.ro_rt);
return (error);
}
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index 502bd15cb072..10746a3e180f 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -96,6 +96,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_dl.h>
#include <net/pfil.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -111,11 +112,13 @@ __FBSDID("$FreeBSD$");
#include <machine/in_cksum.h>
static int
-ip_findroute(struct nhop4_basic *pnh, struct in_addr dest, struct mbuf *m)
+ip_findroute(struct nhop_object **pnh, struct in_addr dest, struct mbuf *m)
{
+ struct nhop_object *nh;
- bzero(pnh, sizeof(*pnh));
- if (fib4_lookup_nh_basic(M_GETFIB(m), dest, 0, 0, pnh) != 0) {
+ nh = fib4_lookup(M_GETFIB(m), dest, 0, NHR_NONE,
+ m->m_pkthdr.flowid);
+ if (nh == NULL) {
IPSTAT_INC(ips_noroute);
IPSTAT_INC(ips_cantforward);
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
@@ -124,18 +127,20 @@ ip_findroute(struct nhop4_basic *pnh, struct in_addr dest, struct mbuf *m)
/*
* Drop blackholed traffic and directed broadcasts.
*/
- if ((pnh->nh_flags & (NHF_BLACKHOLE | NHF_BROADCAST)) != 0) {
+ if ((nh->nh_flags & (NHF_BLACKHOLE | NHF_BROADCAST)) != 0) {
IPSTAT_INC(ips_cantforward);
m_freem(m);
return (EHOSTUNREACH);
}
- if (pnh->nh_flags & NHF_REJECT) {
+ if (nh->nh_flags & NHF_REJECT) {
IPSTAT_INC(ips_cantforward);
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
return (EHOSTUNREACH);
}
+ *pnh = nh;
+
return (0);
}
@@ -151,7 +156,7 @@ ip_tryforward(struct mbuf *m)
{
struct ip *ip;
struct mbuf *m0 = NULL;
- struct nhop4_basic nh;
+ struct nhop_object *nh;
struct sockaddr_in dst;
struct in_addr dest, odest, rtdest;
uint16_t ip_len, ip_off;
@@ -323,7 +328,7 @@ passin:
if (!PFIL_HOOKED_OUT(V_inet_pfil_head))
goto passout;
- if (pfil_run_hooks(V_inet_pfil_head, &m, nh.nh_ifp,
+ if (pfil_run_hooks(V_inet_pfil_head, &m, nh->nh_ifp,
PFIL_OUT | PFIL_FWD, NULL) != PFIL_PASS)
goto drop;
@@ -376,12 +381,15 @@ passout:
bzero(&dst, sizeof(dst));
dst.sin_family = AF_INET;
dst.sin_len = sizeof(dst);
- dst.sin_addr = nh.nh_addr;
+ if (nh->nh_flags & NHF_GATEWAY)
+ dst.sin_addr = nh->gw4_sa.sin_addr;
+ else
+ dst.sin_addr = dest;
/*
* Check if packet fits MTU or if hardware will fragment for us
*/
- if (ip_len <= nh.nh_mtu) {
+ if (ip_len <= nh->nh_mtu) {
/*
* Avoid confusing lower layers.
*/
@@ -389,8 +397,8 @@ passout:
/*
* Send off the packet via outgoing interface
*/
- IP_PROBE(send, NULL, NULL, ip, nh.nh_ifp, ip, NULL);
- error = (*nh.nh_ifp->if_output)(nh.nh_ifp, m,
+ IP_PROBE(send, NULL, NULL, ip, nh->nh_ifp, ip, NULL);
+ error = (*nh->nh_ifp->if_output)(nh->nh_ifp, m,
(struct sockaddr *)&dst, NULL);
} else {
/*
@@ -399,15 +407,15 @@ passout:
if (ip_off & IP_DF) {
IPSTAT_INC(ips_cantfrag);
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG,
- 0, nh.nh_mtu);
+ 0, nh->nh_mtu);
goto consumed;
} else {
/*
* We have to fragment the packet
*/
m->m_pkthdr.csum_flags |= CSUM_IP;
- if (ip_fragment(ip, &m, nh.nh_mtu,
- nh.nh_ifp->if_hwassist) != 0)
+ if (ip_fragment(ip, &m, nh->nh_mtu,
+ nh->nh_ifp->if_hwassist) != 0)
goto drop;
KASSERT(m != NULL, ("null mbuf and no error"));
/*
@@ -423,10 +431,9 @@ passout:
m_clrprotoflags(m);
IP_PROBE(send, NULL, NULL,
- mtod(m, struct ip *), nh.nh_ifp,
+ mtod(m, struct ip *), nh->nh_ifp,
mtod(m, struct ip *), NULL);
- /* XXX: we can use cached route here */
- error = (*nh.nh_ifp->if_output)(nh.nh_ifp, m,
+ error = (*nh->nh_ifp->if_output)(nh->nh_ifp, m,
(struct sockaddr *)&dst, NULL);
if (error)
break;
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index cbae3953b016..a03cf2514fb1 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_var.h>
#include <net/if_types.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -945,7 +946,7 @@ static int
icmp_verify_redirect_gateway(struct sockaddr_in *src, struct sockaddr_in *dst,
struct sockaddr_in *gateway, u_int fibnum)
{
- struct rtentry *rt;
+ struct nhop_object *nh;
struct ifaddr *ifa;
NET_EPOCH_ASSERT();
@@ -958,8 +959,8 @@ icmp_verify_redirect_gateway(struct sockaddr_in *src, struct sockaddr_in *dst,
if (ifa_ifwithaddr_check((struct sockaddr *)gateway))
return (EHOSTUNREACH);
- rt = rtalloc1_fib((struct sockaddr *)dst, 0, 0UL, fibnum); /* NB: rt is locked */
- if (rt == NULL)
+ nh = fib4_lookup(fibnum, dst->sin_addr, 0, NHR_NONE, 0);
+ if (nh == NULL)
return (EINVAL);
/*
@@ -968,28 +969,19 @@ icmp_verify_redirect_gateway(struct sockaddr_in *src, struct sockaddr_in *dst,
* we have a routing loop, perhaps as a result of an interface
* going down recently.
*/
- if (!sa_equal((struct sockaddr *)src, rt->rt_gateway)) {
- RTFREE_LOCKED(rt);
+ if (!sa_equal((struct sockaddr *)src, &nh->gw_sa))
return (EINVAL);
- }
- if (rt->rt_ifa != ifa && ifa->ifa_addr->sa_family != AF_LINK) {
- RTFREE_LOCKED(rt);
+ if (nh->nh_ifa != ifa && ifa->ifa_addr->sa_family != AF_LINK)
return (EINVAL);
- }
/* If host route already exists, ignore redirect. */
- if (rt->rt_flags & RTF_HOST) {
- RTFREE_LOCKED(rt);
+ if (nh->nh_flags & NHF_HOST)
return (EEXIST);
- }
/* If the prefix is directly reachable, ignore redirect. */
- if (!(rt->rt_flags & RTF_GATEWAY)) {
- RTFREE_LOCKED(rt);
+ if (!(nh->nh_flags & NHF_GATEWAY))
return (EEXIST);
- }
- RTFREE_LOCKED(rt);
return (0);
}
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 353528f71eaf..0afe58f3f4b5 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -2412,7 +2413,7 @@ icmp6_redirect_input(struct mbuf *m, int off)
}
void
-icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
+icmp6_redirect_output(struct mbuf *m0, struct nhop_object *nh)
{
struct ifnet *ifp; /* my outgoing interface */
struct in6_addr *ifp_ll6;
@@ -2435,7 +2436,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
goto fail;
/* sanity check */
- if (!m0 || !rt || !(rt->rt_flags & RTF_UP) || !(ifp = rt->rt_ifp))
+ if (!m0 || !nh || !(NH_IS_VALID(nh)) || !(ifp = nh->nh_ifp))
goto fail;
/*
@@ -2469,7 +2470,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL)
goto fail;
- M_SETFIB(m, rt->rt_fibnum);
+ M_SETFIB(m, M_GETFIB(m0));
maxlen = M_TRAILINGSPACE(m);
maxlen = min(IPV6_MMTU, maxlen);
/* just for safety */
@@ -2491,9 +2492,9 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
}
/* get ip6 linklocal address for the router. */
- if (rt->rt_gateway && (rt->rt_flags & RTF_GATEWAY)) {
+ if (nh->nh_flags & NHF_GATEWAY) {
struct sockaddr_in6 *sin6;
- sin6 = (struct sockaddr_in6 *)rt->rt_gateway;
+ sin6 = &nh->gw6_sa;
router_ll6 = &sin6->sin6_addr;
if (!IN6_IS_ADDR_LINKLOCAL(router_ll6))
router_ll6 = (struct in6_addr *)NULL;
@@ -2517,7 +2518,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
nd_rd->nd_rd_type = ND_REDIRECT;
nd_rd->nd_rd_code = 0;
nd_rd->nd_rd_reserved = 0;
- if (rt->rt_flags & RTF_GATEWAY) {
+ if (nh->nh_flags & NHF_GATEWAY) {
/*
* nd_rd->nd_rd_target must be a link-local address in
* better router cases.
diff --git a/sys/netinet6/ip6_fastfwd.c b/sys/netinet6/ip6_fastfwd.c
index 932005fbb74f..78f1a0f79cb0 100644
--- a/sys/netinet6/ip6_fastfwd.c
+++ b/sys/netinet6/ip6_fastfwd.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/pfil.h>
#include <net/vnet.h>
@@ -55,30 +56,35 @@ __FBSDID("$FreeBSD$");
#include <netinet6/nd6.h>
static int
-ip6_findroute(struct nhop6_basic *pnh, const struct sockaddr_in6 *dst,
+ip6_findroute(struct nhop_object **pnh, const struct sockaddr_in6 *dst,
struct mbuf *m)
{
+ struct nhop_object *nh;
- if (fib6_lookup_nh_basic(M_GETFIB(m), &dst->sin6_addr,
- dst->sin6_scope_id, 0, dst->sin6_flowinfo, pnh) != 0) {
+ nh = fib6_lookup(M_GETFIB(m), &dst->sin6_addr,
+ dst->sin6_scope_id, NHR_NONE, m->m_pkthdr.flowid);
+ if (nh == NULL) {
IP6STAT_INC(ip6s_noroute);
IP6STAT_INC(ip6s_cantforward);
icmp6_error(m, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_NOROUTE, 0);
return (EHOSTUNREACH);
}
- if (pnh->nh_flags & NHF_BLACKHOLE) {
+ if (nh->nh_flags & NHF_BLACKHOLE) {
IP6STAT_INC(ip6s_cantforward);
m_freem(m);
return (EHOSTUNREACH);
}
- if (pnh->nh_flags & NHF_REJECT) {
+ if (nh->nh_flags & NHF_REJECT) {
IP6STAT_INC(ip6s_cantforward);
icmp6_error(m, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_REJECT, 0);
return (EHOSTUNREACH);
}
+
+ *pnh = nh;
+
return (0);
}
@@ -86,7 +92,7 @@ struct mbuf*
ip6_tryforward(struct mbuf *m)
{
struct sockaddr_in6 dst;
- struct nhop6_basic nh;
+ struct nhop_object *nh;
struct m_tag *fwd_tag;
struct ip6_hdr *ip6;
struct ifnet *rcvif;
@@ -196,9 +202,9 @@ passin:
goto dropin;
}
if (!PFIL_HOOKED_OUT(V_inet6_pfil_head)) {
- if (m->m_pkthdr.len > nh.nh_mtu) {
- in6_ifstat_inc(nh.nh_ifp, ifs6_in_toobig);
- icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, nh.nh_mtu);
+ if (m->m_pkthdr.len > nh->nh_mtu) {
+ in6_ifstat_inc(nh->nh_ifp, ifs6_in_toobig);
+ icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, nh->nh_mtu);
m = NULL;
goto dropout;
}
@@ -208,7 +214,7 @@ passin:
/*
* Outgoing packet firewall processing.
*/
- if (pfil_run_hooks(V_inet6_pfil_head, &m, nh.nh_ifp, PFIL_OUT |
+ if (pfil_run_hooks(V_inet6_pfil_head, &m, nh->nh_ifp, PFIL_OUT |
PFIL_FWD, NULL) != PFIL_PASS)
goto dropout;
@@ -216,9 +222,9 @@ passin:
* We used slow path processing for packets with scoped addresses.
* So, scope checks aren't needed here.
*/
- if (m->m_pkthdr.len > nh.nh_mtu) {
- in6_ifstat_inc(nh.nh_ifp, ifs6_in_toobig);
- icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, nh.nh_mtu);
+ if (m->m_pkthdr.len > nh->nh_mtu) {
+ in6_ifstat_inc(nh->nh_ifp, ifs6_in_toobig);
+ icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, nh->nh_mtu);
m = NULL;
goto dropout;
}
@@ -272,16 +278,17 @@ passout:
}
m_clrprotoflags(m); /* Avoid confusing lower layers. */
- IP_PROBE(send, NULL, NULL, ip6, nh.nh_ifp, NULL, ip6);
+ IP_PROBE(send, NULL, NULL, ip6, nh->nh_ifp, NULL, ip6);
- dst.sin6_addr = nh.nh_addr;
- error = (*nh.nh_ifp->if_output)(nh.nh_ifp, m,
+ if (nh->nh_flags & NHF_GATEWAY)
+ dst.sin6_addr = nh->gw6_sa.sin6_addr;
+ error = (*nh->nh_ifp->if_output)(nh->nh_ifp, m,
(struct sockaddr *)&dst, NULL);
if (error != 0) {
- in6_ifstat_inc(nh.nh_ifp, ifs6_out_discard);
+ in6_ifstat_inc(nh->nh_ifp, ifs6_out_discard);
IP6STAT_INC(ip6s_cantforward);
} else {
- in6_ifstat_inc(nh.nh_ifp, ifs6_out_forward);
+ in6_ifstat_inc(nh->nh_ifp, ifs6_out_forward);
IP6STAT_INC(ip6s_forward);
}
return (NULL);
@@ -289,7 +296,7 @@ dropin:
in6_ifstat_inc(rcvif, ifs6_in_discard);
goto drop;
dropout:
- in6_ifstat_inc(nh.nh_ifp, ifs6_out_discard);
+ in6_ifstat_inc(nh->nh_ifp, ifs6_out_discard);
drop:
if (m != NULL)
m_freem(m);
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index 9a7110e15561..a8677ab2f382 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -401,7 +401,7 @@ pass:
switch (error) {
case 0:
if (type == ND_REDIRECT) {
- icmp6_redirect_output(mcopy, rt);
+ icmp6_redirect_output(mcopy, rt->rt_nhop);
goto out;
}
goto freecopy;