Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149956397
D18581.id52099.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D18581.id52099.diff
View Options
Index: sbin/route/keywords
===================================================================
--- sbin/route/keywords
+++ sbin/route/keywords
@@ -14,6 +14,7 @@
fib
flush
gateway
+gateway6
genmask
get
host
Index: sbin/route/route.c
===================================================================
--- sbin/route/route.c
+++ sbin/route/route.c
@@ -786,6 +786,7 @@
#define F_FORCEHOST 0x04
#define F_PROXY 0x08
#define F_INTERFACE 0x10
+#define F_GATEWAY6 0x20
static void
newroute(int argc, char **argv)
@@ -912,6 +913,13 @@
getaddr(RTAX_GATEWAY, *++argv, 0, nrflags);
gateway = *argv;
break;
+ case K_GATEWAY6:
+ if (!--argc)
+ usage(NULL);
+ nrflags |= F_GATEWAY6;
+ getaddr(RTAX_GATEWAY, *++argv, 0, nrflags);
+ gateway = *argv;
+ break;
case K_DST:
if (!--argc)
usage(NULL);
@@ -1212,8 +1220,16 @@
#endif
rtm_addrs |= (1 << idx);
sa = (struct sockaddr *)&so[idx];
- sa->sa_family = af;
- sa->sa_len = aflen;
+#ifdef INET6
+ if ((nrflags & F_GATEWAY6) && idx == RTAX_GATEWAY) {
+ sa->sa_family = AF_INET6;
+ sa->sa_len = sizeof(struct sockaddr_in6);
+ } else
+#endif
+ {
+ sa->sa_family = af;
+ sa->sa_len = aflen;
+ }
switch (idx) {
case RTAX_GATEWAY:
Index: sys/net/if_ethersubr.c
===================================================================
--- sys/net/if_ethersubr.c
+++ sys/net/if_ethersubr.c
@@ -246,6 +246,18 @@
memcpy(&eh->ether_type, &etype, sizeof(etype));
memcpy(eh->ether_shost, IF_LLADDR(ifp), ETHER_ADDR_LEN);
}
+ /*
+ * Keep M_ETHER_RFC5549 flag if nd6_resolve() has failed
+ * to do lookup. It may hold a chain of mbufs, and then if
+ * queue becomes overfilled, it could generate ICMPv6 error
+ * for dropped packets. But ICMPv6 code expects IPv6 packet
+ * in a mbuf. With the flag we can avoid ICMPv6 handling.
+ */
+ if (error == 0 && (m->m_flags & M_ETHER_RFC5549) != 0) {
+ m->m_flags &= ~M_ETHER_RFC5549;
+ etype = htons(ETHERTYPE_IP);
+ memcpy(&eh->ether_type, &etype, sizeof(etype));
+ }
break;
#endif
default:
Index: sys/net/route.h
===================================================================
--- sys/net/route.h
+++ sys/net/route.h
@@ -210,6 +210,7 @@
#define NHF_DEFAULT 0x0080 /* Default route */
#define NHF_BROADCAST 0x0100 /* RTF_BROADCAST */
#define NHF_GATEWAY 0x0200 /* RTF_GATEWAY */
+#define NHF_RFC5549 0x0400 /* next hop conforms to RFC5549 */
/* Nexthop request flags */
#define NHR_IFAIF 0x01 /* Return ifa_ifp interface */
Index: sys/net/route.c
===================================================================
--- sys/net/route.c
+++ sys/net/route.c
@@ -1585,8 +1585,11 @@
case RTM_ADD:
if ((flags & RTF_GATEWAY) && !gateway)
return (EINVAL);
- if (dst && gateway && (dst->sa_family != gateway->sa_family) &&
- (gateway->sa_family != AF_UNSPEC) && (gateway->sa_family != AF_LINK))
+ if (dst && gateway &&
+ (dst->sa_family != gateway->sa_family) &&
+ (gateway->sa_family != AF_UNSPEC) &&
+ (gateway->sa_family != AF_LINK) &&
+ (gateway->sa_family != AF_INET6))
return (EINVAL);
if (info->rti_ifa == NULL) {
Index: sys/netinet/in_fib.h
===================================================================
--- sys/netinet/in_fib.h
+++ sys/netinet/in_fib.h
@@ -37,7 +37,15 @@
struct ifnet *nh_ifp; /* Logical egress interface */
uint16_t nh_mtu; /* nexthop mtu */
uint16_t nh_flags; /* nhop flags */
- struct in_addr nh_addr; /* GW/DST IPv4 address */
+ uint8_t spare[4];
+ union { /* GW/DST IPv4 address */
+ struct in_addr nh_addr;
+#ifdef INET6
+ struct in6_addr nh_addr6;
+#else
+ uint8_t nh_addr6[16];
+#endif
+ };
};
/* Extended nexthop info used for control protocols */
@@ -46,9 +54,15 @@
uint16_t nh_mtu; /* nexthop mtu */
uint16_t nh_flags; /* nhop flags */
uint8_t spare[4];
- struct in_addr nh_addr; /* GW/DST IPv4 address */
struct in_addr nh_src; /* default source IPv4 address */
- uint64_t spare2[2];
+ union { /* GW/DST IPv4 address */
+ struct in_addr nh_addr;
+#ifdef INET6
+ struct in6_addr nh_addr6;
+#else
+ uint8_t nh_addr6[16];
+#endif
+ };
};
int fib4_lookup_nh_basic(uint32_t fibnum, struct in_addr dst, uint32_t flags,
Index: sys/netinet/in_fib.c
===================================================================
--- sys/netinet/in_fib.c
+++ sys/netinet/in_fib.c
@@ -31,6 +31,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_route.h"
#include "opt_mpath.h"
@@ -58,6 +59,9 @@
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/in_fib.h>
+#ifdef INET6
+#include <netinet6/scope6_var.h>
+#endif
#ifdef INET
static void fib4_rte_to_nh_basic(struct rtentry *rte, struct in_addr dst,
@@ -71,22 +75,32 @@
fib4_rte_to_nh_basic(struct rtentry *rte, struct in_addr dst,
uint32_t flags, struct nhop4_basic *pnh4)
{
- struct sockaddr_in *gw;
+ struct sockaddr *gw;
if ((flags & NHR_IFAIF) != 0)
pnh4->nh_ifp = rte->rt_ifa->ifa_ifp;
else
pnh4->nh_ifp = rte->rt_ifp;
pnh4->nh_mtu = min(rte->rt_mtu, rte->rt_ifp->if_mtu);
+ pnh4->nh_flags = fib_rte_to_nh_flags(rte->rt_flags);
if (rte->rt_flags & RTF_GATEWAY) {
- gw = (struct sockaddr_in *)rte->rt_gateway;
- pnh4->nh_addr = gw->sin_addr;
+ gw = rte->rt_gateway;
+ MPASS(gw->sa_family == AF_INET ||
+ gw->sa_family == AF_INET6);
+#ifdef INET6
+ if (gw->sa_family == AF_INET6) {
+ pnh4->nh_flags |= NHF_RFC5549;
+ pnh4->nh_addr6 = satosin6(gw)->sin6_addr;
+ in6_clearscope(&pnh4->nh_addr6); /* XXXAE */
+ } else
+#endif
+ {
+ pnh4->nh_addr = satosin(gw)->sin_addr;
+ }
} else
pnh4->nh_addr = dst;
- /* Set flags */
- pnh4->nh_flags = fib_rte_to_nh_flags(rte->rt_flags);
- gw = (struct sockaddr_in *)rt_key(rte);
- if (gw->sin_addr.s_addr == 0)
+ gw = rt_key(rte);
+ if (satosin(gw)->sin_addr.s_addr == INADDR_ANY)
pnh4->nh_flags |= NHF_DEFAULT;
/* TODO: Handle RTF_BROADCAST here */
}
@@ -95,7 +109,7 @@
fib4_rte_to_nh_extended(struct rtentry *rte, struct in_addr dst,
uint32_t flags, struct nhop4_extended *pnh4)
{
- struct sockaddr_in *gw;
+ struct sockaddr *gw;
struct in_ifaddr *ia;
if ((flags & NHR_IFAIF) != 0)
@@ -103,15 +117,25 @@
else
pnh4->nh_ifp = rte->rt_ifp;
pnh4->nh_mtu = min(rte->rt_mtu, rte->rt_ifp->if_mtu);
+ pnh4->nh_flags = fib_rte_to_nh_flags(rte->rt_flags);
if (rte->rt_flags & RTF_GATEWAY) {
- gw = (struct sockaddr_in *)rte->rt_gateway;
- pnh4->nh_addr = gw->sin_addr;
+ gw = rte->rt_gateway;
+ MPASS(gw->sa_family == AF_INET ||
+ gw->sa_family == AF_INET6);
+#ifdef INET6
+ if (gw->sa_family == AF_INET6) {
+ pnh4->nh_flags |= NHF_RFC5549;
+ pnh4->nh_addr6 = satosin6(gw)->sin6_addr;
+ in6_clearscope(&pnh4->nh_addr6); /* XXXAE */
+ } else
+#endif
+ {
+ pnh4->nh_addr = satosin(gw)->sin_addr;
+ }
} else
pnh4->nh_addr = dst;
- /* Set flags */
- pnh4->nh_flags = fib_rte_to_nh_flags(rte->rt_flags);
- gw = (struct sockaddr_in *)rt_key(rte);
- if (gw->sin_addr.s_addr == 0)
+ gw = rt_key(rte);
+ if (satosin(gw)->sin_addr.s_addr == INADDR_ANY)
pnh4->nh_flags |= NHF_DEFAULT;
/* XXX: Set RTF_BROADCAST if GW address is broadcast */
Index: sys/netinet/ip_fastfwd.c
===================================================================
--- sys/netinet/ip_fastfwd.c
+++ sys/netinet/ip_fastfwd.c
@@ -79,6 +79,7 @@
__FBSDID("$FreeBSD$");
#include "opt_ipstealth.h"
+#include "opt_inet6.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -152,7 +153,13 @@
struct ip *ip;
struct mbuf *m0 = NULL;
struct nhop4_basic nh;
- struct sockaddr_in dst;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
+ } dst;
struct in_addr dest, odest, rtdest;
uint16_t ip_len, ip_off;
int error = 0;
@@ -376,9 +383,21 @@
ip_off = ntohs(ip->ip_off);
bzero(&dst, sizeof(dst));
- dst.sin_family = AF_INET;
- dst.sin_len = sizeof(dst);
- dst.sin_addr = nh.nh_addr;
+#ifdef INET6
+ if (nh.nh_flags & NHF_RFC5549) {
+ dst.sin6.sin6_family = AF_INET6;
+ dst.sin6.sin6_len = sizeof(dst.sin6);
+ dst.sin6.sin6_addr = nh.nh_addr6;
+ if (IN6_IS_SCOPE_LINKLOCAL(&nh.nh_addr6))
+ dst.sin6.sin6_addr.s6_addr16[1] =
+ htons(nh.nh_ifp->if_index & 0xffff);
+ } else
+#endif
+ {
+ dst.sin.sin_family = AF_INET;
+ dst.sin.sin_len = sizeof(dst.sin);
+ dst.sin.sin_addr = nh.nh_addr;
+ }
/*
* Check if packet fits MTU or if hardware will fragment for us
@@ -388,15 +407,23 @@
* Avoid confusing lower layers.
*/
m_clrprotoflags(m);
+#ifdef INET6
/*
+ * Notify ethernet layer that we need change ethertype
+ * for RFC5549 case.
+ */
+ if (nh.nh_flags & NHF_RFC5549)
+ m->m_flags |= M_ETHER_RFC5549;
+#endif
+ /*
* 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,
- (struct sockaddr *)&dst, NULL);
+ error = (*nh.nh_ifp->if_output)(nh.nh_ifp, m, &dst.sa, NULL);
} else {
/*
- * Handle EMSGSIZE with icmp reply needfrag for TCP MTU discovery
+ * Handle EMSGSIZE with icmp reply needfrag for TCP MTU
+ * discovery.
*/
if (ip_off & IP_DF) {
IPSTAT_INC(ips_cantfrag);
@@ -423,13 +450,20 @@
* Avoid confusing lower layers.
*/
m_clrprotoflags(m);
-
+#ifdef INET6
+ /*
+ * Notify ethernet layer that we need
+ * change ethertype for RFC5549 case.
+ */
+ if (nh.nh_flags & NHF_RFC5549)
+ m->m_flags |= M_ETHER_RFC5549;
+#endif
IP_PROBE(send, NULL, NULL,
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,
- (struct sockaddr *)&dst, NULL);
+ &dst.sa, NULL);
if (error)
break;
} while ((m = m0) != NULL);
Index: sys/netinet/ip_input.c
===================================================================
--- sys/netinet/ip_input.c
+++ sys/netinet/ip_input.c
@@ -39,6 +39,7 @@
#include "opt_ipsec.h"
#include "opt_route.h"
#include "opt_rss.h"
+#include "opt_inet6.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -1053,12 +1054,16 @@
#define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa))
u_long src = ntohl(ip->ip_src.s_addr);
- if (RTA(rt) &&
- (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) {
- if (rt->rt_flags & RTF_GATEWAY)
- dest.s_addr = satosin(rt->rt_gateway)->sin_addr.s_addr;
- else
- dest.s_addr = ip->ip_dst.s_addr;
+ if (RTA(rt) && (src & RTA(rt)->ia_subnetmask) ==
+ RTA(rt)->ia_subnet
+#ifdef INET6
+ && ((rt->rt_flags & RTF_GATEWAY) == 0 ||
+ rt->rt_gateway->sa_family == AF_INET)
+#endif /* INET6 */
+ ) {
+ dest = (rt->rt_flags & RTF_GATEWAY) ?
+ satosin(rt->rt_gateway)->sin_addr :
+ ip->ip_dst;
/* Router requirements says to only send host redirects */
type = ICMP_REDIRECT;
code = ICMP_REDIRECT_HOST;
Index: sys/netinet/ip_output.c
===================================================================
--- sys/netinet/ip_output.c
+++ sys/netinet/ip_output.c
@@ -35,6 +35,7 @@
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
+#include "opt_inet6.h"
#include "opt_ratelimit.h"
#include "opt_ipsec.h"
#include "opt_mbuf_stress_test.h"
@@ -222,7 +223,7 @@
int mtu;
int error = 0;
struct sockaddr_in *dst;
- const struct sockaddr_in *gw;
+ const struct sockaddr *gw;
struct in_ifaddr *ia;
int isbroadcast;
uint16_t ip_len, ip_off;
@@ -276,7 +277,8 @@
* gw is readonly but can point either to dst OR rt_gateway,
* therefore we need restore gw if we're redoing lookup.
*/
- gw = dst = (struct sockaddr_in *)&ro->ro_dst;
+ gw = &ro->ro_dst;
+ dst = (struct sockaddr_in *)&ro->ro_dst;
fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m);
rte = ro->ro_rt;
if (rte == NULL) {
@@ -391,11 +393,13 @@
counter_u64_add(rte->rt_pksent, 1);
rt_update_ro_flags(ro);
if (rte->rt_flags & RTF_GATEWAY)
- gw = (struct sockaddr_in *)rte->rt_gateway;
+ gw = rte->rt_gateway;
if (rte->rt_flags & RTF_HOST)
isbroadcast = (rte->rt_flags & RTF_BROADCAST);
- else if (ifp->if_flags & IFF_BROADCAST)
- isbroadcast = in_ifaddr_broadcast(gw->sin_addr, ia);
+ else if ((ifp->if_flags & IFF_BROADCAST) &&
+ gw->sa_family == AF_INET)
+ isbroadcast = in_ifaddr_broadcast(
+ ((const struct sockaddr_in *)gw)->sin_addr, ia);
else
isbroadcast = 0;
}
@@ -419,7 +423,7 @@
* still points to the address in "ro". (It may have been
* changed to point to a gateway address, above.)
*/
- gw = dst;
+ gw = (const struct sockaddr *)dst;
/*
* See if the caller provided any multicast options
*/
@@ -581,7 +585,7 @@
RO_RTFREE(ro);
ro->ro_prepend = NULL;
rte = NULL;
- gw = dst;
+ gw = (const struct sockaddr *)dst;
ip = mtod(m, struct ip *);
goto again;
@@ -646,6 +650,14 @@
* to avoid confusing lower layers.
*/
m_clrprotoflags(m);
+#ifdef INET6
+ /*
+ * Notify ethernet layer that we need change ethertype
+ * for RFC5549 case.
+ */
+ if (gw->sa_family == AF_INET6)
+ m->m_flags |= M_ETHER_RFC5549;
+#endif
IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL);
#ifdef RATELIMIT
if (inp != NULL) {
@@ -657,8 +669,7 @@
m->m_pkthdr.snd_tag = NULL;
}
#endif
- error = (*ifp->if_output)(ifp, m,
- (const struct sockaddr *)gw, ro);
+ error = (*ifp->if_output)(ifp, m, gw, ro);
#ifdef RATELIMIT
/* check for route change */
if (error == EAGAIN)
@@ -696,6 +707,14 @@
* to avoid confusing upper layers.
*/
m_clrprotoflags(m);
+#ifdef INET6
+ /*
+ * Notify ethernet layer that we need change
+ * ethertype for RFC5549 case.
+ */
+ if (gw->sa_family == AF_INET6)
+ m->m_flags |= M_ETHER_RFC5549;
+#endif
IP_PROBE(send, NULL, NULL, mtod(m, struct ip *), ifp,
mtod(m, struct ip *), NULL);
@@ -709,8 +728,7 @@
m->m_pkthdr.snd_tag = NULL;
}
#endif
- error = (*ifp->if_output)(ifp, m,
- (const struct sockaddr *)gw, ro);
+ error = (*ifp->if_output)(ifp, m, gw, ro);
#ifdef RATELIMIT
/* check for route change */
if (error == EAGAIN)
Index: sys/netinet6/icmp6.c
===================================================================
--- sys/netinet6/icmp6.c
+++ sys/netinet6/icmp6.c
@@ -229,9 +229,11 @@
{
struct ip6_hdr *ip6;
- if (ifp == NULL)
+ if (ifp == NULL || (m->m_flags & M_ETHER_RFC5549)) {
+ ICMP6STAT_INC(icp6s_canterror);
+ m_freem(m);
return;
-
+ }
#ifndef PULLDOWN_TEST
IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), );
#else
@@ -270,7 +272,7 @@
icmp6_errcount(type, code);
#ifdef M_DECRYPTED /*not openbsd*/
- if (m->m_flags & M_DECRYPTED) {
+ if (m->m_flags & (M_DECRYPTED | M_ETHER_RFC5549)) {
ICMP6STAT_INC(icp6s_canterror);
goto freeit;
}
Index: sys/netinet6/in6.h
===================================================================
--- sys/netinet6/in6.h
+++ sys/netinet6/in6.h
@@ -661,6 +661,7 @@
#define M_AUTHIPDGM M_PROTO7
#define M_RTALERT_MLD M_PROTO8
#define M_FRAGMENTED M_PROTO9 /* contained fragment header */
+#define M_ETHER_RFC5549 M_PROTO12 /* ethertype fix needed */
#ifdef _KERNEL
struct cmsghdr;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 29, 9:20 AM (16 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30520563
Default Alt Text
D18581.id52099.diff (14 KB)
Attached To
Mode
D18581: Add ability to forward IPv4 packets trough IPv6 only router
Attached
Detach File
Event Timeline
Log In to Comment