]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/in_gif.c
xnu-4570.51.1.tar.gz
[apple/xnu.git] / bsd / netinet / in_gif.c
index cc700ae37267c342e0a3dcc8e98ad6214353e2a5..86a2b9920fa0068d64c608457470aaaddce9ed6e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
 #include <netinet/ip6.h>
 #endif
 
-#if MROUTING
-#include <netinet/ip_mroute.h>
-#endif /* MROUTING */
-
 #include <net/if_gif.h>
 
 #include <net/net_osdep.h>
@@ -114,8 +110,13 @@ in_gif_output(
        struct ip iphdr;        /* capsule IP header, host byte ordered */
        int proto, error;
        u_int8_t tos;
-       struct ip_out_args ipoa =
-           { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0 };
+       struct ip_out_args ipoa;
+
+       bzero(&ipoa, sizeof(ipoa));
+       ipoa.ipoa_boundif = IFSCOPE_NONE;
+       ipoa.ipoa_flags = IPOAF_SELECT_SRCIF;
+       ipoa.ipoa_sotc = SO_TC_UNSPEC;
+       ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC;
 
        GIF_LOCK_ASSERT(sc);
 
@@ -181,12 +182,12 @@ in_gif_output(
        iphdr.ip_ttl = ip_gif_ttl;
        iphdr.ip_len = m->m_pkthdr.len + sizeof (struct ip);
        if (ifp->if_flags & IFF_LINK1)
-               ip_ecn_ingress(ECN_ALLOWED, &iphdr.ip_tos, &tos);
+               ip_ecn_ingress(ECN_NORMAL, &iphdr.ip_tos, &tos);
        else
                ip_ecn_ingress(ECN_NOCARE, &iphdr.ip_tos, &tos);
 
        /* prepend new IP header */
-       M_PREPEND(m, sizeof (struct ip), M_DONTWAIT);
+       M_PREPEND(m, sizeof (struct ip), M_DONTWAIT, 0);
        if (m && mbuf_len(m) < sizeof (struct ip))
                m = m_pullup(m, sizeof (struct ip));
        if (m == NULL) {
@@ -236,14 +237,14 @@ in_gif_output(
 }
 
 void
-in_gif_input(m, off)
-       struct mbuf *m;
-       int off;
+in_gif_input(struct mbuf *m, int off)
 {
        struct ifnet *gifp = NULL;
        struct ip *ip;
        int af, proto;
-       u_int8_t otos;
+       u_int8_t otos, old_tos;
+       int egress_success = 0;
+       int sum;
 
        ip = mtod(m, struct ip *);
        proto = ip->ip_p;
@@ -271,10 +272,18 @@ in_gif_input(m, off)
                                return;
                }
                ip = mtod(m, struct ip *);
-               if (gifp->if_flags & IFF_LINK1)
-                       ip_ecn_egress(ECN_ALLOWED, &otos, &ip->ip_tos);
-               else
-                       ip_ecn_egress(ECN_NOCARE, &otos, &ip->ip_tos);
+               if (gifp->if_flags & IFF_LINK1) {
+                       old_tos = ip->ip_tos;
+                       egress_success = ip_ecn_egress(ECN_NORMAL, &otos, &ip->ip_tos);
+                       if (old_tos != ip->ip_tos) {
+                           sum = ~ntohs(ip->ip_sum) & 0xffff;
+                           sum += (~otos & 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, &otos, &ip->ip_tos);
                break;
            }
 #endif
@@ -292,9 +301,9 @@ in_gif_input(m, off)
                ip6 = mtod(m, struct ip6_hdr *);
                itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
                if (gifp->if_flags & IFF_LINK1)
-                       ip_ecn_egress(ECN_ALLOWED, &otos, &itos);
+                       egress_success = ip_ecn_egress(ECN_NORMAL, &otos, &itos);
                else
-                       ip_ecn_egress(ECN_NOCARE, &otos, &itos);
+                       egress_success = ip_ecn_egress(ECN_NOCARE, &otos, &itos);
                ip6->ip6_flow &= ~htonl(0xff << 20);
                ip6->ip6_flow |= htonl((u_int32_t)itos << 20);
                break;
@@ -305,6 +314,13 @@ in_gif_input(m, off)
                m_freem(m);
                return;
        }
+
+       if (egress_success == 0) {
+               OSAddAtomic(1, &ipstat.ips_nogif);
+               m_freem(m);
+               return;
+       }
+
 #ifdef __APPLE__
        /* Replace the rcvif by gifp for dlil to route it correctly */
        if (m->m_pkthdr.rcvif)