/*
- * Copyright (c) 2009-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2009-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
}
/* prepend new IP header */
- M_PREPEND(m, sizeof (struct ip6_hdr), M_DONTWAIT);
+ M_PREPEND(m, sizeof (struct ip6_hdr), M_DONTWAIT, 1);
if (m && mbuf_len(m) < sizeof (struct ip6_hdr))
m = m_pullup(m, sizeof (struct ip6_hdr));
if (m == NULL) {
m_freem(m);
return (ENETUNREACH);
}
- ip_ecn_ingress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED : ECN_NOCARE,
+ ip_ecn_ingress((ifp->if_flags & IFF_LINK1) ? ECN_NORMAL : ECN_NOCARE,
&otos, &itos);
ip6->ip6_flow &= ~htonl(0xff << 20);
ip6->ip6_flow |= htonl((u_int32_t)otos << 20);
struct ip6_hdr *ip6;
int af = 0;
u_int32_t otos;
+ int egress_success = 0;
ip6 = mtod(m, struct ip6_hdr *);
case IPPROTO_IPV4:
{
struct ip *ip;
- u_int8_t otos8;
+ u_int8_t otos8, old_tos;
+ int sum;
+
af = AF_INET;
otos8 = (ntohl(otos) >> 20) & 0xff;
if (mbuf_len(m) < sizeof (*ip)) {
return (IPPROTO_DONE);
}
ip = mtod(m, struct ip *);
- if (gifp->if_flags & IFF_LINK1)
- ip_ecn_egress(ECN_ALLOWED, &otos8, &ip->ip_tos);
- else
- ip_ecn_egress(ECN_NOCARE, &otos8, &ip->ip_tos);
+ if (gifp->if_flags & IFF_LINK1) {
+ old_tos = ip->ip_tos;
+ egress_success = ip_ecn_egress(ECN_NORMAL, &otos8, &ip->ip_tos);
+ if (old_tos != ip->ip_tos) {
+ sum = ~ntohs(ip->ip_sum) & 0xffff;
+ sum += (~old_tos & 0xffff) + ip->ip_tos;
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16); /* add carry */
+ ip->ip_sum = htons(~sum & 0xffff);
+ }
+ } else
+ egress_success = ip_ecn_egress(ECN_NOCARE, &otos8, &ip->ip_tos);
break;
}
#endif /* INET */
}
ip6 = mtod(m, struct ip6_hdr *);
if (gifp->if_flags & IFF_LINK1)
- ip6_ecn_egress(ECN_ALLOWED, &otos, &ip6->ip6_flow);
+ egress_success = ip6_ecn_egress(ECN_NORMAL, &otos, &ip6->ip6_flow);
else
- ip6_ecn_egress(ECN_NOCARE, &otos, &ip6->ip6_flow);
+ egress_success = ip6_ecn_egress(ECN_NOCARE, &otos, &ip6->ip6_flow);
break;
}
#endif
return (IPPROTO_DONE);
}
+ if (egress_success == 0) {
+ ip6stat.ip6s_nogif++;
+ m_freem(m);
+ return (IPPROTO_DONE);
+ }
+
/* Replace the rcvif by gifp for ifnet_input to route it correctly */
if (m->m_pkthdr.rcvif)
m->m_pkthdr.rcvif = gifp;