]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netat/ddp_lap.c
xnu-792.2.4.tar.gz
[apple/xnu.git] / bsd / netat / ddp_lap.c
index 8418e61af1e438a185edb67cb54e89db27e5afe4..f2ed8d1b40bafffbab3af351bdf47ef9e1b9940e 100644 (file)
@@ -3,22 +3,19 @@
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * 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. 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
+ * This 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, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 #include <sys/mbuf.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
+#include <net/if_dl.h>
 #include <sys/socketvar.h>
 #include <sys/malloc.h>
+#include <sys/domain.h>
 #include <sys/sockio.h>
 #include <vm/vm_kern.h>         /* for kernel_map */
 
@@ -128,6 +127,7 @@ extern asp_scb_t *scb_used_list;
 extern CCB *adsp_inputQ[];
 extern CCB *ccb_used_list;
 extern at_ddp_stats_t at_ddp_stats;
+extern lck_mtx_t * atalk_mutex;
 
 /* protos */
 extern snmpAarpEnt_t * getAarp(int *);
@@ -308,7 +308,7 @@ int elap_wput(gref, m)
        register ioc_t          *iocbp;
        register at_if_cfg_t    *cfgp;
        at_elap_stats_t         *statsp;
-       int error, i;
+       int             i;
        int                     (*func)();
        gbuf_t          *tmpm;
        at_ifaddr_t *patp;
@@ -777,7 +777,7 @@ elap_dataput(m, elapp, addr_flag, addr)
      char *addr;
 {
        register int            size;
-       int                     error;
+       int                     error = 0;
        extern  int             zip_type_packet();
        struct  etalk_addr      dest_addr;
        struct  atalk_addr      dest_at_addr;
@@ -887,14 +887,28 @@ static int elap_online1(elapp)
        /* Get DDP started */
        if ((errno = ddp_add_if(elapp)))
                return(errno);
-
+       
+       // check if we still have an interface - can be lost when
+       // ddp_add_if calls malloc
+       // need to make check here after ddp_add_if completes because 
+       // lap_online will call ddp_rem_if if we fail here
+       if (elapp->aa_ifp == 0)
+               return ENOENT;
+               
        /* set up multicast address for cable-wide broadcasts */
        (void)at_reg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
 
+        // need to check again if interface is present
+        // can be lost in at_reg_mcast
+       if (elapp->aa_ifp == 0)
+               return ENOENT;
+
        elapp->startup_inprogress = TRUE;
-       if (! (elapp->startup_error = re_aarp(elapp)))
-               (void)tsleep(&elapp->startup_inprogress, PSOCK | PCATCH, 
+       if (! (elapp->startup_error = re_aarp(elapp))) {
+               lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED);
+               (void)msleep(&elapp->startup_inprogress, atalk_mutex, PSOCK | PCATCH, 
                             "elap_online1", 0);
+       }
 
        /* then later, after some timeouts AARPwakeup() is called */
 
@@ -995,7 +1009,8 @@ int elap_online3(elapp)
 
        /* then later, after some timeouts AARPwakeup() is called */
 
-       (void)tsleep(&elapp->startup_inprogress, PSOCK | PCATCH, 
+       lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED);
+       (void)msleep(&elapp->startup_inprogress, atalk_mutex, PSOCK | PCATCH, 
                     "elap_online3", 0);
        return(elapp->startup_error);
 } /* elap_online3 */
@@ -1032,6 +1047,7 @@ void elap_offline(elapp)
                ATENABLE(s, ddpinp_lock);
 
                /* make sure no zip timeouts are left running */
+               elapp->ifGNIScheduled = 0;
                untimeout(zip_sched_getnetinfo, elapp);
        }
        ddp_rem_if(elapp);
@@ -1083,8 +1099,6 @@ int ddp_shutdown(count_only)
        vm_offset_t temp_rcb_data, temp_state_data;
        int i, s, active_skts = 0;      /* count of active pids for non-socketized
                                   AppleTalk protocols */
-       extern int aarp_sched_probe();
-
 
        /* Network is shutting down... send error messages up on each open
         * socket.
@@ -1235,29 +1249,6 @@ int ddp_shutdown(count_only)
        }
        ddp_start();
        
-       /* free buffers for large arrays used by atp.
-        * to prevent a race condition if the funnel is dropped
-        * while calling kmem_free, the fields are grabbed and
-        * zeroed first.
-        */
-       if (atp_rcb_data != NULL) {
-               temp_rcb_data = (vm_offset_t)atp_rcb_data; 
-               atp_rcb_data = NULL;
-               atp_rcb_free_list = NULL;
-       } else
-               temp_rcb_data = NULL;
-       if (atp_state_data != NULL) {
-               temp_state_data = (vm_offset_t)atp_state_data;
-               atp_state_data = NULL;
-               atp_free_list = NULL;
-       } else
-               temp_state_data = NULL;
-
-       if (temp_rcb_data)
-         kmem_free(kernel_map, temp_rcb_data, sizeof(struct atp_rcb) * NATP_RCB);
-       if (temp_state_data)
-         kmem_free(kernel_map, temp_state_data, sizeof(struct atp_state) * NATP_STATE);
-
        splx(s);
        return(0);
 } /* ddp_shutdown */
@@ -1267,6 +1258,7 @@ int routerStart(keP)
 {
        register at_ifaddr_t *ifID;
        int error;
+       struct timespec ts;
 
        if (! ifID_home)
                return(EINVAL);
@@ -1290,12 +1282,18 @@ int routerStart(keP)
        dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
                ("router_start: waiting 20 sec before starting up\n"));
 
+       lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED);
        /* sleep for 20 seconds */
+
+       /* the vaue of 10n terms of hz is 100ms */
+       ts.tv_sec = 20;
+       ts.tv_nsec = 0;
+       
        if ((error = 
             /* *** eventually this will be the ifID for the interface
                being brought up in router mode *** */
-            tsleep(&ifID_home->startup_inprogress, 
-                   PSOCK | PCATCH, "routerStart", 20 * SYS_HZ))
+               msleep(&ifID_home->startup_inprogress, atalk_mutex,
+                   PSOCK | PCATCH, "routerStart", &ts))
            != EWOULDBLOCK) {
 /*
                if (!error)
@@ -1364,7 +1362,7 @@ void AARPwakeup(probe_cb)
 
        ATDISABLE(s, arpinp_lock);
        elapp = probe_cb->elapp;
-       if ( (elapp != NULL) && elapp->startup_inprogress ) {
+       if ( (elapp != NULL) && elapp->startup_inprogress && elapp->aa_ifp != 0) {
                ATENABLE(s, arpinp_lock);
 
                /* was AARPContinue */
@@ -1444,7 +1442,9 @@ static int elap_trackMcast(patp, func, addr)
        u_char c;
        switch(patp->aa_ifp->if_type) {
        case IFT_ETHER: 
-       case IFT_FDDI: 
+       case IFT_FDDI:
+       case IFT_L2VLAN:
+       case IFT_IEEE8023ADLAG: /* bonded ethernet */
                /* set addr to point to unique part of addr */
                c = addr[5];
 
@@ -1531,6 +1531,8 @@ static getSnmpCfg(snmp)
                        ifc->ifc_addrSize = getPhysAddrSize(i);
                        switch (elapp->aa_ifp->if_type) {
                                case IFT_ETHER:
+                                case IFT_L2VLAN:
+                               case IFT_IEEE8023ADLAG: /* bonded ethernet */
                                        ifc->ifc_type = SNMP_TYPE_ETHER2;
                                        break;
                                case IFT_ISO88025: /* token ring */
@@ -1586,7 +1588,7 @@ int at_reg_mcast(ifID, data)
      caddr_t data;
 {
        struct ifnet *nddp = ifID->aa_ifp;
-       struct sockaddr sa;
+       struct sockaddr_dl sdl;
 
        if (*(int *)data) {
                if (!nddp) {
@@ -1598,16 +1600,22 @@ int at_reg_mcast(ifID, data)
                        return(0);
 
                /* this is for ether_output */
-               sa.sa_family = AF_UNSPEC;
-               sa.sa_len = 2 + sizeof(struct etalk_addr);
-               bcopy (data, &sa.sa_data[0], sizeof(struct etalk_addr));
+               bzero(&sdl, sizeof(sdl));
+               sdl.sdl_family = AF_LINK;
+               sdl.sdl_alen = sizeof(struct etalk_addr);
+               sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data) 
+                   + sizeof(struct etalk_addr);
+               bcopy(data, sdl.sdl_data, sizeof(struct etalk_addr));
+               /* these next two lines should not really be needed XXX */
+               sdl.sdl_index = nddp->if_index;
+               sdl.sdl_type = IFT_ETHER;
 
                dPrintf(D_M_PAT, D_L_STARTUP,
                        ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
                         *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff, 
                         (unsigned)ifID));
 
-               if (if_addmulti(nddp, &sa, 0))
+               if (if_addmulti(nddp, &sdl, 0))
                        return -1;
        }
        return 0;
@@ -1619,7 +1627,7 @@ int at_unreg_mcast(ifID, data)
      caddr_t data;
 {
        struct ifnet *nddp = ifID->aa_ifp;
-       struct sockaddr sa;
+       struct sockaddr_dl sdl;
 
        if (*(int *)data) {
                if (!nddp) {
@@ -1630,9 +1638,15 @@ int at_unreg_mcast(ifID, data)
                elap_trackMcast(ifID, MCAST_TRACK_DELETE, data);
 
                /* this is for ether_output */
-               sa.sa_family = AF_UNSPEC;
-               sa.sa_len = 2 + sizeof(struct etalk_addr);
-               bcopy (data, &sa.sa_data[0], sizeof(struct etalk_addr));
+               bzero(&sdl, sizeof(sdl));
+               sdl.sdl_family = AF_LINK;
+               sdl.sdl_alen = sizeof(struct etalk_addr);
+               sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data) 
+                   + sizeof(struct etalk_addr);
+               bcopy(data, sdl.sdl_data, sizeof(struct etalk_addr));
+               /* these next two lines should not really be needed XXX */
+               sdl.sdl_index = nddp->if_index;
+               sdl.sdl_type = IFT_ETHER;
 
                dPrintf(D_M_PAT, D_L_STARTUP,
                        ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
@@ -1640,7 +1654,7 @@ int at_unreg_mcast(ifID, data)
                         (unsigned)ifID));
                bzero(data, sizeof(struct etalk_addr));
 
-               if (if_delmulti(nddp, &sa))
+               if (if_delmulti(nddp, &sdl))
                        return -1;
        }
        return 0;