summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet6
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2015-04-08 15:37:49 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2015-05-20 09:58:21 +0200
commit165dd8ea1256d71d6a4f52c0a66dcc2799ef8f99 (patch)
treec42072a99573d4d7cc03b2263e2c0c6d53f9c691 /freebsd/sys/netinet6
parentrtems-bsd-chunk: Include missing header file (diff)
downloadrtems-libbsd-165dd8ea1256d71d6a4f52c0a66dcc2799ef8f99.tar.bz2
Update to FreeBSD Stable/9 2015-04-08
Diffstat (limited to 'freebsd/sys/netinet6')
-rw-r--r--freebsd/sys/netinet6/icmp6.c2
-rw-r--r--freebsd/sys/netinet6/in6.c27
-rw-r--r--freebsd/sys/netinet6/in6_mcast.c2
-rw-r--r--freebsd/sys/netinet6/in6_pcb.c12
-rw-r--r--freebsd/sys/netinet6/in6_src.c10
-rw-r--r--freebsd/sys/netinet6/in6_var.h1
-rw-r--r--freebsd/sys/netinet6/ip6_input.c29
-rw-r--r--freebsd/sys/netinet6/ip6_output.c17
-rw-r--r--freebsd/sys/netinet6/ip6_var.h3
-rw-r--r--freebsd/sys/netinet6/nd6.c2
-rw-r--r--freebsd/sys/netinet6/nd6.h2
-rw-r--r--freebsd/sys/netinet6/nd6_nbr.c39
-rw-r--r--freebsd/sys/netinet6/nd6_rtr.c12
-rw-r--r--freebsd/sys/netinet6/scope6.c31
-rw-r--r--freebsd/sys/netinet6/scope6_var.h3
15 files changed, 105 insertions, 87 deletions
diff --git a/freebsd/sys/netinet6/icmp6.c b/freebsd/sys/netinet6/icmp6.c
index 20b03a21..49b1bd8a 100644
--- a/freebsd/sys/netinet6/icmp6.c
+++ b/freebsd/sys/netinet6/icmp6.c
@@ -363,8 +363,6 @@ icmp6_error(struct mbuf *m, int type, int code, int param)
preplen = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
M_PREPEND(m, preplen, M_DONTWAIT); /* FIB is also copied over. */
- if (m && m->m_len < preplen)
- m = m_pullup(m, preplen);
if (m == NULL) {
nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__));
return;
diff --git a/freebsd/sys/netinet6/in6.c b/freebsd/sys/netinet6/in6.c
index f68f21f2..8dc4d29f 100644
--- a/freebsd/sys/netinet6/in6.c
+++ b/freebsd/sys/netinet6/in6.c
@@ -286,7 +286,7 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
return (mrt6_ioctl ? mrt6_ioctl(cmd, data) : EOPNOTSUPP);
}
- switch(cmd) {
+ switch (cmd) {
case SIOCAADDRCTL_POLICY:
case SIOCDADDRCTL_POLICY:
if (td != NULL) {
@@ -358,14 +358,10 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
if (error)
return (error);
}
- return (scope6_set(ifp,
- (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
+ /* FALLTHROUGH */
case SIOCGSCOPE6:
- return (scope6_get(ifp,
- (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
case SIOCGSCOPE6DEF:
- return (scope6_get_default((struct scope6_id *)
- ifr->ifr_ifru.ifru_scope_id));
+ return (scope6_ioctl(cmd, data, ifp));
}
switch (cmd) {
@@ -496,6 +492,13 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
if (error)
goto out;
}
+ /* FALLTHROUGH */
+ case SIOCGIFSTAT_IN6:
+ case SIOCGIFSTAT_ICMP6:
+ if (ifp->if_afdata[AF_INET6] == NULL) {
+ error = EPFNOSUPPORT;
+ goto out;
+ }
break;
case SIOCGIFADDR_IN6:
@@ -571,10 +574,6 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
break;
case SIOCGIFSTAT_IN6:
- if (ifp == NULL) {
- error = EINVAL;
- goto out;
- }
bzero(&ifr->ifr_ifru.ifru_stat,
sizeof(ifr->ifr_ifru.ifru_stat));
ifr->ifr_ifru.ifru_stat =
@@ -582,10 +581,6 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
break;
case SIOCGIFSTAT_ICMP6:
- if (ifp == NULL) {
- error = EINVAL;
- goto out;
- }
bzero(&ifr->ifr_ifru.ifru_icmp6stat,
sizeof(ifr->ifr_ifru.ifru_icmp6stat));
ifr->ifr_ifru.ifru_icmp6stat =
@@ -801,7 +796,7 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
}
default:
- if (ifp == NULL || ifp->if_ioctl == 0) {
+ if (ifp->if_ioctl == NULL) {
error = EOPNOTSUPP;
goto out;
}
diff --git a/freebsd/sys/netinet6/in6_mcast.c b/freebsd/sys/netinet6/in6_mcast.c
index e5457707..d32d57c6 100644
--- a/freebsd/sys/netinet6/in6_mcast.c
+++ b/freebsd/sys/netinet6/in6_mcast.c
@@ -1077,6 +1077,8 @@ in6m_purge(struct in6_multi *inm)
free(ims, M_IP6MSOURCE);
inm->in6m_nsrc--;
}
+ /* Free state-change requests that might be queued. */
+ _IF_DRAIN(&inm->in6m_scq);
}
/*
diff --git a/freebsd/sys/netinet6/in6_pcb.c b/freebsd/sys/netinet6/in6_pcb.c
index 4b0b3389..8a7581c9 100644
--- a/freebsd/sys/netinet6/in6_pcb.c
+++ b/freebsd/sys/netinet6/in6_pcb.c
@@ -638,18 +638,12 @@ in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr *dst,
/*
* If the error designates a new path MTU for a destination
* and the application (associated with this socket) wanted to
- * know the value, notify. Note that we notify for all
- * disconnected sockets if the corresponding application
- * wanted. This is because some UDP applications keep sending
- * sockets disconnected.
+ * know the value, notify.
* XXX: should we avoid to notify the value to TCP sockets?
*/
- if (cmd == PRC_MSGSIZE && (inp->inp_flags & IN6P_MTU) != 0 &&
- (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) ||
- IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &sa6_dst->sin6_addr))) {
+ if (cmd == PRC_MSGSIZE && cmdarg != NULL)
ip6_notify_pmtu(inp, (struct sockaddr_in6 *)dst,
- (u_int32_t *)cmdarg);
- }
+ *(u_int32_t *)cmdarg);
/*
* Detect if we should notify the error. If no source and
diff --git a/freebsd/sys/netinet6/in6_src.c b/freebsd/sys/netinet6/in6_src.c
index cc2f5ee5..79beb703 100644
--- a/freebsd/sys/netinet6/in6_src.c
+++ b/freebsd/sys/netinet6/in6_src.c
@@ -445,6 +445,16 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
REPLACE(8);
/*
+ * Rule 10: prefer address with `prefer_source' flag.
+ */
+ if ((ia_best->ia6_flags & IN6_IFF_PREFER_SOURCE) == 0 &&
+ (ia->ia6_flags & IN6_IFF_PREFER_SOURCE) != 0)
+ REPLACE(10);
+ if ((ia_best->ia6_flags & IN6_IFF_PREFER_SOURCE) != 0 &&
+ (ia->ia6_flags & IN6_IFF_PREFER_SOURCE) == 0)
+ NEXT(10);
+
+ /*
* Rule 14: Use longest matching prefix.
* Note: in the address selection draft, this rule is
* documented as "Rule 8". However, since it is also
diff --git a/freebsd/sys/netinet6/in6_var.h b/freebsd/sys/netinet6/in6_var.h
index c7ebe523..90530a68 100644
--- a/freebsd/sys/netinet6/in6_var.h
+++ b/freebsd/sys/netinet6/in6_var.h
@@ -473,6 +473,7 @@ struct in6_rrenumreq {
*/
#define IN6_IFF_AUTOCONF 0x40 /* autoconfigurable address. */
#define IN6_IFF_TEMPORARY 0x80 /* temporary (anonymous) address. */
+#define IN6_IFF_PREFER_SOURCE 0x0100 /* preferred address for SAS */
#define IN6_IFF_NOPFX 0x8000 /* skip kernel prefix management.
* XXX: this should be temporary.
*/
diff --git a/freebsd/sys/netinet6/ip6_input.c b/freebsd/sys/netinet6/ip6_input.c
index 0de64eb7..17420faf 100644
--- a/freebsd/sys/netinet6/ip6_input.c
+++ b/freebsd/sys/netinet6/ip6_input.c
@@ -1605,24 +1605,28 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
#undef IS2292
void
-ip6_notify_pmtu(struct inpcb *in6p, struct sockaddr_in6 *dst, u_int32_t *mtu)
+ip6_notify_pmtu(struct inpcb *inp, struct sockaddr_in6 *dst, u_int32_t mtu)
{
struct socket *so;
struct mbuf *m_mtu;
struct ip6_mtuinfo mtuctl;
- so = in6p->inp_socket;
-
- if (mtu == NULL)
+ KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
+ /*
+ * Notify the error by sending IPV6_PATHMTU ancillary data if
+ * application wanted to know the MTU value.
+ * NOTE: we notify disconnected sockets, because some udp
+ * applications keep sending sockets disconnected.
+ * NOTE: our implementation doesn't notify connected sockets that has
+ * foreign address that is different than given destination addresses
+ * (this is permitted by RFC 3542).
+ */
+ if ((inp->inp_flags & IN6P_MTU) == 0 || (
+ !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
+ !IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &dst->sin6_addr)))
return;
-#ifdef DIAGNOSTIC
- if (so == NULL) /* I believe this is impossible */
- panic("ip6_notify_pmtu: socket is NULL");
-#endif
-
- bzero(&mtuctl, sizeof(mtuctl)); /* zero-clear for safety */
- mtuctl.ip6m_mtu = *mtu;
+ mtuctl.ip6m_mtu = mtu;
mtuctl.ip6m_addr = *dst;
if (sa6_recoverscope(&mtuctl.ip6m_addr))
return;
@@ -1631,14 +1635,13 @@ ip6_notify_pmtu(struct inpcb *in6p, struct sockaddr_in6 *dst, u_int32_t *mtu)
IPV6_PATHMTU, IPPROTO_IPV6)) == NULL)
return;
+ so = inp->inp_socket;
if (sbappendaddr(&so->so_rcv, (struct sockaddr *)dst, NULL, m_mtu)
== 0) {
m_freem(m_mtu);
/* XXX: should count statistics */
} else
sorwakeup(so);
-
- return;
}
#ifdef PULLDOWN_TEST
diff --git a/freebsd/sys/netinet6/ip6_output.c b/freebsd/sys/netinet6/ip6_output.c
index 06f1246a..95231631 100644
--- a/freebsd/sys/netinet6/ip6_output.c
+++ b/freebsd/sys/netinet6/ip6_output.c
@@ -998,19 +998,12 @@ passout:
* Even if the DONTFRAG option is specified, we cannot send the
* packet when the data length is larger than the MTU of the
* outgoing interface.
- * Notify the error by sending IPV6_PATHMTU ancillary data as
- * well as returning an error code (the latter is not described
- * in the API spec.)
+ * Notify the error by sending IPV6_PATHMTU ancillary data if
+ * application wanted to know the MTU value. Also return an
+ * error code (this is not described in the API spec).
*/
- u_int32_t mtu32;
- struct ip6ctlparam ip6cp;
-
- mtu32 = (u_int32_t)mtu;
- bzero(&ip6cp, sizeof(ip6cp));
- ip6cp.ip6c_cmdarg = (void *)&mtu32;
- pfctlinput2(PRC_MSGSIZE, (struct sockaddr *)&ro_pmtu->ro_dst,
- (void *)&ip6cp);
-
+ if (inp != NULL)
+ ip6_notify_pmtu(inp, &dst_sa, (u_int32_t)mtu);
error = EMSGSIZE;
goto bad;
}
diff --git a/freebsd/sys/netinet6/ip6_var.h b/freebsd/sys/netinet6/ip6_var.h
index 4a094d42..4e8c42bd 100644
--- a/freebsd/sys/netinet6/ip6_var.h
+++ b/freebsd/sys/netinet6/ip6_var.h
@@ -406,8 +406,7 @@ int ip6_process_hopopts(struct mbuf *, u_int8_t *, int, u_int32_t *,
struct mbuf **ip6_savecontrol_v4(struct inpcb *, struct mbuf *,
struct mbuf **, int *);
void ip6_savecontrol(struct inpcb *, struct mbuf *, struct mbuf **);
-void ip6_notify_pmtu(struct inpcb *, struct sockaddr_in6 *,
- u_int32_t *);
+void ip6_notify_pmtu(struct inpcb *, struct sockaddr_in6 *, u_int32_t);
int ip6_sysctl(int *, u_int, void *, size_t *, void *, size_t);
void ip6_forward(struct mbuf *, int);
diff --git a/freebsd/sys/netinet6/nd6.c b/freebsd/sys/netinet6/nd6.c
index 9233bef5..1b855cae 100644
--- a/freebsd/sys/netinet6/nd6.c
+++ b/freebsd/sys/netinet6/nd6.c
@@ -2283,6 +2283,8 @@ SYSCTL_NODE(_net_inet6_icmp6, ICMPV6CTL_ND6_PRLIST, nd6_prlist,
CTLFLAG_RD, nd6_sysctl_prlist, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXQLEN, nd6_maxqueuelen,
CTLFLAG_RW, &VNET_NAME(nd6_maxqueuelen), 1, "");
+SYSCTL_VNET_INT(_net_inet6_icmp6, OID_AUTO, nd6_gctimer,
+ CTLFLAG_RW, &VNET_NAME(nd6_gctimer), (60 * 60 * 24), "");
static int
nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS)
diff --git a/freebsd/sys/netinet6/nd6.h b/freebsd/sys/netinet6/nd6.h
index 79e41e38..94202e10 100644
--- a/freebsd/sys/netinet6/nd6.h
+++ b/freebsd/sys/netinet6/nd6.h
@@ -79,7 +79,7 @@ struct nd_ifinfo {
#define ND6_IFF_PERFORMNUD 0x1
#define ND6_IFF_ACCEPT_RTADV 0x2
-#define ND6_IFF_PREFER_SOURCE 0x4 /* XXX: not related to ND. */
+#define ND6_IFF_PREFER_SOURCE 0x4 /* Not used in FreeBSD. */
#define ND6_IFF_IFDISABLED 0x8 /* IPv6 operation is disabled due to
* DAD failure. (XXX: not ND-specific)
*/
diff --git a/freebsd/sys/netinet6/nd6_nbr.c b/freebsd/sys/netinet6/nd6_nbr.c
index 09011b7e..ce26d54f 100644
--- a/freebsd/sys/netinet6/nd6_nbr.c
+++ b/freebsd/sys/netinet6/nd6_nbr.c
@@ -234,41 +234,28 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
/* (2) check. */
if (ifa == NULL) {
- struct rtentry *rt;
- struct sockaddr_in6 tsin6;
- int need_proxy;
-#ifdef RADIX_MPATH
struct route_in6 ro;
-#endif
+ int need_proxy;
- bzero(&tsin6, sizeof tsin6);
- tsin6.sin6_len = sizeof(struct sockaddr_in6);
- tsin6.sin6_family = AF_INET6;
- tsin6.sin6_addr = taddr6;
+ bzero(&ro, sizeof(ro));
+ ro.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
+ ro.ro_dst.sin6_family = AF_INET6;
+ ro.ro_dst.sin6_addr = taddr6;
/* Always use the default FIB. */
#ifdef RADIX_MPATH
- bzero(&ro, sizeof(ro));
- ro.ro_dst = tsin6;
rtalloc_mpath_fib((struct route *)&ro, RTF_ANNOUNCE,
RT_DEFAULT_FIB);
- rt = ro.ro_rt;
#else
- rt = in6_rtalloc1((struct sockaddr *)&tsin6, 0, 0,
- RT_DEFAULT_FIB);
+ in6_rtalloc(&ro, RT_DEFAULT_FIB);
#endif
- need_proxy = (rt && (rt->rt_flags & RTF_ANNOUNCE) != 0 &&
- rt->rt_gateway->sa_family == AF_LINK);
- if (rt != NULL) {
- /*
- * Make a copy while we can be sure that rt_gateway
- * is still stable before unlocking to avoid lock
- * order problems. proxydl will only be used if
- * proxy will be set in the next block.
- */
+ need_proxy = (ro.ro_rt &&
+ (ro.ro_rt->rt_flags & RTF_ANNOUNCE) != 0 &&
+ ro.ro_rt->rt_gateway->sa_family == AF_LINK);
+ if (ro.ro_rt != NULL) {
if (need_proxy)
- proxydl = *SDL(rt->rt_gateway);
- RTFREE_LOCKED(rt);
+ proxydl = *SDL(ro.ro_rt->rt_gateway);
+ RTFREE(ro.ro_rt);
}
if (need_proxy) {
/*
@@ -711,8 +698,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
*/
if (ifa
&& (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
- ifa_free(ifa);
nd6_dad_na_input(ifa);
+ ifa_free(ifa);
goto freeit;
}
diff --git a/freebsd/sys/netinet6/nd6_rtr.c b/freebsd/sys/netinet6/nd6_rtr.c
index bd6fa33b..030cac3d 100644
--- a/freebsd/sys/netinet6/nd6_rtr.c
+++ b/freebsd/sys/netinet6/nd6_rtr.c
@@ -298,8 +298,16 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
}
if (nd_ra->nd_ra_retransmit)
ndi->retrans = ntohl(nd_ra->nd_ra_retransmit);
- if (nd_ra->nd_ra_curhoplimit)
- ndi->chlim = nd_ra->nd_ra_curhoplimit;
+ if (nd_ra->nd_ra_curhoplimit) {
+ if (ndi->chlim < nd_ra->nd_ra_curhoplimit)
+ ndi->chlim = nd_ra->nd_ra_curhoplimit;
+ else if (ndi->chlim != nd_ra->nd_ra_curhoplimit) {
+ log(LOG_ERR, "RA with a lower CurHopLimit sent from "
+ "%s on %s (current = %d, received = %d). "
+ "Ignored.\n", ip6_sprintf(ip6bufs, &ip6->ip6_src),
+ if_name(ifp), ndi->chlim, nd_ra->nd_ra_curhoplimit);
+ }
+ }
dr = defrtrlist_update(&dr0);
}
diff --git a/freebsd/sys/netinet6/scope6.c b/freebsd/sys/netinet6/scope6.c
index f891c9ce..2ccd2f7a 100644
--- a/freebsd/sys/netinet6/scope6.c
+++ b/freebsd/sys/netinet6/scope6.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
+#include <sys/sockio.h>
#include <sys/systm.h>
#include <sys/queue.h>
#include <sys/syslog.h>
@@ -74,6 +75,9 @@ static VNET_DEFINE(struct scope6_id, sid_default);
#define SID(ifp) \
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->scope6_id)
+static int scope6_get(struct ifnet *, struct scope6_id *);
+static int scope6_set(struct ifnet *, struct scope6_id *);
+
void
scope6_init(void)
{
@@ -117,6 +121,30 @@ scope6_ifdetach(struct scope6_id *sid)
}
int
+scope6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
+{
+ struct in6_ifreq *ifr;
+
+ if (ifp->if_afdata[AF_INET6] == NULL)
+ return (EPFNOSUPPORT);
+
+ ifr = (struct in6_ifreq *)data;
+ switch (cmd) {
+ case SIOCSSCOPE6:
+ return (scope6_set(ifp,
+ (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
+ case SIOCGSCOPE6:
+ return (scope6_get(ifp,
+ (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
+ case SIOCGSCOPE6DEF:
+ return (scope6_get_default(
+ (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
+ default:
+ return (EOPNOTSUPP);
+ }
+}
+
+static int
scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
{
int i;
@@ -179,7 +207,7 @@ scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
return (error);
}
-int
+static int
scope6_get(struct ifnet *ifp, struct scope6_id *idlist)
{
struct scope6_id *sid;
@@ -198,7 +226,6 @@ scope6_get(struct ifnet *ifp, struct scope6_id *idlist)
return (0);
}
-
/*
* Get a scope of the address. Node-local, link-local, site-local or global.
*/
diff --git a/freebsd/sys/netinet6/scope6_var.h b/freebsd/sys/netinet6/scope6_var.h
index ae337b86..990325e9 100644
--- a/freebsd/sys/netinet6/scope6_var.h
+++ b/freebsd/sys/netinet6/scope6_var.h
@@ -45,8 +45,7 @@ struct scope6_id {
void scope6_init(void);
struct scope6_id *scope6_ifattach(struct ifnet *);
void scope6_ifdetach(struct scope6_id *);
-int scope6_set(struct ifnet *, struct scope6_id *);
-int scope6_get(struct ifnet *, struct scope6_id *);
+int scope6_ioctl(u_long cmd, caddr_t data, struct ifnet *);
void scope6_setdefault(struct ifnet *);
int scope6_get_default(struct scope6_id *);
u_int32_t scope6_addr2default(struct in6_addr *);