Page MenuHomeFreeBSD

D18581.id52099.diff
No OneTemporary

D18581.id52099.diff

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

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)

Event Timeline