]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/if_gif.c
xnu-1228.7.58.tar.gz
[apple/xnu.git] / bsd / net / if_gif.c
index 6ada7aa5e18b30bbcae9522b9434b4fbe1a180a7..1381fc6fd597376599f1e7fc79b44a0fde964583 100644 (file)
@@ -1,23 +1,29 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * 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
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * 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.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * 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_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*     $FreeBSD: src/sys/net/if_gif.c,v 1.4.2.6 2001/07/24 19:10:18 brooks Exp $       */
 /*     $KAME: if_gif.c,v 1.47 2001/05/01 05:28:42 itojun Exp $ */
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+/*
+ * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce
+ * support for mandatory and extensible security protections.  This notice
+ * is included in support of clause 2.2 (b) of the Apple Public License,
+ * Version 2.0.
+ */
 
 #include <sys/param.h>
 #include <sys/systm.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
-#include <net/netisr.h>
 #include <net/route.h>
 #include <net/bpf.h>
+#include <net/kpi_protocol.h>
+#include <net/kpi_interface.h>
 
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 
 #include <net/net_osdep.h>
 
+#if CONFIG_MACF_NET
+#include <security/mac_framework.h>
+#endif
+
 #define GIFNAME                "gif"
 #define GIFDEV         "if_gif"
 #define GIF_MAXUNIT    0x7fff  /* ifp->if_unit is only 15 bits */
@@ -104,12 +121,13 @@ static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
 TAILQ_HEAD(gifhead, gif_softc) gifs = TAILQ_HEAD_INITIALIZER(gifs);
 
 #ifdef __APPLE__
-void gifattach __P((void));
-int gif_pre_output __P((struct ifnet *, register struct mbuf **, struct sockaddr *,
-       caddr_t, char *, char *, u_long));
+void gifattach(void);
 static void gif_create_dev(void);
 static int gif_encapcheck(const struct mbuf*, int, int, void*);
-
+static errno_t gif_output(ifnet_t ifp, mbuf_t m);
+static errno_t gif_input(ifnet_t ifp, protocol_family_t protocol_family,
+                                                mbuf_t m, char *frame_header);
+static errno_t gif_ioctl(ifnet_t ifp, u_int32_t cmd, void *data);
 
 int ngif = 0;          /* number of interfaces */
 #endif
@@ -119,37 +137,24 @@ struct protosw in_gif_protosw =
 { SOCK_RAW,    0,      0/*IPPROTO_IPV[46]*/,   PR_ATOMIC|PR_ADDR,
   in_gif_input,        0,      0,              0,
   0,
-  0,           0,              0,              0,
+  0,           0,      0,      0,      
   0,
-  &rip_usrreqs
+  &rip_usrreqs,
+  0,           rip_unlock,     0, {0, 0}, 0, {0}
 };
 #endif
 #if INET6
 struct ip6protosw in6_gif_protosw =
 { SOCK_RAW,    0,      0/*IPPROTO_IPV[46]*/,   PR_ATOMIC|PR_ADDR,
-  in6_gif_input,
-  0,   0,              0,
+  in6_gif_input, 0,            0,              0,
   0,
   0,           0,              0,              0,
-  0,
-  &rip6_usrreqs
-};
-#endif
+  0,  
+  &rip6_usrreqs,
+  0,           rip_unlock,             0, {0, 0}, 0, {0}
 
-#ifndef MAX_GIF_NEST
-/*
- * This macro controls the upper limitation on nesting of gif tunnels.
- * Since, setting a large value to this macro with a careless configuration
- * may introduce system crash, we don't allow any nestings by default.
- * If you need to configure nested gif tunnels, you can define this macro
- * in your kernel configuration file. However, if you do so, please be
- * careful to configure the tunnels so that it won't make a loop.
- */
-#define MAX_GIF_NEST 1
+};
 #endif
-static int max_gif_nesting = MAX_GIF_NEST;
-
-
 
 #ifdef __APPLE__
 /*
@@ -163,156 +168,115 @@ static int max_gif_nesting = MAX_GIF_NEST;
  */
 
 /* GIF interface module support */
-int gif_demux(ifp, m, frame_header, proto)
-    struct ifnet *ifp;
-    struct mbuf  *m;
-    char         *frame_header;
-    struct if_proto **proto;
+static int gif_demux(
+    ifnet_t                                    ifp,
+    __unused mbuf_t                    m,
+    __unused char                      *frame_header,
+    protocol_family_t          *protocol_family)
 {
-       struct gif_softc* gif = (struct gif_softc*)ifp->if_softc;
-       
        /* Only one protocol may be attached to a gif interface. */
-       *proto = gif->gif_proto;
+       *protocol_family = ((struct gif_softc*)ifnet_softc(ifp))->gif_proto;
        
        return 0;
 }
 
-static
-int  gif_add_if(struct ifnet *ifp) 
-{
-    ifp->if_demux  = gif_demux;
-    ifp->if_framer = 0;
-    return 0;
-}       
-
-static
-int  gif_del_if(struct ifnet *ifp)
-{       
-    return 0;
-}   
-
-static
-int  gif_add_proto(struct ddesc_head_str *desc_head, struct if_proto *proto, u_long dl_tag)
+static errno_t
+gif_add_proto(
+       ifnet_t                                                                 ifp,
+       protocol_family_t                                               protocol_family,
+       __unused const struct ifnet_demux_desc  *demux_array,
+       __unused u_int32_t                                              demux_count)
 {
        /* Only one protocol may be attached at a time */
-       struct gif_softc* gif = (struct gif_softc*)proto->ifp;
-
-       if (gif->gif_proto != NULL)
-               printf("gif_add_proto: request add_proto for gif%d\n", gif->gif_if.if_unit);
-
-       gif->gif_proto = proto;
+       struct gif_softc* gif = ifnet_softc(ifp);
 
-       return 0;
-}
+       if (gif->gif_proto != 0)
+               printf("gif_add_proto: request add_proto for gif%d\n", ifnet_unit(ifp));
 
-static
-int  gif_del_proto(struct if_proto *proto, u_long dl_tag)
-{
-       if (((struct gif_softc*)proto->ifp)->gif_proto == proto)
-               ((struct gif_softc*)proto->ifp)->gif_proto = NULL;
-       else
-               return ENOENT;
+       gif->gif_proto = protocol_family;
 
        return 0;
 }
 
-int gif_shutdown()
+static errno_t
+gif_del_proto(
+       ifnet_t                         ifp,
+       protocol_family_t       protocol_family)
 {
+       if (((struct gif_softc*)ifnet_softc(ifp))->gif_proto == protocol_family)
+               ((struct gif_softc*)ifnet_softc(ifp))->gif_proto = 0;
+       
        return 0;
 }
 
-void gif_reg_if_mods()
-{
-     struct dlil_ifmod_reg_str  gif_ifmod;
-
-     bzero(&gif_ifmod, sizeof(gif_ifmod));
-     gif_ifmod.add_if = gif_add_if;
-     gif_ifmod.del_if = gif_del_if;
-     gif_ifmod.add_proto = gif_add_proto;
-     gif_ifmod.del_proto = gif_del_proto;
-     gif_ifmod.ifmod_ioctl = 0;
-     gif_ifmod.shutdown    = gif_shutdown;
-
-    if (dlil_reg_if_modules(APPLE_IF_FAM_GIF, &gif_ifmod))
-        panic("Couldn't register gif modules\n");
-
-}
-
 /* Glue code to attach inet to a gif interface through DLIL */
-
-u_long  gif_attach_proto_family(struct ifnet *ifp, int af)
+static errno_t
+gif_attach_proto_family(
+       ifnet_t                         ifp,
+       protocol_family_t       protocol_family)
 {
-    struct dlil_proto_reg_str   reg;
-    struct dlil_demux_desc      desc;
-    u_long                      dl_tag=0;
-    short native=0;     
-    int   stat;
-
-       /* Check if we're already attached */
-       stat = dlil_find_dltag(ifp->if_family, ifp->if_unit, af, &dl_tag);
-       if (stat == 0)
-               return dl_tag;
-
-    TAILQ_INIT(&reg.demux_desc_head);
-    desc.type = DLIL_DESC_RAW;
-    desc.variants.bitmask.proto_id_length = 0;
-    desc.variants.bitmask.proto_id = 0;
-    desc.variants.bitmask.proto_id_mask = 0;
-    desc.native_type = (char *) &native;
-    TAILQ_INSERT_TAIL(&reg.demux_desc_head, &desc, next);
-    reg.interface_family = ifp->if_family;
-    reg.unit_number      = ifp->if_unit;
-    reg.input            = gif_input;
-    reg.pre_output       = gif_pre_output;
-    reg.event            = 0;
-    reg.offer            = 0;
-    reg.ioctl            = 0;
-    reg.default_proto    = 0;
-    reg.protocol_family  = af;
-
-    stat = dlil_attach_protocol(&reg, &dl_tag);
-    if (stat) {
-        panic("gif_attach_proto_family can't attach interface fam=%d\n", af);
-    }
+    struct ifnet_attach_proto_param    reg;
+    errno_t                                                    stat;
 
-    return dl_tag;
-}
+       bzero(&reg, sizeof(reg));
+    reg.input            = gif_input;
 
-u_long  gif_detach_proto_family(struct ifnet *ifp, int af)
-{
-    u_long      ip_dl_tag = 0;
-    int         stat;
-
-    stat = dlil_find_dltag(ifp->if_family, ifp->if_unit, af, &ip_dl_tag);
-    if (stat == 0) {
-        stat = dlil_detach_protocol(ip_dl_tag);
-        if (stat) {
-            printf("WARNING: gif_detach can't detach IP fam=%d from interface\n", af);
-       }
+    stat = ifnet_attach_protocol(ifp, protocol_family, &reg);
+    if (stat && stat != EEXIST) {
+        printf("gif_attach_proto_family can't attach interface fam=%d\n",
+                  protocol_family);
     }
-    return (stat);
+
+    return stat;
 }
 
 #endif
 
 /* Function to setup the first gif interface */
-void
+__private_extern__ void
 gifattach(void)
 {
+       errno_t result;
+
        /* Init the list of interfaces */
        TAILQ_INIT(&gifs);
 
-       gif_reg_if_mods(); /* DLIL modules */
+       /* Register protocol registration functions */
+       result = proto_register_plumber(PF_INET, APPLE_IF_FAM_GIF,
+                                                                       gif_attach_proto_family, NULL);
+       if (result != 0)
+               printf("proto_register_plumber failed for AF_INET error=%d\n", result);
+       
+       result = proto_register_plumber(PF_INET6, APPLE_IF_FAM_GIF,
+                                                                       gif_attach_proto_family, NULL);
+       if (result != 0)
+               printf("proto_register_plumber failed for AF_INET6 error=%d\n", result);
 
        /* Create first device */
        gif_create_dev();
 }
 
+static errno_t
+gif_set_bpf_tap(
+       ifnet_t                 ifp,
+       bpf_tap_mode    mode,
+       bpf_packet_func callback)
+{
+       struct gif_softc        *sc = ifnet_softc(ifp);
+       
+       sc->tap_mode = mode;
+       sc->tap_callback = callback;
+       
+       return 0;
+}
+
 /* Creates another gif device if there are none free */
 static void
 gif_create_dev(void)
 {
-       struct gif_softc *sc;
+       struct gif_softc                        *sc;
+       struct ifnet_init_params        gif_init;
+       errno_t                                         result = 0;
        
        
        /* Can't create more than GIF_MAXUNIT */
@@ -322,7 +286,7 @@ gif_create_dev(void)
        /* Check for unused gif interface */
        TAILQ_FOREACH(sc, &gifs, gif_link) {
                /* If unused, return, no need to create a new interface */
-               if ((sc->gif_if.if_flags & IFF_RUNNING) == 0)
+               if ((ifnet_flags(sc->gif_if) & IFF_RUNNING) == 0)
                        return;
        }
 
@@ -331,23 +295,39 @@ gif_create_dev(void)
                log(LOG_ERR, "gifattach: failed to allocate gif%d\n", ngif);
                return;
        }
+       
+       bzero(&gif_init, sizeof(gif_init));
+       gif_init.name = GIFNAME;
+       gif_init.unit = ngif;
+       gif_init.type = IFT_GIF;
+       gif_init.family = IFNET_FAMILY_GIF;
+       gif_init.output = gif_output;
+       gif_init.demux = gif_demux;
+       gif_init.add_proto = gif_add_proto;
+       gif_init.del_proto = gif_del_proto;
+       gif_init.softc = sc;
+       gif_init.ioctl = gif_ioctl;
+       gif_init.set_bpf_tap = gif_set_bpf_tap;
 
        bzero(sc, sizeof(struct gif_softc));
-       sc->gif_if.if_softc     = sc;
-       sc->gif_if.if_name      = GIFNAME;
-       sc->gif_if.if_unit      = ngif;
-       
+       result = ifnet_allocate(&gif_init, &sc->gif_if);
+       if (result != 0) {
+               printf("gif_create_dev, ifnet_allocate failed - %d\n", result);
+               _FREE(sc, M_DEVBUF);
+               return;
+       }
        sc->encap_cookie4 = sc->encap_cookie6 = NULL;
-#ifdef INET
+#if INET
        sc->encap_cookie4 = encap_attach_func(AF_INET, -1,
            gif_encapcheck, &in_gif_protosw, sc);
        if (sc->encap_cookie4 == NULL) {
-               printf("%s: unable to attach encap4\n", if_name(&sc->gif_if));
+               printf("%s: unable to attach encap4\n", if_name(sc->gif_if));
+               ifnet_release(sc->gif_if);
                FREE(sc, M_DEVBUF);
                return;
        }
 #endif
-#ifdef INET6
+#if INET6
        sc->encap_cookie6 = encap_attach_func(AF_INET6, -1,
            gif_encapcheck, (struct protosw*)&in6_gif_protosw, sc);
        if (sc->encap_cookie6 == NULL) {
@@ -355,34 +335,40 @@ gif_create_dev(void)
                        encap_detach(sc->encap_cookie4);
                        sc->encap_cookie4 = NULL;
                }
-               printf("%s: unable to attach encap6\n", if_name(&sc->gif_if));
+               printf("%s: unable to attach encap6\n", if_name(sc->gif_if));
+               ifnet_release(sc->gif_if);
                FREE(sc, M_DEVBUF);
                return;
        }
 #endif
-       
-       sc->gif_if.if_family= APPLE_IF_FAM_GIF;
-       sc->gif_if.if_mtu       = GIF_MTU;
-       sc->gif_if.if_flags  = IFF_POINTOPOINT | IFF_MULTICAST;
+       sc->gif_called = 0;
+       ifnet_set_mtu(sc->gif_if, GIF_MTU);
+       ifnet_set_flags(sc->gif_if, IFF_POINTOPOINT | IFF_MULTICAST, 0xffff);
 #if 0
        /* turn off ingress filter */
        sc->gif_if.if_flags  |= IFF_LINK2;
 #endif
-       sc->gif_if.if_ioctl     = gif_ioctl;
-       sc->gif_if.if_output = NULL;    /* pre_output returns error or EJUSTRETURN */
-       sc->gif_if.if_type   = IFT_GIF;
-       dlil_if_attach(&sc->gif_if);
-       bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
+       result = ifnet_attach(sc->gif_if, NULL);
+       if (result != 0) {
+               printf("gif_create_dev - ifnet_attach failed - %d\n", result);
+               ifnet_release(sc->gif_if);
+               FREE(sc, M_DEVBUF);
+               return;
+       }
+#if CONFIG_MACF_NET
+       mac_ifnet_label_init(&sc->gif_if);
+#endif
+       bpfattach(sc->gif_if, DLT_NULL, sizeof(u_int));
        TAILQ_INSERT_TAIL(&gifs, sc, gif_link);
        ngif++;
 }
 
 static int
-gif_encapcheck(m, off, proto, arg)
-       const struct mbuf *m;
-       int off;
-       int proto;
-       void *arg;
+gif_encapcheck(
+       const struct mbuf *m,
+       int off,
+       int proto,
+       void *arg)
 {
        struct ip ip;
        struct gif_softc *sc;
@@ -391,7 +377,7 @@ gif_encapcheck(m, off, proto, arg)
        if (sc == NULL)
                return 0;
 
-       if ((sc->gif_if.if_flags & IFF_UP) == 0)
+       if ((ifnet_flags(sc->gif_if) & IFF_UP) == 0)
                return 0;
 
        /* no physical address */
@@ -411,8 +397,7 @@ gif_encapcheck(m, off, proto, arg)
                return 0;
        }
 
-       /* LINTED const cast */
-       m_copydata((struct mbuf *)m, 0, sizeof(ip), (caddr_t)&ip);
+       mbuf_copydata(m, 0, sizeof(ip), &ip);
 
        switch (ip.ip_v) {
 #if INET
@@ -434,64 +419,31 @@ gif_encapcheck(m, off, proto, arg)
        }
 }
 
-int
-gif_pre_output(ifp, m0, dst, rt, frame, address, dl_tag)
-       struct ifnet *ifp;
-       struct mbuf **m0;
-       struct sockaddr *dst;
-       caddr_t rt;
-       char *frame;
-       char *address;
-       u_long dl_tag;
+static errno_t
+gif_output(
+       ifnet_t         ifp,
+       mbuf_t          m)
 {
-       struct gif_softc *sc = (struct gif_softc*)ifp;
-       register struct mbuf * m = *m0;
+       struct gif_softc *sc = ifnet_softc(ifp);
        int error = 0;
-       static int called = 0;  /* XXX: MUTEX */
-
+       
        /*
-        * gif may cause infinite recursion calls when misconfigured.
-        * We'll prevent this by introducing upper limit.
-        * XXX: this mechanism may introduce another problem about
-        *      mutual exclusion of the variable CALLED, especially if we
-        *      use kernel thread.
+          max_gif_nesting check used to live here. It doesn't anymore
+          because there is no guaruntee that we won't be called
+          concurrently from more than one thread.
         */
-       if (++called > max_gif_nesting) {
-               log(LOG_NOTICE,
-                   "gif_output: recursively called too many times(%d)\n",
-                   called);
-               error = EIO;    /* is there better errno? */
-               goto end;
-       }
-
-       getmicrotime(&ifp->if_lastchange);
+       
        m->m_flags &= ~(M_BCAST|M_MCAST);
-       if (!(ifp->if_flags & IFF_UP) ||
+       if (!(ifnet_flags(ifp) & IFF_UP) ||
            sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
+               ifnet_touch_lastchange(ifp);
+               m_freem(m);     /* free it here not in dlil_output */
                error = ENETDOWN;
                goto end;
        }
 
-       if (ifp->if_bpf) {
-               /*
-                * We need to prepend the address family as
-                * a four byte field.  Cons up a dummy header
-                * to pacify bpf.  This is safe because bpf
-                * will only read from the mbuf (i.e., it won't
-                * try to free it or keep a pointer a to it).
-                */
-               struct mbuf m0;
-               u_int32_t af = dst->sa_family;
-
-               m0.m_next = m;
-               m0.m_len = 4;
-               m0.m_data = (char *)&af;
-               
-               bpf_mtap(ifp, &m0);
-       }
-       ifp->if_opackets++;     
-       ifp->if_obytes += m->m_pkthdr.len;
-
+       bpf_tap_out(ifp, 0, m, &sc->gif_proto, sizeof(sc->gif_proto));
+       
        /* inner AF-specific encapsulation */
 
        /* XXX should we check if our outer source is legal? */
@@ -500,12 +452,12 @@ gif_pre_output(ifp, m0, dst, rt, frame, address, dl_tag)
        switch (sc->gif_psrc->sa_family) {
 #if INET
        case AF_INET:
-               error = in_gif_output(ifp, dst->sa_family, m, (struct rtentry*)rt);
+               error = in_gif_output(ifp, sc->gif_proto, m, NULL);
                break;
 #endif
 #if INET6
        case AF_INET6:
-               error = in6_gif_output(ifp, dst->sa_family, m, (struct rtentry*)rt);
+               error = in6_gif_output(ifp, sc->gif_proto, m, NULL);
                break;
 #endif
        default:
@@ -514,55 +466,32 @@ gif_pre_output(ifp, m0, dst, rt, frame, address, dl_tag)
        }
 
   end:
-       called = 0;             /* reset recursion counter */
-       if (error)
-               ifp->if_oerrors++;
+       if (error) {
+               /* the mbuf was freed either by in_gif_output or in here */
+               ifnet_stat_increment_out(ifp, 0, 0, 1);
+       }
+       else {
+               ifnet_stat_increment_out(ifp, 1, m->m_pkthdr.len, 0);
+       }
        if (error == 0) 
                error = EJUSTRETURN; /* if no error, packet got sent already */
        return error;
 }
 
-int
-gif_input(m, frame_header, gifp, dl_tag, sync_ok)
-       struct mbuf *m;
-       char* frame_header;
-       struct ifnet* gifp;
-       u_long dl_tag;
-       int sync_ok;
+/*
+ * gif_input is the input handler for IP and IPv6 attached to gif
+ */
+static errno_t
+gif_input(
+       ifnet_t                         ifp,
+       protocol_family_t       protocol_family,
+       mbuf_t                          m,
+       __unused char           *frame_header)
 {
-       int s, isr;
-       struct ifqueue *ifq = 0;
-       int af;
-
-       if (gifp == NULL) {
-               /* just in case */
-               m_freem(m);
-               return;
-       }
-
-       /* Assume packet is of type of protocol attached to this interface */
-       af = ((struct gif_softc*)(gifp->if_softc))->gif_proto->protocol_family;
-
-       if (m->m_pkthdr.rcvif)
-               m->m_pkthdr.rcvif = gifp;
+       errno_t error;
+       struct gif_softc *sc = ifnet_softc(ifp);
        
-       if (gifp->if_bpf) {
-               /*
-                * We need to prepend the address family as
-                * a four byte field.  Cons up a dummy header
-                * to pacify bpf.  This is safe because bpf
-                * will only read from the mbuf (i.e., it won't
-                * try to free it or keep a pointer a to it).
-                */
-               struct mbuf m0;
-               u_int32_t af1 = af;
-               
-               m0.m_next = m;
-               m0.m_len = 4;
-               m0.m_data = (char *)&af1;
-               
-               bpf_mtap(gifp, &m0);
-       }
+       bpf_tap_in(ifp, 0, m, &sc->gif_proto, sizeof(sc->gif_proto));
 
        /*
         * Put the packet to the network layer input queue according to the
@@ -576,54 +505,24 @@ gif_input(m, frame_header, gifp, dl_tag, sync_ok)
         * it occurs more times than we thought, we may change the policy
         * again.
         */
-       switch (af) {
-#if INET
-       case AF_INET:
-               ifq = &ipintrq;
-               isr = NETISR_IP;
-               break;
-#endif
-#if INET6
-       case AF_INET6:
-               ifq = &ip6intrq;
-               isr = NETISR_IPV6;
-               break;
-#endif
-       default:
-               m_freem(m);
-               return (EJUSTRETURN);
-       }
-
-       s = splimp();
-       if (IF_QFULL(ifq)) {
-               IF_DROP(ifq);   /* update statistics */
-               m_freem(m);
-               splx(s);
-               return (EJUSTRETURN);
-       }
-       IF_ENQUEUE(ifq, m);
-       /* we need schednetisr since the address family may change */
-       schednetisr(isr);
-       gifp->if_ipackets++;
-       gifp->if_ibytes += m->m_pkthdr.len;
-       splx(s);
+       error = proto_input(protocol_family, m);
+       ifnet_stat_increment_in(ifp, 1, m->m_pkthdr.len, 0);
 
        return (0);
 }
 
 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
-int
-gif_ioctl(ifp, cmd, data)
-       struct ifnet *ifp;
-       u_long cmd;
-       void* data;
+static errno_t
+gif_ioctl(
+       ifnet_t                 ifp,
+       u_int32_t               cmd,
+       void                    *data)
 {
-       struct gif_softc *sc  = (struct gif_softc*)ifp;
+       struct gif_softc *sc  = ifnet_softc(ifp);
        struct ifreq     *ifr = (struct ifreq*)data;
        int error = 0, size;
-       struct sockaddr *dst, *src;
+       struct sockaddr *dst = NULL, *src = NULL;
        struct sockaddr *sa;
-       int s;
        struct ifnet *ifp2;
        struct gif_softc *sc2;
                
@@ -649,7 +548,7 @@ gif_ioctl(ifp, cmd, data)
                        if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
                                return (EINVAL);
                        }
-                       ifp->if_mtu = mtu;
+                       ifnet_set_mtu(ifp, mtu);
                }
                break;
 #endif /* SIOCSIFMTU */
@@ -738,10 +637,11 @@ gif_ioctl(ifp, cmd, data)
                        break;
                }
 
-               TAILQ_FOREACH(ifp2, &ifnet, if_link) {
-                       if (strcmp(ifp2->if_name, GIFNAME) != 0)
+               ifnet_head_lock_shared();
+               TAILQ_FOREACH(ifp2, &ifnet_head, if_link) {
+                       if (strcmp(ifnet_name(ifp2), GIFNAME) != 0)
                                continue;
-                       sc2 = ifp2->if_softc;
+                       sc2 = ifnet_softc(ifp2);
                        if (sc2 == sc)
                                continue;
                        if (!sc2->gif_pdst || !sc2->gif_psrc)
@@ -756,6 +656,7 @@ gif_ioctl(ifp, cmd, data)
                        if (bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
                            bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
                                error = EADDRNOTAVAIL;
+                               ifnet_head_done();
                                goto bad;
                        }
 #endif
@@ -770,16 +671,19 @@ gif_ioctl(ifp, cmd, data)
                        if (dst->sa_family == AF_INET &&
                            multidest(dst) && multidest(sc2->gif_pdst)) {
                                error = EADDRNOTAVAIL;
+                               ifnet_head_done();
                                goto bad;
                        }
 #if INET6
                        if (dst->sa_family == AF_INET6 &&
                            multidest6(dst) && multidest6(sc2->gif_pdst)) {
                                error = EADDRNOTAVAIL;
+                               ifnet_head_done();
                                goto bad;
                        }
 #endif
                }
+               ifnet_head_done();
 
                if (sc->gif_psrc)
                        FREE((caddr_t)sc->gif_psrc, M_IFADDR);
@@ -793,17 +697,12 @@ gif_ioctl(ifp, cmd, data)
                bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
                sc->gif_pdst = sa;
 
-               ifp->if_flags |= IFF_RUNNING;
-
-               gif_attach_proto_family(ifp, src->sa_family);
-
-               s = splimp();
-               if_up(ifp);     /* mark interface UP and send up RTM_IFINFO */
+               ifnet_set_flags(ifp, IFF_RUNNING | IFF_UP, IFF_RUNNING | IFF_UP);
+               
 #ifdef __APPLE__
                /* Make sure at least one unused device is still available */
                gif_create_dev();
 #endif
-               splx(s);
 
                error = 0;
                break;
@@ -923,6 +822,8 @@ gif_ioctl(ifp, cmd, data)
        return error;
 }
 
+#ifndef __APPLE__
+/* This function is not used in our stack */
 void
 gif_delete_tunnel(sc)
        struct gif_softc *sc;
@@ -939,3 +840,4 @@ gif_delete_tunnel(sc)
        }
        /* change the IFF_UP flag as well? */
 }
+#endif