/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
extern struct inpcbhead ripcb;
extern int icmp6errppslim;
+extern int icmp6errppslim_random_incr;
extern int icmp6rappslim;
static int icmp6errpps_count = 0;
static int icmp6rapps_count = 0;
static const char *icmp6_redirect_diag(struct in6_addr *,
struct in6_addr *, struct in6_addr *);
static struct mbuf *ni6_input(struct mbuf *, int);
-static struct mbuf *ni6_nametodns(const char *, int, int);
+static struct mbuf *ni6_nametodns(const char *, uint32_t, int);
static int ni6_dnsmatch(const char *, int, const char *, int);
static int ni6_addrs(struct icmp6_nodeinfo *,
struct ifnet **, char *);
if (!icmp6_initialized) {
icmp6_initialized = 1;
mld_init();
+ if (icmp6errppslim >= 0 &&
+ icmp6errppslim_random_incr > 0 &&
+ icmp6errppslim <= INT32_MAX - (icmp6errppslim_random_incr + 1)) {
+ icmp6errppslim += (random() % icmp6errppslim_random_incr) + 1;
+ }
}
}
struct icmp6_hdr *icmp6;
u_int preplen;
int off;
- int nxt;
icmp6stat.icp6s_error++;
/*
* If we are about to send ICMPv6 against ICMPv6 error/redirect,
* don't do it.
+ *
+ * We want to check for that for all ICMP error types, other than
+ * ICMP6_PARAM_PROB when it is being sent in response of first frag
+ * with incomplete header.
+ * That also includes the case when the first frag has incomplete ICMPv6
+ * header. The check below in that case would fail the IP6_EXTHDR_CHECK
+ * and would otherwise prevent us from sending the error back.
*/
- nxt = -1;
- off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
- if (off >= 0 && nxt == IPPROTO_ICMPV6) {
- struct icmp6_hdr *icp;
+ if (type != ICMP6_PARAM_PROB ||
+ code != ICMP6_PARAMPROB_FIRSTFRAG_INCOMP_HDR) {
+ int nxt = -1;
+ off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
+ if (off >= 0 && nxt == IPPROTO_ICMPV6) {
+ struct icmp6_hdr *icp;
#ifndef PULLDOWN_TEST
- IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct icmp6_hdr), return );
- icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
+ IP6_EXTHDR_CHECK(m, 0, off + sizeof(struct icmp6_hdr), return );
+ icp = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
#else
- IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,
- sizeof(*icp));
- if (icp == NULL) {
- icmp6stat.icp6s_tooshort++;
- return;
- }
+ IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,
+ sizeof(*icp));
+ if (icp == NULL) {
+ icmp6stat.icp6s_tooshort++;
+ return;
+ }
#endif
- if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
- icp->icmp6_type == ND_REDIRECT) {
- /*
- * ICMPv6 error
- * Special case: for redirect (which is
- * informational) we must not send icmp6 error.
- */
- icmp6stat.icp6s_canterror++;
- goto freeit;
+ if (icp->icmp6_type < ICMP6_ECHO_REQUEST ||
+ icp->icmp6_type == ND_REDIRECT) {
+ /*
+ * ICMPv6 error
+ * Special case: for redirect (which is
+ * informational) we must not send icmp6 error.
+ */
+ icmp6stat.icp6s_canterror++;
+ goto freeit;
+ } else {
+ /* ICMPv6 informational - send the error */
+ }
} else {
- /* ICMPv6 informational - send the error */
+ /* non-ICMPv6 - send the error */
}
- } else {
- /* non-ICMPv6 - send the error */
}
oip6 = mtod(m, struct ip6_hdr *); /* adjust pointer */
m = m_pullup(m, preplen);
}
if (m == NULL) {
- nd6log((LOG_DEBUG, "ENOBUFS in icmp6_error %d\n", __LINE__));
+ nd6log(debug, "ENOBUFS in icmp6_error %d\n", __LINE__);
return;
}
in6_clearscope(&oip6->ip6_dst);
icmp6 = (struct icmp6_hdr *)(nip6 + 1);
- icmp6->icmp6_type = type;
- icmp6->icmp6_code = code;
+ icmp6->icmp6_type = (uint8_t)type;
+ icmp6->icmp6_code = (uint8_t)code;
icmp6->icmp6_pptr = htonl((u_int32_t)param);
/*
* calculate the checksum
*/
if ((sum = in6_cksum(m, IPPROTO_ICMPV6, off, icmp6len)) != 0) {
- nd6log((LOG_ERR,
+ nd6log(error,
"ICMP6 checksum error(%d|%x) %s\n",
- icmp6->icmp6_type, sum, ip6_sprintf(&ip6->ip6_src)));
+ icmp6->icmp6_type, sum, ip6_sprintf(&ip6->ip6_src));
icmp6stat.icp6s_checksum++;
goto freeit;
}
case ICMP6_PACKET_TOO_BIG:
icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_pkttoobig);
+ if (ntohl(icmp6->icmp6_mtu) < IPV6_MMTU) {
+ icmp6stat.icp6s_badpkttoobig++;
+ goto freeit;
+ }
code = PRC_MSGSIZE;
if ((n = m_copym(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
/* give up local */
- icmp6_redirect_input(m, off);
+ icmp6_redirect_input(m, off, icmp6len);
m = NULL;
goto freeit;
}
- icmp6_redirect_input(n, off);
+ icmp6_redirect_input(n, off, icmp6len);
/* m stays. */
goto rate_limit_checked;
break;
default:
- nd6log((LOG_DEBUG,
+ nd6log(debug,
"icmp6_input: unknown type %d(src=%s, dst=%s, ifid=%d)\n",
icmp6->icmp6_type, ip6_sprintf(&ip6->ip6_src),
ip6_sprintf(&ip6->ip6_dst),
- m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0));
+ m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0);
if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) {
/* ICMPv6 error: MUST deliver it by spec... */
code = PRC_NCMDS;
}
#endif
eip6 = (struct ip6_hdr *)(icmp6 + 1);
+ bzero(&icmp6dst, sizeof(icmp6dst));
/* Detect the upper level protocol */
{
int eoff = off + sizeof(struct icmp6_hdr) +
sizeof(struct ip6_hdr);
struct ip6ctlparam ip6cp;
- struct in6_addr *finaldst = NULL;
int icmp6type = icmp6->icmp6_type;
struct ip6_frag *fh;
struct ip6_rthdr *rth;
/* just ignore a bogus header */
if ((rth0->ip6r0_len % 2) == 0 &&
(hops = rth0->ip6r0_len / 2)) {
- finaldst = (struct in6_addr *)(void *)(rth0 + 1) + (hops - 1);
+ icmp6dst.sin6_addr = *((struct in6_addr *)(void *)(rth0 + 1) + (hops - 1));
}
}
eoff += rthlen;
*/
eip6 = (struct ip6_hdr *)(icmp6 + 1);
- bzero(&icmp6dst, sizeof(icmp6dst));
icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
icmp6dst.sin6_family = AF_INET6;
- if (finaldst == NULL) {
+ if (IN6_IS_ADDR_UNSPECIFIED(&icmp6dst.sin6_addr)) {
icmp6dst.sin6_addr = eip6->ip6_dst;
- } else {
- icmp6dst.sin6_addr = *finaldst;
}
if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL)) {
goto freeit;
icmp6src.sin6_flowinfo =
(eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
- if (finaldst == NULL) {
- finaldst = &eip6->ip6_dst;
- }
ip6cp.ip6c_m = m;
ip6cp.ip6c_icmp6 = icmp6;
ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
ip6cp.ip6c_off = eoff;
- ip6cp.ip6c_finaldst = finaldst;
+ ip6cp.ip6c_finaldst = &icmp6dst.sin6_addr;
ip6cp.ip6c_src = &icmp6src;
ip6cp.ip6c_nxt = nxt;
return;
}
- /*
- * In case the suggested mtu is less than IPV6_MMTU, we
- * only need to remember that it was for above mentioned
- * "alwaysfrag" case.
- * Try to be as close to the spec as possible.
- */
+ /* Limit the MTU to the minimum IPv6 MTU */
if (mtu < IPV6_MMTU) {
- mtu = IPV6_MMTU - 8;
+ mtu = IPV6_MMTU;
}
bzero(&sin6, sizeof(sin6));
* - joins NI group address at in6_ifattach() time only, does not cope
* with hostname changes by sethostname(3)
*/
-#define hostnamelen strlen(hostname)
+#define hostnamelen (uint32_t)strlen(hostname)
static struct mbuf *
ni6_input(struct mbuf *m, int off)
{
* [RFC4602, Section 5.]
*/
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
- if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) {
+ if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst) &&
+ !IN6_IS_ADDR_MC_UNICAST_BASED_LINKLOCAL(&ip6->ip6_dst)) {
goto bad;
}
/* else it's a link-local multicast, fine */
}
if ((ia6_flags & IN6_IFF_TEMPORARY) &&
!(icmp6_nodeinfo & ICMP6_NODEINFO_TMPADDROK)) {
- nd6log((LOG_DEBUG, "ni6_input: ignore node info to "
- "a temporary address in %s:%d",
- __func__, __LINE__));
+ nd6log(debug, "ni6_input: ignore node info to a temporary address in %s:%d",
+ __func__, __LINE__);
goto bad;
}
}
if (ni6->ni_code == ICMP6_NI_SUBJ_FQDN && subjlen == 0) {
break;
}
- /* FALLTHROUGH */
+ OS_FALLTHROUGH;
case NI_QTYPE_FQDN:
case NI_QTYPE_NODEADDR:
case NI_QTYPE_IPV4ADDR:
* wildcard match, if gethostname(3) side has
* truncated hostname.
*/
+ lck_mtx_lock(&hostname_lock);
n = ni6_nametodns(hostname, hostnamelen, 0);
+ lck_mtx_unlock(&hostname_lock);
if (!n || n->m_next || n->m_len == 0) {
goto bad;
}
/*
* XXX do we really have FQDN in variable "hostname"?
*/
+ lck_mtx_lock(&hostname_lock);
n->m_next = ni6_nametodns(hostname, hostnamelen, oldfqdn);
+ lck_mtx_unlock(&hostname_lock);
if (n->m_next == NULL) {
goto bad;
}
nni6->ni_code = ICMP6_NI_SUCCESS;
n->m_pkthdr.len = n->m_len =
sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
- lenlim = M_TRAILINGSPACE(n);
+ lenlim = (int)M_TRAILINGSPACE(n);
copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
/* XXX: reset mbuf length */
n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
static struct mbuf *
ni6_nametodns(
const char *name,
- int namelen,
+ uint32_t namelen,
int old) /* return pascal string if non-zero */
{
struct mbuf *m;
char *cp, *ep;
const char *p, *q;
- int i, len, nterm;
+ int i, nterm;
+ uint32_t len;
if (old) {
len = namelen + 1;
if (old) {
m->m_len = len;
- *mtod(m, char *) = namelen;
+ *mtod(m, char *) = (char)namelen;
bcopy(name, mtod(m, char *) + 1, namelen);
return m;
} else {
if (i <= 0 || i >= 64) {
goto fail;
}
- *cp++ = i;
+ *cp++ = (char)i;
bcopy(p, cp, i);
cp += i;
p = q;
while (nterm-- > 0) {
*cp++ = '\0';
}
- m->m_len = cp - mtod(m, char *);
+ m->m_len = (int32_t)(cp - mtod(m, char *));
return m;
}
ltime = ND6_INFINITE_LIFETIME;
} else {
if (lt->ia6ti_expire > now) {
- ltime = htonl(lt->ia6ti_expire - now);
+ ltime = htonl((uint32_t)(lt->ia6ti_expire - now));
} else {
ltime = 0;
}
struct mbuf *n;
if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
if ((last->in6p_flags & INP_CONTROLOPTS) != 0 ||
+#if CONTENT_FILTER
+ /* Content Filter needs to see local address */
+ (last->in6p_socket->so_cfil_db != NULL) ||
+#endif
(last->in6p_socket->so_options & SO_TIMESTAMP) != 0 ||
(last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0 ||
(last->in6p_socket->so_options & SO_TIMESTAMP_CONTINUOUS) != 0) {
}
if (last) {
if ((last->in6p_flags & INP_CONTROLOPTS) != 0 ||
+#if CONTENT_FILTER
+ /* Content Filter needs to see local address */
+ (last->in6p_socket->so_cfil_db != NULL) ||
+#endif
(last->in6p_socket->so_options & SO_TIMESTAMP) != 0 ||
(last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0 ||
(last->in6p_socket->so_options & SO_TIMESTAMP_CONTINUOUS) != 0) {
/* too short to reflect */
if (off < sizeof(struct ip6_hdr)) {
- nd6log((LOG_DEBUG,
- "sanity fail: off=%lx, sizeof(ip6)=%lx in %s:%d\n",
+ nd6log(debug,
+ "sanity fail: off=%x, sizeof(ip6)=%x in %s:%d\n",
(u_int32_t)off, (u_int32_t)sizeof(struct ip6_hdr),
- __func__, __LINE__));
+ __func__, __LINE__);
goto bad;
}
l = off - sizeof(struct ip6_hdr);
m_copydata(m, 0, sizeof(nip6), (caddr_t)&nip6);
- m_adj(m, l);
+ m_adj(m, (int)l);
l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
if (m->m_len < l) {
- if ((m_ip6hdr = m_pulldown(m, 0, l, NULL)) == NULL) {
+ if ((m_ip6hdr = m_pulldown(m, 0, (int)l, NULL)) == NULL) {
return;
}
}
size_t l;
l = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr);
if (m->m_len < l) {
- if ((m_ip6hdr = m_pulldown(m, 0, l, NULL)) == NULL) {
+ if ((m_ip6hdr = m_pulldown(m, 0, (int)l, NULL)) == NULL) {
return;
}
}
* to search in the ifaddr list.
*/
lck_rw_lock_shared(&in6_ifaddr_rwlock);
- for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
+ TAILQ_FOREACH(ia, IN6ADDR_HASH(&t), ia6_hash) {
IFA_LOCK(&ia->ia_ifa);
if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) &&
(ia->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY | IN6_IFF_CLAT46)) == 0) {
&src_storage, ip6oa.ip6oa_boundif, &e);
ROUTE_RELEASE(&ro);
if (src == NULL) {
- nd6log((LOG_DEBUG,
+ nd6log(debug,
"icmp6_reflect: source can't be determined: "
"dst=%s, error=%d\n",
- ip6_sprintf(&sa6_src.sin6_addr), e));
+ ip6_sprintf(&sa6_src.sin6_addr), e);
goto bad;
}
}
ip6->ip6_hlim = ndi->chlim;
lck_mtx_unlock(&ndi->lock);
} else {
- ip6->ip6_hlim = ip6_defhlim;
+ ip6->ip6_hlim = (uint8_t)ip6_defhlim;
}
/* Use the same traffic class as in the request to match IPv4 */
icmp6->icmp6_cksum = 0;
}
void
-icmp6_redirect_input(struct mbuf *m, int off)
+icmp6_redirect_input(struct mbuf *m, int off, int icmp6len)
{
- struct ifnet *ifp = m->m_pkthdr.rcvif;
- struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
- struct nd_redirect *nd_rd;
- int icmp6len = ntohs(ip6->ip6_plen);
+ struct ifnet *ifp = NULL;
+ struct ip6_hdr *ip6 = NULL;
+ struct nd_redirect *nd_rd = NULL;
char *lladdr = NULL;
int lladdrlen = 0;
u_char *redirhdr = NULL;
int redirhdrlen = 0;
struct rtentry *rt = NULL;
- int is_router;
- int is_onlink;
- struct in6_addr src6 = ip6->ip6_src;
- struct in6_addr redtgt6;
- struct in6_addr reddst6;
- union nd_opts ndopts;
-
- if (!m || !ifp) {
+ int is_router = 0;
+ int is_onlink = 0;
+ struct in6_addr src6 = {};
+ struct in6_addr redtgt6 = {};
+ struct in6_addr reddst6 = {};
+ union nd_opts ndopts = {};
+
+ if (m == NULL) {
return;
}
+ ifp = m->m_pkthdr.rcvif;
+ if (ifp == NULL) {
+ goto freeit;
+ }
+
/*
* If we are an advertising router on this interface,
* don't update route by icmp6 redirect.
*/
- if (ifp->if_eflags & IFEF_IPV6_ROUTER) {
+ if (ifp->if_ipv6_router_mode == IPV6_ROUTER_MODE_EXCLUSIVE) {
goto freeit;
}
if (!icmp6_rediraccept) {
goto freeit;
}
+ ip6 = mtod(m, struct ip6_hdr *);
+ src6 = ip6->ip6_src;
#ifndef PULLDOWN_TEST
IP6_EXTHDR_CHECK(m, off, icmp6len, return );
- nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
+ nd_rd = (struct nd_redirect *)(mtod(m, caddr_t) + off);
#else
IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
if (nd_rd == NULL) {
icmp6stat.icp6s_tooshort++;
- return;
+ goto freeit;
}
#endif
+ ip6 = mtod(m, struct ip6_hdr *);
+
redtgt6 = nd_rd->nd_rd_target;
reddst6 = nd_rd->nd_rd_dst;
/* validation */
if (!IN6_IS_ADDR_LINKLOCAL(&src6)) {
- nd6log((LOG_ERR,
+ nd6log(error,
"ICMP6 redirect sent from %s rejected; "
- "must be from linklocal\n", ip6_sprintf(&src6)));
+ "must be from linklocal\n", ip6_sprintf(&src6));
goto bad;
}
- if (ip6->ip6_hlim != 255) {
- nd6log((LOG_ERR,
+ if (ip6->ip6_hlim != IPV6_MAXHLIM) {
+ nd6log(error,
"ICMP6 redirect sent from %s rejected; "
"hlim=%d (must be 255)\n",
- ip6_sprintf(&src6), ip6->ip6_hlim));
+ ip6_sprintf(&src6), ip6->ip6_hlim);
goto bad;
}
{
RT_LOCK(rt);
if (rt->rt_gateway == NULL ||
rt->rt_gateway->sa_family != AF_INET6) {
- nd6log((LOG_ERR,
+ nd6log(error,
"ICMP6 redirect rejected; no route "
"with inet6 gateway found for redirect dst: %s\n",
- icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
+ icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
RT_UNLOCK(rt);
rtfree(rt);
goto bad;
gw6 = &(((struct sockaddr_in6 *)(void *)
rt->rt_gateway)->sin6_addr);
if (bcmp(&src6, gw6, sizeof(struct in6_addr)) != 0) {
- nd6log((LOG_ERR,
+ nd6log(error,
"ICMP6 redirect rejected; "
"not equal to gw-for-src=%s (must be same): "
"%s\n",
ip6_sprintf(gw6),
- icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
+ icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
RT_UNLOCK(rt);
rtfree(rt);
goto bad;
}
} else {
- nd6log((LOG_ERR,
+ nd6log(error,
"ICMP6 redirect rejected; "
"no route found for redirect dst: %s\n",
- icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
+ icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
goto bad;
}
RT_UNLOCK(rt);
rt = NULL;
}
if (IN6_IS_ADDR_MULTICAST(&reddst6)) {
- nd6log((LOG_ERR,
+ nd6log(error,
"ICMP6 redirect rejected; "
"redirect dst must be unicast: %s\n",
- icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
+ icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
goto bad;
}
is_onlink = 1; /* on-link destination case */
}
if (!is_router && !is_onlink) {
- nd6log((LOG_ERR,
+ nd6log(error,
"ICMP6 redirect rejected; "
"neither router case nor onlink case: %s\n",
- icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
+ icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
goto bad;
}
/* validation passed */
icmp6len -= sizeof(*nd_rd);
nd6_option_init(nd_rd + 1, icmp6len, &ndopts);
if (nd6_options(&ndopts) < 0) {
- nd6log((LOG_INFO, "icmp6_redirect_input: "
+ nd6log(info, "icmp6_redirect_input: "
"invalid ND option, rejected: %s\n",
- icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
+ icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
/* nd6_options have incremented stats */
goto freeit;
}
}
if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
- nd6log((LOG_INFO,
+ nd6log(info,
"icmp6_redirect_input: lladdrlen mismatch for %s "
"(if %d, icmp6 packet %d): %s\n",
ip6_sprintf(&redtgt6), ifp->if_addrlen, lladdrlen - 2,
- icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
+ icmp6_redirect_diag(&src6, &reddst6, &redtgt6));
goto bad;
}
* If we are not a router to begin with, or not an advertising
* router on this interface, don't send icmp6 redirect.
*/
- if (!ip6_forwarding || !(ifp->if_eflags & IFEF_IPV6_ROUTER)) {
+ if (!ip6_forwarding || ifp->if_ipv6_router_mode != IPV6_ROUTER_MODE_EXCLUSIVE) {
goto fail;
}
m->m_pkthdr.rcvif = NULL;
m->m_len = 0;
maxlen = M_TRAILINGSPACE(m);
- maxlen = min(IPV6_MMTU, maxlen);
+ maxlen = MIN(IPV6_MMTU, maxlen);
/* just for safety */
if (maxlen < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) +
((sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7)) {
ip6->ip6_vfc |= IPV6_VERSION;
/* ip6->ip6_plen will be set later */
ip6->ip6_nxt = IPPROTO_ICMPV6;
- ip6->ip6_hlim = 255;
+ ip6->ip6_hlim = IPV6_MAXHLIM;
/* ip6->ip6_src must be linklocal addr for my outgoing if. */
bcopy(&ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
rt_router->rt_gateway) && sdl->sdl_alen) {
nd_opt = (struct nd_opt_hdr *)p;
nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
- nd_opt->nd_opt_len = len >> 3;
+ nd_opt->nd_opt_len = (uint8_t)(len >> 3);
lladdr = (char *)(nd_opt + 1);
bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen);
p += len;
nolladdropt:;
- m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
+ m->m_pkthdr.len = m->m_len = (int32_t)(p - (u_char *)ip6);
/* just to be safe */
#ifdef M_DECRYPTED /*not openbsd*/
* compute the maximum size for icmp6 redirect header option.
* XXX room for auth header?
*/
- len = maxlen - (p - (u_char *)ip6);
+ len = (int)(maxlen - (p - (u_char *)ip6));
len &= ~7;
/* This is just for simplicity. */
nd_opt_rh = (struct nd_opt_rd_hdr *)p;
bzero(nd_opt_rh, sizeof(*nd_opt_rh));
nd_opt_rh->nd_opt_rh_type = ND_OPT_REDIRECTED_HEADER;
- nd_opt_rh->nd_opt_rh_len = len >> 3;
+ nd_opt_rh->nd_opt_rh_len = (uint8_t)(len >> 3);
p += sizeof(*nd_opt_rh);
- m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
+ m->m_pkthdr.len = m->m_len = (int32_t)(p - (u_char *)ip6);
/* connect m0 to m */
m->m_next = m0;
in6_clearscope(&nd_rd->nd_rd_target);
in6_clearscope(&nd_rd->nd_rd_dst);
- ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
+ ip6->ip6_plen = htons((uint16_t)(m->m_pkthdr.len - sizeof(struct ip6_hdr)));
nd_rd->nd_rd_cksum = 0;
nd_rd->nd_rd_cksum
/* send the packet to outside... */
ip6oa.ip6oa_boundif = ifp->if_index;
ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF;
+ ip6oa.ip6oa_flags |= IP6OAF_DONT_FRAG;
ip6_output(m, NULL, NULL, IPV6_OUTARGS, NULL, &outif, &ip6oa);
if (outif) {
icmp6_ctloutput(struct socket *so, struct sockopt *sopt)
{
int error = 0;
- int optlen;
+ size_t optlen;
struct inpcb *inp = sotoinpcb(so);
int level, op, optname;
break;
}
error = sooptcopyout(sopt, inp->in6p_icmp6filt,
- min(sizeof(struct icmp6_filter), optlen));
+ MIN(sizeof(struct icmp6_filter), optlen));
break;
}
#pragma unused(flags, p)
int error = 0;
struct inpcb *inp = sotoinpcb(so);
- struct sockaddr_in6 tmp;
- struct sockaddr_in6 *dst = (struct sockaddr_in6 *)(void *)nam;
struct icmp6_hdr *icmp6;
if (inp == NULL
return rip6_output(m, so, SIN6(nam), control, 0);
}
- /* always copy sockaddr to avoid overwrites */
- if (so->so_state & SS_ISCONNECTED) {
- if (nam != NULL) {
- error = EISCONN;
- goto bad;
- }
- /* XXX */
- bzero(&tmp, sizeof(tmp));
- tmp.sin6_family = AF_INET6;
- tmp.sin6_len = sizeof(struct sockaddr_in6);
- bcopy(&inp->in6p_faddr, &tmp.sin6_addr,
- sizeof(struct in6_addr));
- dst = &tmp;
- } else {
- if (nam == NULL) {
- error = ENOTCONN;
- goto bad;
- }
- tmp = *(struct sockaddr_in6 *)(void *)nam;
- dst = &tmp;
- }
-
/*
* For an ICMPv6 packet, we should know its type and code
*/
}
}
-#if ENABLE_DEFAULT_SCOPE
- if (dst->sin6_scope_id == 0) { /* not change if specified */
- dst->sin6_scope_id = scope6_addr2default(&dst->sin6_addr);
- }
-#endif
-
- return rip6_output(m, so, dst, control, 0);
+ return rip6_output(m, so, SIN6(nam), control, 0);
bad:
VERIFY(error != 0);
}
} else if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count,
icmp6errppslim)) {
- /* The packet is subject to rate limit */
- ret++;
+ /*
+ * We add some randomness here to still generate ICMPv6 error
+ * post icmp6errppslim limit with a probability that goes down
+ * with increased value of icmp6errpps_count.
+ */
+ if (icmp6errpps_count > 0 && icmp6errppslim > 0 &&
+ icmp6errpps_count > icmp6errppslim &&
+ (random() % (icmp6errpps_count - icmp6errppslim)) != 0) {
+ /* The packet is subject to rate limit */
+ ret++;
+ }
}
return ret;