summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet6/ip6_output.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-12-09 14:19:03 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-01-10 09:53:34 +0100
commit75b706fde4cbf82bcd41a1cec319778aa0f8eb2d (patch)
treeea39a351a1f6337b5a5dd6036314693adef5ffe6 /freebsd/sys/netinet6/ip6_output.c
parentVMSTAT(8): Port to RTEMS (diff)
downloadrtems-libbsd-75b706fde4cbf82bcd41a1cec319778aa0f8eb2d.tar.bz2
Update to FreeBSD head 2016-12-10
Git mirror commit 80c55f08a05ab3b26a73b226ccb56adc3122a55c.
Diffstat (limited to 'freebsd/sys/netinet6/ip6_output.c')
-rw-r--r--freebsd/sys/netinet6/ip6_output.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/freebsd/sys/netinet6/ip6_output.c b/freebsd/sys/netinet6/ip6_output.c
index d3dc973e..63d1dac1 100644
--- a/freebsd/sys/netinet6/ip6_output.c
+++ b/freebsd/sys/netinet6/ip6_output.c
@@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/if_llatbl.h>
#include <net/netisr.h>
#include <net/route.h>
#include <net/pfil.h>
@@ -260,7 +261,7 @@ ip6_fragment(struct ifnet *ifp, struct mbuf *m0, int hlen, u_char nextproto,
ip6f->ip6f_offlg |= IP6F_MORE_FRAG;
mhip6->ip6_plen = htons((u_short)(mtu + hlen +
sizeof(*ip6f) - sizeof(struct ip6_hdr)));
- if ((m_frgpart = m_copy(m0, off, mtu)) == NULL) {
+ if ((m_frgpart = m_copym(m0, off, mtu, M_NOWAIT)) == NULL) {
IP6STAT_INC(ip6s_odropped);
return (ENOBUFS);
}
@@ -554,6 +555,9 @@ again:
rt = ro->ro_rt;
ifp = ro->ro_rt->rt_ifp;
} else {
+ if (ro->ro_lle)
+ LLE_FREE(ro->ro_lle); /* zeros ro_lle */
+ ro->ro_lle = NULL;
if (fwd_tag == NULL) {
bzero(&dst_sa, sizeof(dst_sa));
dst_sa.sin6_family = AF_INET6;
@@ -823,6 +827,9 @@ again:
} else {
RO_RTFREE(ro);
needfiblookup = 1; /* Redo the routing table lookup. */
+ if (ro->ro_lle)
+ LLE_FREE(ro->ro_lle); /* zeros ro_lle */
+ ro->ro_lle = NULL;
}
}
/* See if fib was changed by packet filter. */
@@ -831,6 +838,9 @@ again:
fibnum = M_GETFIB(m);
RO_RTFREE(ro);
needfiblookup = 1;
+ if (ro->ro_lle)
+ LLE_FREE(ro->ro_lle); /* zeros ro_lle */
+ ro->ro_lle = NULL;
}
if (needfiblookup)
goto again;
@@ -1056,12 +1066,7 @@ sendorfree:
IP6STAT_INC(ip6s_fragmented);
done:
- /*
- * Release the route if using our private route, or if
- * (with flowtable) we don't have our own reference.
- */
- if (ro == &ip6route ||
- (ro != NULL && ro->ro_flags & RT_NORTREF))
+ if (ro == &ip6route)
RO_RTFREE(ro);
return (error);
@@ -1390,6 +1395,15 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
int retval;
#endif
+/*
+ * Don't use more than a quarter of mbuf clusters. N.B.:
+ * nmbclusters is an int, but nmbclusters * MCLBYTES may overflow
+ * on LP64 architectures, so cast to u_long to avoid undefined
+ * behavior. ILP32 architectures cannot have nmbclusters
+ * large enough to overflow for other reasons.
+ */
+#define IPV6_PKTOPTIONS_MBUF_LIMIT ((u_long)nmbclusters * MCLBYTES / 4)
+
level = sopt->sopt_level;
op = sopt->sopt_dir;
optname = sopt->sopt_name;
@@ -1445,6 +1459,12 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
{
struct mbuf *m;
+ if (optlen > IPV6_PKTOPTIONS_MBUF_LIMIT) {
+ printf("ip6_ctloutput: mbuf limit hit\n");
+ error = ENOBUFS;
+ break;
+ }
+
error = soopt_getm(sopt, &m); /* XXX */
if (error != 0)
break;
@@ -2995,7 +3015,7 @@ ip6_mloopback(struct ifnet *ifp, struct mbuf *m)
struct mbuf *copym;
struct ip6_hdr *ip6;
- copym = m_copy(m, 0, M_COPYALL);
+ copym = m_copym(m, 0, M_COPYALL, M_NOWAIT);
if (copym == NULL)
return;