]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet6/ip6_input.c
xnu-3789.21.4.tar.gz
[apple/xnu.git] / bsd / netinet6 / ip6_input.c
index 4cc199ca8bc0b53ee9ac2c6225b599d2199a3ec7..ec32485cbcdac174962103a880b8877df38e2db0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
 #include <net/ntstat.h>
 #include <net/init.h>
 #include <net/net_osdep.h>
+#include <net/net_perf.h>
 
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 extern int ipsec_bypass;
 #endif /* IPSEC */
 
-#if IPFW2
-#include <netinet6/ip6_fw.h>
-#endif /* IPFW2 */
-
 #if DUMMYNET
 #include <netinet/ip_fw.h>
 #include <netinet/ip_dummynet.h>
@@ -177,13 +174,6 @@ struct in6_ifaddr *in6_ifaddrs = NULL;
 #define        ICMP6_IFSTAT_REQUIRE_ALIGNED_64(f)      \
        _CASSERT(!(offsetof(struct icmp6_ifstat, f) % sizeof (uint64_t)))
 
-#if IPFW2
-/* firewall hooks */
-ip6_fw_chk_t *ip6_fw_chk_ptr;
-ip6_fw_ctl_t *ip6_fw_ctl_ptr;
-int ip6_fw_enable = 1;
-#endif /* IPFW2 */
-
 struct ip6stat ip6stat;
 
 decl_lck_mtx_data(, proxy6_lock);
@@ -204,6 +194,9 @@ static lck_grp_attr_t       *ip6_mutex_grp_attr;
 extern int loopattach_done;
 extern void addrsel_policy_init(void);
 
+static int sysctl_reset_ip6_input_stats SYSCTL_HANDLER_ARGS;
+static int sysctl_ip6_input_measure_bins SYSCTL_HANDLER_ARGS;
+static int sysctl_ip6_input_getperf SYSCTL_HANDLER_ARGS;
 static void ip6_init_delayed(void);
 static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
 
@@ -213,16 +206,28 @@ extern void stfattach(void);
 
 SYSCTL_DECL(_net_inet6_ip6);
 
-int ip6_doscopedroute = 1;
-SYSCTL_INT(_net_inet6_ip6, OID_AUTO, scopedroute,
-       CTLFLAG_RD | CTLFLAG_LOCKED, &ip6_doscopedroute, 0,
-       "Enable IPv6 scoped routing");
-
 static uint32_t ip6_adj_clear_hwcksum = 0;
 SYSCTL_UINT(_net_inet6_ip6, OID_AUTO, adj_clear_hwcksum,
        CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_adj_clear_hwcksum, 0,
        "Invalidate hwcksum info when adjusting length");
 
+static int ip6_input_measure = 0;
+SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, input_perf,
+       CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
+       &ip6_input_measure, 0, sysctl_reset_ip6_input_stats, "I", "Do time measurement");
+
+static uint64_t ip6_input_measure_bins = 0;
+SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, input_perf_bins,
+       CTLTYPE_QUAD | CTLFLAG_RW | CTLFLAG_LOCKED, &ip6_input_measure_bins, 0,
+       sysctl_ip6_input_measure_bins, "I",
+       "bins for chaining performance data histogram");
+
+static net_perf_t net_perf;
+SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, input_perf_data,
+       CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
+       0, 0, sysctl_ip6_input_getperf, "S,net_perf",
+       "IP6 input performance data (struct net_perf, net/net_perf.h)");
+
 /*
  * On platforms which require strict alignment (currently for anything but
  * i386 or x86_64), check if the IP header pointer is 32-bit aligned; if not,
@@ -263,7 +268,18 @@ static void
 ip6_proto_input(protocol_family_t protocol, mbuf_t packet)
 {
 #pragma unused(protocol)
+#if INET
+       struct timeval start_tv;
+       if (ip6_input_measure)
+               net_perf_start_time(&net_perf, &start_tv);
+#endif /* INET */
        ip6_input(packet);
+#if INET
+       if (ip6_input_measure) {
+               net_perf_measure_time(&net_perf, &start_tv, 1);
+               net_perf_histogram(&net_perf, 1);
+       }
+#endif /* INET */
 }
 
 /*
@@ -289,9 +305,6 @@ ip6_init(struct ip6protosw *pp, struct domain *dp)
                return;
        ip6_initialized = 1;
 
-       PE_parse_boot_argn("net.inet6.ip6.scopedroute", &ip6_doscopedroute,
-           sizeof (ip6_doscopedroute));
-
        pr = pffindproto_locked(PF_INET6, IPPROTO_RAW, SOCK_RAW);
        if (pr == NULL) {
                panic("%s: Unable to find [PF_INET6,IPPROTO_RAW,SOCK_RAW]\n",
@@ -450,7 +463,7 @@ ip6_input(struct mbuf *m)
        int nxt = 0, ours = 0;
        struct ifnet *inifp, *deliverifp = NULL;
        ipfilter_t inject_ipfref = NULL;
-       int seen;
+       int seen = 1;
        struct in6_ifaddr *ia6 = NULL;
        struct sockaddr_in6 *dst6;
 #if DUMMYNET
@@ -605,6 +618,7 @@ ip6_input(struct mbuf *m)
        }
 
        ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
+
        /*
         * Check against address spoofing/corruption.
         */
@@ -669,22 +683,6 @@ ip6_input(struct mbuf *m)
                goto bad;
        }
 #endif
-#if IPFW2
-        /*
-         * Check with the firewall...
-         */
-        if (ip6_fw_enable && ip6_fw_chk_ptr) {
-                u_short port = 0;
-                /* If ipfw says divert, we have to just drop packet */
-                /* use port as a dummy argument */
-                if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
-                        m_freem(m);
-                        m = NULL;
-                }
-                if (!m)
-                        goto done;
-        }
-#endif /* IPFW2 */
 
        /*
         * Naively assume we can attribute inbound data to the route we would
@@ -1142,7 +1140,7 @@ injectit:
                /*
                 * Call IP filter
                 */
-               if (!TAILQ_EMPTY(&ipv6_filters)) {
+               if (!TAILQ_EMPTY(&ipv6_filters) && !IFNET_IS_INTCOPROC(inifp)) {
                        ipf_ref();
                        TAILQ_FOREACH(filter, &ipv6_filters, ipf_link) {
                                if (seen == 0) {
@@ -1318,12 +1316,8 @@ ip6_hopopts_input(uint32_t *plenp, uint32_t *rtalertp, struct mbuf **mp,
  * opthead + hbhlen is located in continuous memory region.
  */
 int
-ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
-       struct mbuf *m;
-       u_int8_t *opthead;
-       int hbhlen;
-       u_int32_t *rtalertp;
-       u_int32_t *plenp;
+ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
+                   u_int32_t *rtalertp, u_int32_t *plenp)
 {
        struct ip6_hdr *ip6;
        int optlen = 0;
@@ -1697,7 +1691,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
                                }
                                break;
                        case IPPROTO_ROUTING:
-                               if (!in6p->inp_flags & IN6P_RTHDR)
+                               if (!(in6p->inp_flags & IN6P_RTHDR))
                                        break;
 
                                mp = sbcreatecontrol_mbuf((caddr_t)ip6e, elen,
@@ -1788,9 +1782,7 @@ ip6_notify_pmtu(struct inpcb *in6p, struct sockaddr_in6 *dst, u_int32_t *mtu)
  * we develop `neater' mechanism to process extension headers.
  */
 char *
-ip6_get_prevhdr(m, off)
-       struct mbuf *m;
-       int off;
+ip6_get_prevhdr(struct mbuf *m, int off)
 {
        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
 
@@ -1895,8 +1887,6 @@ ip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp)
        default:
                return (-1);
        }
-
-       return (-1);
 }
 
 /*
@@ -1994,3 +1984,57 @@ u_char   inet6ctlerrmap[PRC_NCMDS] = {
        0,              0,              0,              0,
        ENOPROTOOPT
 };
+
+static int
+sysctl_reset_ip6_input_stats SYSCTL_HANDLER_ARGS
+{
+#pragma unused(arg1, arg2)
+       int error, i;
+
+       i = ip6_input_measure;
+       error = sysctl_handle_int(oidp, &i, 0, req);
+       if (error || req->newptr == USER_ADDR_NULL)
+               goto done;
+       /* impose bounds */
+       if (i < 0 || i > 1) {
+               error = EINVAL;
+               goto done;
+       }
+       if (ip6_input_measure != i && i == 1) {
+               net_perf_initialize(&net_perf, ip6_input_measure_bins);
+       }
+       ip6_input_measure = i;
+done:
+       return (error);
+}
+
+static int
+sysctl_ip6_input_measure_bins SYSCTL_HANDLER_ARGS
+{
+#pragma unused(arg1, arg2)
+       int error;
+       uint64_t i;
+
+       i = ip6_input_measure_bins;
+       error = sysctl_handle_quad(oidp, &i, 0, req);
+       if (error || req->newptr == USER_ADDR_NULL)
+               goto done;
+       /* validate data */
+       if (!net_perf_validate_bins(i)) {
+               error = EINVAL;
+               goto done;
+       }
+       ip6_input_measure_bins = i;
+done:
+       return (error);
+}
+
+static int
+sysctl_ip6_input_getperf SYSCTL_HANDLER_ARGS
+{
+#pragma unused(oidp, arg1, arg2)
+       if (req->oldptr == USER_ADDR_NULL)
+               req->oldlen = (size_t)sizeof (struct ipstat);
+
+       return (SYSCTL_OUT(req, &net_perf, MIN(sizeof (net_perf), req->oldlen)));
+}