]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/kpi_protocol.c
xnu-4903.221.2.tar.gz
[apple/xnu.git] / bsd / net / kpi_protocol.c
index 6c3043c94575684f94fdab8b2ed98293a43c38d0..6265a4b4bb53c58629a69fbee8d5b5582ea70b42 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
@@ -44,167 +44,141 @@ typedef int (*attach_t)(struct ifnet *ifp, uint32_t protocol_family);
 typedef int (*detach_t)(struct ifnet *ifp, uint32_t protocol_family);
 
 struct proto_input_entry {
-       struct proto_input_entry                *next;
-       int                                                             detach;
-       struct domain                                   *domain;
-       int                                                             hash;
-       int                                                             chain;
-       
-       protocol_family_t                               protocol;
-       proto_input_handler                             input;
+       struct proto_input_entry        *next;
+       int                             detach;
+       struct domain                   *domain;
+       int                             hash;
+       int                             chain;
+
+       protocol_family_t               protocol;
+       proto_input_handler             input;
        proto_input_detached_handler    detached;
-       
-       mbuf_t                                                  inject_first;
-       mbuf_t                                                  inject_last;
-       
-       struct proto_input_entry                *input_next;
-       mbuf_t                                                  input_first;
-       mbuf_t                                                  input_last;
+
+       mbuf_t                          inject_first;
+       mbuf_t                          inject_last;
+
+       struct proto_input_entry        *input_next;
+       mbuf_t                          input_first;
+       mbuf_t                          input_last;
 };
 
 
 struct proto_family_str {
        TAILQ_ENTRY(proto_family_str)   proto_fam_next;
-       protocol_family_t                               proto_family;
-       ifnet_family_t                                  if_family;
-       proto_plumb_handler                             attach_proto;
-       proto_unplumb_handler                   detach_proto;
+       protocol_family_t               proto_family;
+       ifnet_family_t                  if_family;
+       proto_plumb_handler             attach_proto;
+       proto_unplumb_handler           detach_proto;
 };
 
-#define PROTO_HASH_SLOTS       5
-
-static struct proto_input_entry                        *proto_hash[PROTO_HASH_SLOTS];
-static int                                                             proto_total_waiting = 0;
-static struct proto_input_entry                *proto_input_add_list = NULL;
-static lck_mtx_t                                               *proto_family_mutex = 0;
-static TAILQ_HEAD(, proto_family_str)  proto_family_head =
-                       TAILQ_HEAD_INITIALIZER(proto_family_head);
-
-extern lck_mtx_t       *domain_proto_mtx;
-extern struct dlil_threading_info *dlil_lo_thread_ptr;
-
-static int
-proto_hash_value(
-       protocol_family_t protocol)
-{
-       switch(protocol) {
-               case PF_INET:
-                       return 0;
-               case PF_INET6:
-                       return 1;
-               case PF_APPLETALK:
-                       return 2;
-               case PF_VLAN:
-                       return 3;
-       }
-       return 4;
-}
+static struct proto_input_entry *proto_hash[PROTO_HASH_SLOTS];
+static int proto_total_waiting = 0;
+static struct proto_input_entry        *proto_input_add_list = NULL;
+decl_lck_mtx_data(static, proto_family_mutex_data);
+static lck_mtx_t *proto_family_mutex = &proto_family_mutex_data;
+static TAILQ_HEAD(, proto_family_str) proto_family_head =
+    TAILQ_HEAD_INITIALIZER(proto_family_head);
 
 __private_extern__ void
 proto_kpi_init(void)
 {
-       lck_grp_attr_t  *grp_attrib = 0;
-       lck_attr_t              *lck_attrib = 0;
-       lck_grp_t               *lck_group = 0;
-       
+       lck_grp_attr_t  *grp_attrib = NULL;
+       lck_attr_t      *lck_attrib = NULL;
+       lck_grp_t       *lck_group = NULL;
+
        /* Allocate a mtx lock */
        grp_attrib = lck_grp_attr_alloc_init();
        lck_group = lck_grp_alloc_init("protocol kpi", grp_attrib);
        lck_grp_attr_free(grp_attrib);
        lck_attrib = lck_attr_alloc_init();
-       proto_family_mutex = lck_mtx_alloc_init(lck_group, lck_attrib);
+       lck_mtx_init(proto_family_mutex, lck_group, lck_attrib);
        lck_grp_free(lck_group);
        lck_attr_free(lck_attrib);
-       
-       bzero(proto_hash, sizeof(proto_hash));
+
+       bzero(proto_hash, sizeof (proto_hash));
 }
 
 __private_extern__ errno_t
-proto_register_input(
-       protocol_family_t protocol,
-       proto_input_handler input,
-       proto_input_detached_handler detached,
-       int     chains)
+proto_register_input(protocol_family_t protocol, proto_input_handler input,
+    proto_input_detached_handler detached, int chains)
 {
-       
        struct proto_input_entry *entry;
-       struct dlil_threading_info *thread = dlil_lo_thread_ptr;
-       
-       entry = _MALLOC(sizeof(*entry), M_IFADDR, M_WAITOK);
-       
+       struct dlil_threading_info *inp = dlil_main_input_thread;
+       struct domain *dp;
+       domain_guard_t guard;
+
+       entry = _MALLOC(sizeof (*entry), M_IFADDR, M_WAITOK | M_ZERO);
        if (entry == NULL)
-               return ENOMEM;
-       
-       bzero(entry, sizeof(*entry));
+               return (ENOMEM);
+
        entry->protocol = protocol;
        entry->input = input;
        entry->detached = detached;
        entry->hash = proto_hash_value(protocol);
        entry->chain = chains;
-       
-       {
-               struct domain *dp = domains;
-
-               lck_mtx_assert(domain_proto_mtx, LCK_MTX_ASSERT_NOTOWNED);
-               lck_mtx_lock(domain_proto_mtx);
-               while (dp && (protocol_family_t)dp->dom_family != protocol)
-                       dp = dp->dom_next;
-               entry->domain = dp;
-               lck_mtx_unlock(domain_proto_mtx);       
+
+       guard = domain_guard_deploy();
+       TAILQ_FOREACH(dp, &domains, dom_entry) {
+               if (dp->dom_family == (int)protocol)
+                       break;
        }
+       domain_guard_release(guard);
+       if (dp == NULL)
+               return (EINVAL);
+
+       entry->domain = dp;
 
-       
-       lck_mtx_lock(&thread->input_lck);
+       lck_mtx_lock(&inp->input_lck);
        entry->next = proto_input_add_list;
        proto_input_add_list = entry;
-       
-       thread->input_waiting |= DLIL_PROTO_REGISTER;
-       if ((thread->input_waiting & DLIL_INPUT_RUNNING) == 0)
-               wakeup((caddr_t)&thread->input_waiting);
-       lck_mtx_unlock(&thread->input_lck);
-       
-       return 0;
-}
 
+       inp->input_waiting |= DLIL_PROTO_REGISTER;
+       if ((inp->input_waiting & DLIL_INPUT_RUNNING) == 0)
+               wakeup((caddr_t)&inp->input_waiting);
+       lck_mtx_unlock(&inp->input_lck);
+
+       return (0);
+}
 
 __private_extern__ void
-proto_unregister_input(
-       protocol_family_t       protocol)
+proto_unregister_input(protocol_family_t protocol)
 {
        struct proto_input_entry *entry = NULL;
-       
-       for (entry = proto_hash[proto_hash_value(protocol)]; entry; entry = entry->next)
+
+       for (entry = proto_hash[proto_hash_value(protocol)]; entry != NULL;
+           entry = entry->next) {
                if (entry->protocol == protocol)
                        break;
-       
-       if (entry)
+       }
+
+       if (entry != NULL)
                entry->detach = 1;
 }
 
-
 static void
-proto_delayed_attach(
-       struct proto_input_entry *entry)
+proto_delayed_attach(struct proto_input_entry *entry)
 {
        struct proto_input_entry *next_entry;
-       for (next_entry = entry->next; entry; entry = next_entry) {
+
+       for (next_entry = entry->next; entry != NULL; entry = next_entry) {
                struct proto_input_entry *exist;
                int hash_slot;
-               
+
                hash_slot = proto_hash_value(entry->protocol);
                next_entry = entry->next;
-               
-               for (exist = proto_hash[hash_slot]; exist; exist = exist->next)
+
+               for (exist = proto_hash[hash_slot]; exist != NULL;
+                   exist = exist->next) {
                        if (exist->protocol == entry->protocol)
                                break;
-               
+               }
+
                /* If the entry already exists, call detached and dispose */
-               if (exist) {
+               if (exist != NULL) {
                        if (entry->detached)
                                entry->detached(entry->protocol);
                        FREE(entry, M_IFADDR);
-               }
-               else {
+               } else {
                        entry->next = proto_hash[hash_slot];
                        proto_hash[hash_slot] = entry;
                }
@@ -214,31 +188,32 @@ proto_delayed_attach(
 __private_extern__ void
 proto_input_run(void)
 {
-       struct proto_input_entry        *entry;
-       struct dlil_threading_info *thread = dlil_lo_thread_ptr;
+       struct proto_input_entry *entry;
+       struct dlil_threading_info *inp = dlil_main_input_thread;
        mbuf_t packet_list;
        int i, locked = 0;
 
-       lck_mtx_assert(&thread->input_lck,  LCK_MTX_ASSERT_NOTOWNED);
+       LCK_MTX_ASSERT(&inp->input_lck, LCK_MTX_ASSERT_NOTOWNED);
 
-       if ((thread->input_waiting & DLIL_PROTO_REGISTER) != 0) {
-               lck_mtx_lock_spin(&thread->input_lck);
+       if (inp->input_waiting & DLIL_PROTO_REGISTER) {
+               lck_mtx_lock_spin(&inp->input_lck);
                entry = proto_input_add_list;
                proto_input_add_list = NULL;
-               thread->input_waiting &= ~DLIL_PROTO_REGISTER;
-               lck_mtx_unlock(&thread->input_lck);
+               inp->input_waiting &= ~DLIL_PROTO_REGISTER;
+               lck_mtx_unlock(&inp->input_lck);
                proto_delayed_attach(entry);
        }
+
        /*
-         Move everything from the lock protected list to the thread
-         specific list.
+        * Move everything from the lock protected list to the thread
+        * specific list.
         */
        for (i = 0; proto_total_waiting != 0 && i < PROTO_HASH_SLOTS; i++) {
-               for (entry = proto_hash[i]; entry && proto_total_waiting;
-                        entry = entry->next) {
-                       if (entry->inject_first) {
-                               lck_mtx_lock_spin(&thread->input_lck);
-                               thread->input_waiting &= ~DLIL_PROTO_WAITING;
+               for (entry = proto_hash[i];
+                   entry != NULL && proto_total_waiting; entry = entry->next) {
+                       if (entry->inject_first != NULL) {
+                               lck_mtx_lock_spin(&inp->input_lck);
+                               inp->input_waiting &= ~DLIL_PROTO_WAITING;
 
                                packet_list = entry->inject_first;
 
@@ -246,160 +221,159 @@ proto_input_run(void)
                                entry->inject_last = NULL;
                                proto_total_waiting--;
 
-                               lck_mtx_unlock(&thread->input_lck);
+                               lck_mtx_unlock(&inp->input_lck);
 
-                               if (entry->domain && (entry->domain->dom_flags & DOM_REENTRANT) == 0) {
+                               if (entry->domain != NULL && !(entry->domain->
+                                   dom_flags & DOM_REENTRANT)) {
                                        lck_mtx_lock(entry->domain->dom_mtx);
                                        locked = 1;
                                }
-               
+
                                if (entry->chain) {
-                                       entry->input(entry->protocol, packet_list);
-                               }
-                               else {
+                                       entry->input(entry->protocol,
+                                           packet_list);
+                               else {
                                        mbuf_t  packet;
-                               
-                                       for (packet = packet_list; packet; packet = packet_list) {
-                                               packet_list = mbuf_nextpkt(packet);
+
+                                       for (packet = packet_list;
+                                           packet != NULL;
+                                           packet = packet_list) {
+                                               packet_list =
+                                                   mbuf_nextpkt(packet);
                                                mbuf_setnextpkt(packet, NULL);
-                                               entry->input(entry->protocol, packet);
+                                               entry->input(entry->protocol,
+                                                   packet);
                                        }
                                }
                                if (locked) {
                                        locked = 0;
                                        lck_mtx_unlock(entry->domain->dom_mtx);
-                               }       
+                               }
+                       }
                }
        }
-       }
-
 }
 
 errno_t
-proto_input(
-       protocol_family_t       protocol,
-       mbuf_t                          packet_list)
+proto_input(protocol_family_t protocol, mbuf_t packet_list)
 {
-       struct proto_input_entry        *entry;
-       errno_t                         locked =0, result = 0;
+       struct proto_input_entry *entry;
+       errno_t locked = 0, result = 0;
 
-       for (entry = proto_hash[proto_hash_value(protocol)]; entry;
-                entry = entry->next) {
+       for (entry = proto_hash[proto_hash_value(protocol)]; entry != NULL;
+           entry = entry->next) {
                if (entry->protocol == protocol)
                        break;
        }
 
-       if (entry->domain && (entry->domain->dom_flags & DOM_REENTRANT) == 0) {
+       if (entry == NULL)
+               return (-1);
+
+       if (entry->domain && !(entry->domain->dom_flags & DOM_REENTRANT)) {
                lck_mtx_lock(entry->domain->dom_mtx);
                locked = 1;
        }
-       
+
        if (entry->chain) {
                entry->input(entry->protocol, packet_list);
-       }
-       else {
+       } else {
                mbuf_t  packet;
-               
-               for (packet = packet_list; packet; packet = packet_list) {
+
+               for (packet = packet_list; packet != NULL;
+                   packet = packet_list) {
                        packet_list = mbuf_nextpkt(packet);
                        mbuf_setnextpkt(packet, NULL);
                        entry->input(entry->protocol, packet);
                }
        }
-       
+
        if (locked) {
                lck_mtx_unlock(entry->domain->dom_mtx);
-       }       
-       return result;
+       }
+       return (result);
 }
 
 errno_t
-proto_inject(
-       protocol_family_t       protocol,
-       mbuf_t                          packet_list)
+proto_inject(protocol_family_t protocol, mbuf_t packet_list)
 {
-       struct proto_input_entry        *entry;
-       mbuf_t                          last_packet;
-       int                             hash_slot = proto_hash_value(protocol);
-       struct dlil_threading_info      *thread = dlil_lo_thread_ptr;
-       
-       for (last_packet = packet_list; mbuf_nextpkt(last_packet);
-                last_packet = mbuf_nextpkt(last_packet))
+       struct proto_input_entry *entry;
+       mbuf_t last_packet;
+       int hash_slot = proto_hash_value(protocol);
+       struct dlil_threading_info *inp = dlil_main_input_thread;
+
+       for (last_packet = packet_list; mbuf_nextpkt(last_packet) != NULL;
+           last_packet = mbuf_nextpkt(last_packet))
                /* find the last packet */;
-       
-       for (entry = proto_hash[hash_slot]; entry; entry = entry->next) {
+
+       for (entry = proto_hash[hash_slot]; entry != NULL;
+           entry = entry->next) {
                if (entry->protocol == protocol)
                        break;
        }
-       
-       if (entry) {
-               lck_mtx_lock(&thread->input_lck);
+
+       if (entry != NULL) {
+               lck_mtx_lock(&inp->input_lck);
                if (entry->inject_first == NULL) {
                        proto_total_waiting++;
-                       thread->input_waiting |= DLIL_PROTO_WAITING;
+                       inp->input_waiting |= DLIL_PROTO_WAITING;
                        entry->inject_first = packet_list;
-               }
-               else {
+               } else {
                        mbuf_setnextpkt(entry->inject_last, packet_list);
                }
                entry->inject_last = last_packet;
-               if ((thread->input_waiting & DLIL_INPUT_RUNNING) == 0) {
-                       wakeup((caddr_t)&thread->input_waiting);
+               if ((inp->input_waiting & DLIL_INPUT_RUNNING) == 0) {
+                       wakeup((caddr_t)&inp->input_waiting);
                }
-               lck_mtx_unlock(&thread->input_lck);
-       }
-       else
-       {
-               return ENOENT;
+               lck_mtx_unlock(&inp->input_lck);
+       } else {
+               return (ENOENT);
        }
 
-       return 0;
+       return (0);
 }
 
-static struct proto_family_str*
-proto_plumber_find(
-       protocol_family_t       proto_family,
-       ifnet_family_t          if_family)
+static struct proto_family_str *
+proto_plumber_find(protocol_family_t proto_family, ifnet_family_t if_family)
 {
        struct proto_family_str  *mod = NULL;
 
        TAILQ_FOREACH(mod, &proto_family_head, proto_fam_next) {
-               if ((mod->proto_family == (proto_family & 0xffff)) 
-                       && (mod->if_family == (if_family & 0xffff))) 
+               if ((mod->proto_family == (proto_family & 0xffff)) &&
+                   (mod->if_family == (if_family & 0xffff)))
                        break;
-               }
+       }
 
-       return mod;
+       return (mod);
 }
 
 errno_t
-proto_register_plumber(
-       protocol_family_t               protocol_family,
-       ifnet_family_t                  interface_family, 
-       proto_plumb_handler             attach,
-       proto_unplumb_handler   detach)
+proto_register_plumber(protocol_family_t protocol_family,
+    ifnet_family_t interface_family, proto_plumb_handler attach,
+    proto_unplumb_handler detach)
 {
        struct proto_family_str *proto_family;
 
-       if (attach == NULL) return EINVAL;
+       if (attach == NULL)
+               return (EINVAL);
 
        lck_mtx_lock(proto_family_mutex);
-       
+
        TAILQ_FOREACH(proto_family, &proto_family_head, proto_fam_next) {
                if (proto_family->proto_family == protocol_family &&
-                       proto_family->if_family == interface_family) {
+                   proto_family->if_family == interface_family) {
                        lck_mtx_unlock(proto_family_mutex);
-                       return EEXIST;
+                       return (EEXIST);
                }
        }
 
-       proto_family = (struct proto_family_str *) _MALLOC(sizeof(struct proto_family_str), M_IFADDR, M_WAITOK);
+       proto_family = (struct proto_family_str *)
+           _MALLOC(sizeof (struct proto_family_str), M_IFADDR,
+           M_WAITOK | M_ZERO);
        if (!proto_family) {
                lck_mtx_unlock(proto_family_mutex);
-               return ENOMEM;
+               return (ENOMEM);
        }
 
-       bzero(proto_family, sizeof(struct proto_family_str));
        proto_family->proto_family      = protocol_family;
        proto_family->if_family         = interface_family & 0xffff;
        proto_family->attach_proto      = attach;
@@ -407,57 +381,51 @@ proto_register_plumber(
 
        TAILQ_INSERT_TAIL(&proto_family_head, proto_family, proto_fam_next);
        lck_mtx_unlock(proto_family_mutex);
-       return 0;
+       return (0);
 }
 
 void
-proto_unregister_plumber(
-       protocol_family_t       protocol_family,
-       ifnet_family_t          interface_family)
+proto_unregister_plumber(protocol_family_t protocol_family,
+    ifnet_family_t interface_family)
 {
        struct proto_family_str  *proto_family;
 
        lck_mtx_lock(proto_family_mutex);
 
        proto_family = proto_plumber_find(protocol_family, interface_family);
-       if (proto_family == 0) {
+       if (proto_family == NULL) {
                lck_mtx_unlock(proto_family_mutex);
                return;
        }
 
        TAILQ_REMOVE(&proto_family_head, proto_family, proto_fam_next);
        FREE(proto_family, M_IFADDR);
-       
+
        lck_mtx_unlock(proto_family_mutex);
-       return;
 }
 
 __private_extern__ errno_t
-proto_plumb(
-       protocol_family_t       protocol_family,
-       ifnet_t                         ifp)
+proto_plumb(protocol_family_t protocol_family, ifnet_t ifp)
 {
        struct proto_family_str  *proto_family;
        int ret = 0;
 
        lck_mtx_lock(proto_family_mutex);
        proto_family = proto_plumber_find(protocol_family, ifp->if_family);
-       if (proto_family == 0) {
+       if (proto_family == NULL) {
                lck_mtx_unlock(proto_family_mutex);
-               return ENXIO;
+               return (ENXIO);
        }
 
        ret = proto_family->attach_proto(ifp, protocol_family);
 
        lck_mtx_unlock(proto_family_mutex);
-       return ret;
+       return (ret);
 }
 
 
 __private_extern__ errno_t
-proto_unplumb(
-       protocol_family_t       protocol_family,
-       ifnet_t                         ifp)
+proto_unplumb(protocol_family_t protocol_family, ifnet_t ifp)
 {
        struct proto_family_str  *proto_family;
        int ret = 0;
@@ -465,11 +433,11 @@ proto_unplumb(
        lck_mtx_lock(proto_family_mutex);
 
        proto_family = proto_plumber_find(protocol_family, ifp->if_family);
-       if (proto_family && proto_family->detach_proto)
+       if (proto_family != NULL && proto_family->detach_proto)
                proto_family->detach_proto(ifp, protocol_family);
        else
                ret = ifnet_detach_protocol(ifp, protocol_family);
-    
+
        lck_mtx_unlock(proto_family_mutex);
-       return ret;
+       return (ret);
 }