]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/if_gif.c
xnu-2050.18.24.tar.gz
[apple/xnu.git] / bsd / net / if_gif.c
index 79bacaf4303038b9b4737dce741c01645d682f86..c638758a2b8567cda568b481eab1ad888f873e34 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * 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>
@@ -74,6 +80,8 @@
 #include <net/if_types.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 */
@@ -110,11 +122,11 @@ TAILQ_HEAD(gifhead, gif_softc) gifs = TAILQ_HEAD_INITIALIZER(gifs);
 
 #ifdef __APPLE__
 void gifattach(void);
-int gif_pre_output(struct ifnet *ifp, u_long protocol_family, struct mbuf **m0,
-                                  const struct sockaddr *dst, caddr_t rt, char *frame, char *address);
-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_long cmd, void *data);
 
 int ngif = 0;          /* number of interfaces */
 #endif
@@ -127,7 +139,7 @@ struct protosw in_gif_protosw =
   0,           0,      0,      0,      
   0,
   &rip_usrreqs,
-  0,           rip_unlock,     0
+  0,           rip_unlock,     0, {0, 0}, 0, {0}
 };
 #endif
 #if INET6
@@ -138,25 +150,15 @@ struct ip6protosw in6_gif_protosw =
   0,           0,              0,              0,
   0,  
   &rip6_usrreqs,
-  0,           rip_unlock,             0,
+  0,           rip_unlock,             0, {0, 0}, 0, {0}
 
 };
 #endif
 
-#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;
-
-
+static if_clone_t gif_cloner = NULL;
+static int gif_clone_create(struct if_clone *, uint32_t, void *);
+static int gif_clone_destroy(struct ifnet *);
+static void gif_delete_tunnel(struct gif_softc *);
 
 #ifdef __APPLE__
 /*
@@ -170,65 +172,63 @@ static int max_gif_nesting = MAX_GIF_NEST;
  */
 
 /* GIF interface module support */
-int gif_demux(
-    struct ifnet *ifp,
-    struct mbuf  *m,
-    char         *frame_header,
-    u_long *protocol_family)
+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. */
-       *protocol_family = gif->gif_proto;
+       *protocol_family = ((struct gif_softc*)ifnet_softc(ifp))->gif_proto;
        
        return 0;
 }
 
-static
-int  gif_add_proto(struct ifnet *ifp, u_long protocol_family, struct ddesc_head_str *desc_head)
+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*)ifp->if_softc;
+       struct gif_softc* gif = ifnet_softc(ifp);
 
        if (gif->gif_proto != 0)
-               printf("gif_add_proto: request add_proto for gif%d\n", gif->gif_if.if_unit);
+               printf("gif_add_proto: request add_proto for gif%d\n", ifnet_unit(ifp));
 
        gif->gif_proto = protocol_family;
 
        return 0;
 }
 
-static
-int  gif_del_proto(struct ifnet *ifp, u_long protocol_family)
+static errno_t
+gif_del_proto(
+       ifnet_t                         ifp,
+       protocol_family_t       protocol_family)
 {
-       if (((struct gif_softc*)ifp)->gif_proto == protocol_family)
-               ((struct gif_softc*)ifp)->gif_proto = 0;
-       else
-               return ENOENT;
-
+       if (((struct gif_softc*)ifnet_softc(ifp))->gif_proto == protocol_family)
+               ((struct gif_softc*)ifnet_softc(ifp))->gif_proto = 0;
+       
        return 0;
 }
 
 /* Glue code to attach inet to a gif interface through DLIL */
-int
+static errno_t
 gif_attach_proto_family(
-       struct ifnet *ifp,
-       u_long protocol_family)
+       ifnet_t                         ifp,
+       protocol_family_t       protocol_family)
 {
-    struct dlil_proto_reg_str   reg;
-    int   stat;
+    struct ifnet_attach_proto_param    reg;
+    errno_t                                                    stat;
 
        bzero(&reg, sizeof(reg));
-    TAILQ_INIT(&reg.demux_desc_head);
-    reg.interface_family = ifp->if_family;
-    reg.unit_number      = ifp->if_unit;
     reg.input            = gif_input;
-    reg.pre_output       = gif_pre_output;
-    reg.protocol_family  = protocol_family;
 
-    stat = dlil_attach_protocol(&reg);
+    stat = ifnet_attach_protocol(ifp, protocol_family, &reg);
     if (stat && stat != EEXIST) {
-        panic("gif_attach_proto_family can't attach interface fam=%d\n", protocol_family);
+        printf("gif_attach_proto_family can't attach interface fam=%d\n",
+                  protocol_family);
     }
 
     return stat;
@@ -237,65 +237,111 @@ gif_attach_proto_family(
 #endif
 
 /* Function to setup the first gif interface */
-void
+__private_extern__ void
 gifattach(void)
 {
-       int error;
+       errno_t result;
+       struct ifnet_clone_params ifnet_clone_params;
+       struct if_clone *ifc = NULL; 
 
        /* Init the list of interfaces */
        TAILQ_INIT(&gifs);
 
        /* Register protocol registration functions */
-       if ( error = dlil_reg_proto_module(AF_INET, APPLE_IF_FAM_GIF, gif_attach_proto_family, NULL) != 0)
-               printf("dlil_reg_proto_module failed for AF_INET error=%d\n", error);
+       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);
        
-       if ( error = dlil_reg_proto_module(AF_INET6, APPLE_IF_FAM_GIF, gif_attach_proto_family, NULL) != 0)
-               printf("dlil_reg_proto_module failed for AF_INET6 error=%d\n", error);
+       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);
+
+       ifnet_clone_params.ifc_name = "gif";
+       ifnet_clone_params.ifc_create = gif_clone_create;
+       ifnet_clone_params.ifc_destroy = gif_clone_destroy;
+
+       result = ifnet_clone_attach(&ifnet_clone_params, &gif_cloner);
+       if (result != 0)
+               printf("gifattach: ifnet_clone_attach failed %d\n", result);
 
        /* Create first device */
-       gif_create_dev();
+       ifc = if_clone_lookup("gif", NULL);
+       gif_clone_create(ifc, 0, NULL);
 }
 
-/* Creates another gif device if there are none free */
-static void
-gif_create_dev(void)
+static errno_t
+gif_set_bpf_tap(
+       ifnet_t                 ifp,
+       bpf_tap_mode    mode,
+       bpf_packet_func callback)
 {
-       struct gif_softc *sc;
+       struct gif_softc        *sc = ifnet_softc(ifp);
        
+       sc->tap_mode = mode;
+       sc->tap_callback = callback;
        
+       return 0;
+}
+
+
+static int
+gif_clone_create(struct if_clone *ifc, uint32_t unit, __unused void *params)
+{
+       struct gif_softc        *sc = NULL;
+       struct ifnet_init_params gif_init;
+       errno_t result = 0;
+
        /* Can't create more than GIF_MAXUNIT */
        if (ngif >= GIF_MAXUNIT)
-               return;
-       
-       /* 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)
-                       return;
-       }
+               return (ENXIO);
 
        sc = _MALLOC(sizeof(struct gif_softc), M_DEVBUF, M_WAITOK);
        if (sc == NULL) {
-               log(LOG_ERR, "gifattach: failed to allocate gif%d\n", ngif);
-               return;
+               log(LOG_ERR, "gif_clone_create: failed to allocate gif%d\n", unit);
+               return ENOBUFS;
        }
-
        bzero(sc, sizeof(struct gif_softc));
-       sc->gif_if.if_softc     = sc;
-       sc->gif_if.if_name      = GIFNAME;
-       sc->gif_if.if_unit      = ngif;
-       
+
+       /* use the interface name as the unique id for ifp recycle */
+       snprintf(sc->gif_ifname, sizeof(sc->gif_ifname), "%s%d",
+                       ifc->ifc_name, unit);
+
+       bzero(&gif_init, sizeof(gif_init));
+       gif_init.uniqueid = sc->gif_ifname;
+       gif_init.uniqueid_len = strlen(sc->gif_ifname);
+       gif_init.name = GIFNAME;
+       gif_init.unit = unit;
+       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;
+
+       result = ifnet_allocate(&gif_init, &sc->gif_if);
+       if (result != 0) {
+               printf("gif_clone_create, ifnet_allocate failed - %d\n", result);
+               _FREE(sc, M_DEVBUF);
+               return ENOBUFS;
+       }
+
        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);
+                       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;
+               return ENOBUFS;
        }
 #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) {
@@ -303,38 +349,85 @@ 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;
+               return ENOBUFS;
        }
 #endif
-       
        sc->gif_called = 0;
-       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;
+       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_demux = gif_demux;
-       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;
-       sc->gif_if.if_add_proto = gif_add_proto;
-       sc->gif_if.if_del_proto = gif_del_proto;
-       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_clone_create - ifnet_attach failed - %d\n", result);
+               ifnet_release(sc->gif_if);
+               if (sc->encap_cookie4) {
+                       encap_detach(sc->encap_cookie4);
+                       sc->encap_cookie4 = NULL;
+               }
+               if (sc->encap_cookie6) {
+                       encap_detach(sc->encap_cookie6);
+                       sc->encap_cookie6 = NULL;
+               }
+               FREE(sc, M_DEVBUF);
+               return result;
+       }
+#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++;
+       return 0;
 }
 
 static int
-gif_encapcheck(m, off, proto, arg)
-       const struct mbuf *m;
-       int off;
-       int proto;
-       void *arg;
+gif_clone_destroy(struct ifnet *ifp)
+{
+#if defined(INET) || defined(INET6)
+       int err = 0;
+#endif
+       struct gif_softc *sc = ifp->if_softc;
+
+       TAILQ_REMOVE(&gifs, sc, gif_link);
+
+       gif_delete_tunnel(sc);
+#ifdef INET6
+       if (sc->encap_cookie6 != NULL) {
+               err = encap_detach(sc->encap_cookie6);
+               KASSERT(err == 0, ("gif_clone_destroy: Unexpected error detaching encap_cookie6"));
+       }
+#endif
+#ifdef INET
+       if (sc->encap_cookie4 != NULL) {
+               err = encap_detach(sc->encap_cookie4);
+               KASSERT(err == 0, ("gif_clone_destroy: Unexpected error detaching encap_cookie4"));
+       }
+#endif
+       err = ifnet_set_flags(ifp, 0, IFF_UP);
+       if (err != 0) {
+               printf("gif_clone_destroy: ifnet_set_flags failed %d\n", err);
+       }
+
+       err = ifnet_detach(ifp);
+       if (err != 0)
+               panic("gif_clone_destroy: ifnet_detach(%p) failed %d\n", ifp, err);
+       FREE(sc, M_DEVBUF);
+       ngif--;
+       return 0;
+}
+
+static int
+gif_encapcheck(
+       const struct mbuf *m,
+       int off,
+       int proto,
+       void *arg)
 {
        struct ip ip;
        struct gif_softc *sc;
@@ -343,7 +436,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 */
@@ -363,8 +456,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((struct mbuf *)(size_t)m, 0, sizeof(ip), &ip);
 
        switch (ip.ip_v) {
 #if INET
@@ -386,65 +478,31 @@ gif_encapcheck(m, off, proto, arg)
        }
 }
 
-int
-gif_pre_output(
-       struct ifnet *ifp,
-       u_long protocol_family,
-       struct mbuf **m0,
-       const struct sockaddr *dst,
-       caddr_t rt,
-       char *frame,
-       char *address)
+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;
        
        /*
-        * 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 (++sc->gif_called > max_gif_nesting) {
-               log(LOG_NOTICE,
-                   "gif_output: recursively called too many times(%d)\n",
-                   sc->gif_called);
-               m_freem(m);     /* free it here not in dlil_output*/
-               error = EIO;    /* is there better errno? */
-               goto end;
-       }
-
-       ifnet_touch_lastchange(ifp);
+       
        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 protocol_family = dst->sa_family;
-
-               m0.m_next = m;
-               m0.m_len = 4;
-               m0.m_data = (char *)&protocol_family;
-               
-               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? */
@@ -453,12 +511,12 @@ gif_pre_output(
        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:
@@ -467,52 +525,31 @@ gif_pre_output(
        }
 
   end:
-       sc->gif_called = 0;             /* reset recursion counter */
        if (error) {
                /* the mbuf was freed either by in_gif_output or in here */
-               *m0 = NULL; /* avoid getting dlil_output freeing it */
-               ifp->if_oerrors++;
+               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 is the input handler for IP and IPv6 attached to gif
+ */
+static errno_t
 gif_input(
-       struct mbuf *m,
-       char* frame_header,
-       struct ifnet* gifp,
-       u_long protocol_family,
-       int sync_ok)
+       ifnet_t                         ifp,
+       protocol_family_t       protocol_family,
+       mbuf_t                          m,
+       __unused char           *frame_header)
 {
-
-       if (gifp == NULL) {
-               /* just in case */
-               m_freem(m);
-               return;
-       }
-
-       if (m->m_pkthdr.rcvif)
-               m->m_pkthdr.rcvif = gifp;
+       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 protocol_family1 = protocol_family;
-               
-               m0.m_next = m;
-               m0.m_len = 4;
-               m0.m_data = (char *)&protocol_family1;
-               
-               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
@@ -526,33 +563,34 @@ gif_input(
         * it occurs more times than we thought, we may change the policy
         * again.
         */
-       proto_input(protocol_family, m);
-       gifp->if_ipackets++;
-       gifp->if_ibytes += m->m_pkthdr.len;
+       if (proto_input(protocol_family, m) != 0) {
+               ifnet_stat_increment_in(ifp, 0, 0, 1);
+               m_freem(m);
+       } else
+               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_long                  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;
-               
+
        switch (cmd) {
        case SIOCSIFADDR:
                break;
-               
+
        case SIOCSIFDSTADDR:
                break;
 
@@ -566,19 +604,20 @@ gif_ioctl(ifp, cmd, data)
 
        case SIOCSIFMTU:
                {
-                       u_long mtu;
+                       u_int32_t mtu;
                        mtu = ifr->ifr_mtu;
                        if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
                                return (EINVAL);
                        }
-                       ifp->if_mtu = mtu;
+                       ifnet_set_mtu(ifp, mtu);
                }
                break;
 #endif /* SIOCSIFMTU */
 
        case SIOCSIFPHYADDR:
 #if INET6
-       case SIOCSIFPHYADDR_IN6:
+       case SIOCSIFPHYADDR_IN6_32:
+       case SIOCSIFPHYADDR_IN6_64:
 #endif /* INET6 */
        case SIOCSLIFPHYADDR:
                switch (cmd) {
@@ -591,12 +630,23 @@ gif_ioctl(ifp, cmd, data)
                        break;
 #endif
 #if INET6
-               case SIOCSIFPHYADDR_IN6:
-                       src = (struct sockaddr *)
-                               &(((struct in6_aliasreq *)data)->ifra_addr);
-                       dst = (struct sockaddr *)
-                               &(((struct in6_aliasreq *)data)->ifra_dstaddr);
+               case SIOCSIFPHYADDR_IN6_32: {
+                       struct in6_aliasreq_32 *ifra_32 =
+                           (struct in6_aliasreq_32 *)data;
+
+                       src = (struct sockaddr *)&ifra_32->ifra_addr;
+                       dst = (struct sockaddr *)&ifra_32->ifra_dstaddr;
                        break;
+               }
+
+               case SIOCSIFPHYADDR_IN6_64: {
+                       struct in6_aliasreq_64 *ifra_64 =
+                           (struct in6_aliasreq_64 *)data;
+
+                       src = (struct sockaddr *)&ifra_64->ifra_addr;
+                       dst = (struct sockaddr *)&ifra_64->ifra_dstaddr;
+                       break;
+               }
 #endif
                case SIOCSLIFPHYADDR:
                        src = (struct sockaddr *)
@@ -650,7 +700,8 @@ gif_ioctl(ifp, cmd, data)
                                break;
                        return EAFNOSUPPORT;
 #if INET6
-               case SIOCSIFPHYADDR_IN6:
+               case SIOCSIFPHYADDR_IN6_32:
+               case SIOCSIFPHYADDR_IN6_64:
                        if (src->sa_family == AF_INET6)
                                break;
                        return EAFNOSUPPORT;
@@ -662,9 +713,9 @@ gif_ioctl(ifp, cmd, data)
 
                ifnet_head_lock_shared();
                TAILQ_FOREACH(ifp2, &ifnet_head, if_link) {
-                       if (strcmp(ifp2->if_name, GIFNAME) != 0)
+                       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)
@@ -686,10 +737,10 @@ gif_ioctl(ifp, cmd, data)
 
                        /* can't configure multiple multi-dest interfaces */
 #define multidest(x) \
-       (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY)
+       (((struct sockaddr_in *)(void *)(x))->sin_addr.s_addr == INADDR_ANY)
 #if INET6
 #define multidest6(x) \
-       (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr))
+       (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(void *)(x))->sin6_addr))
 #endif
                        if (dst->sa_family == AF_INET &&
                            multidest(dst) && multidest(sc2->gif_pdst)) {
@@ -711,25 +762,21 @@ gif_ioctl(ifp, cmd, data)
                if (sc->gif_psrc)
                        FREE((caddr_t)sc->gif_psrc, M_IFADDR);
                sa = (struct sockaddr *)_MALLOC(src->sa_len, M_IFADDR, M_WAITOK);
+               if (sa == NULL)
+                       return ENOBUFS;
                bcopy((caddr_t)src, (caddr_t)sa, src->sa_len);
                sc->gif_psrc = sa;
 
                if (sc->gif_pdst)
                        FREE((caddr_t)sc->gif_pdst, M_IFADDR);
                sa = (struct sockaddr *)_MALLOC(dst->sa_len, M_IFADDR, M_WAITOK);
+               if (sa == NULL)
+                       return ENOBUFS; 
                bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len);
                sc->gif_pdst = sa;
 
-               ifp->if_flags |= IFF_RUNNING;
-
-               s = splimp();
-               if_up(ifp);     /* mark interface UP and send up RTM_IFINFO */
-#ifdef __APPLE__
-               /* Make sure at least one unused device is still available */
-               gif_create_dev();
-#endif
-               splx(s);
-
+               ifnet_set_flags(ifp, IFF_RUNNING | IFF_UP, IFF_RUNNING | IFF_UP);
+               
                error = 0;
                break;
 
@@ -848,7 +895,6 @@ gif_ioctl(ifp, cmd, data)
        return error;
 }
 
-#ifndef __APPLE__
 /* This function is not used in our stack */
 void
 gif_delete_tunnel(sc)
@@ -866,4 +912,3 @@ gif_delete_tunnel(sc)
        }
        /* change the IFF_UP flag as well? */
 }
-#endif