X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..4a3eedf9ecc9bbe3f3a5c6ce5e53ad199d639d32:/bsd/netat/ddp_lap.c diff --git a/bsd/netat/ddp_lap.c b/bsd/netat/ddp_lap.c index 8418e61af..c7e075c5a 100644 --- a/bsd/netat/ddp_lap.c +++ b/bsd/netat/ddp_lap.c @@ -1,16 +1,19 @@ /* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, 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 - * 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. + * 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. + * + * 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 @@ -20,7 +23,7 @@ * Please see the License for the specific language governing rights and * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1988, 1989, 1993-1998 Apple Computer, Inc. @@ -56,8 +59,10 @@ #include #include #include +#include #include #include +#include #include #include /* for kernel_map */ @@ -67,6 +72,7 @@ #include #include +#include #include #include #include @@ -74,13 +80,14 @@ #include #include #include -#include #include #include #include #include #include #include +#include +#include #include @@ -116,8 +123,6 @@ int xpatcnt = 0; /* externs */ extern TAILQ_HEAD(name_registry, _nve_) name_registry; extern snmpStats_t snmpStats; -extern atlock_t ddpinp_lock; -extern atlock_t arpinp_lock; extern short appletalk_inited; extern int adspInited; extern struct atpcb ddp_head; @@ -128,21 +133,24 @@ 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 *); -extern void nbp_shutdown(), routershutdown(), ddp_brt_shutdown(); -extern void ddp_brt_init(), rtmp_init(), rtmp_input(); -extern rtmp_router_start(at_kern_err_t *); -static void getIfNames(at_ifnames_t *); -static void add_route(); -static int set_zones(); -void elap_offline(); -static int elap_online1(), re_aarp(); -int at_reg_mcast(), at_unreg_mcast(); -void AARPwakeup(), ZIPwakeup(); -static void elap_hangup(); -static getSnmpCfg(); +int rtmp_router_start(at_kern_err_t *); +static void add_route(RT_entry *); +void elap_offline(at_ifaddr_t *); +static int elap_online1(at_ifaddr_t *); +static void elap_online2(at_ifaddr_t *); + int elap_online3(at_ifaddr_t *); +static int re_aarp(at_ifaddr_t *); +static int getSnmpCfg(snmpCfg_t *); + +int routerStart(at_kern_err_t *); + +static int validate_msg_size(gbuf_t *, gref_t *, at_ifaddr_t **); +at_ifaddr_t *find_ifID(char *); +int lap_online( at_ifaddr_t *, at_if_cfg_t *cfgp); + at_ifaddr_t *find_ifID(if_name) char *if_name; @@ -168,7 +176,6 @@ static int validate_msg_size(m, gref, elapp) */ { register ioc_t *iocbp; - register at_if_cfg_t *cfgp; int i = 0, size = 1; *elapp = NULL; @@ -251,8 +258,9 @@ int lap_online(elapp, cfgp) elapp->flags |= ELAP_CFG_SEED; } - if (!DEFAULT_ZONE(&cfgp->zonename) && - (elapp->flags & ELAP_CFG_HOME) || MULTIHOME_MODE) { + /* (VL) !? */ + if ((!DEFAULT_ZONE(&cfgp->zonename) && + (elapp->flags & ELAP_CFG_HOME)) || MULTIHOME_MODE) { elapp->startup_zone = cfgp->zonename; } @@ -308,10 +316,12 @@ int elap_wput(gref, m) register ioc_t *iocbp; register at_if_cfg_t *cfgp; at_elap_stats_t *statsp; - int error, i; - int (*func)(); - gbuf_t *tmpm; - at_ifaddr_t *patp; + int i,j; + int size, totalsize = 0, tabsize; + gbuf_t *mn; /* new gbuf */ + gbuf_t *mo; /* old gbuf */ + gbuf_t *mt = NULL; /* temp */ + snmpNbpTable_t *nbp; switch (gbuf_type(m)) { @@ -460,7 +470,6 @@ int elap_wput(gref, m) kprintf("LAP_IOC_SNMP_GET_CFG\n"); #endif { - int i,size; snmpCfg_t snmp; i = *(int *)gbuf_rptr(gbuf_cont(m)); @@ -544,12 +553,6 @@ int elap_wput(gref, m) kprintf("LAP_IOC_SNMP_GET_ZIP\n"); #endif { /* matching brace NOT in this case */ - register int i,j; - register int size, total, tabsize; - gbuf_t *mn; /* new gbuf */ - gbuf_t *mo; /* old gbuf */ - gbuf_t *mt; /* temp */ - snmpNbpTable_t *nbp; i = *(int *)gbuf_rptr(gbuf_cont(m)); gbuf_freem(gbuf_cont(m)); @@ -580,11 +583,11 @@ int elap_wput(gref, m) } if (!mo) { /* if first new one */ mt = mn; - total = size; + totalsize = size; } else { gbuf_cont(mo) = mn; - total += size; + totalsize += size; } mo = mn; getZipTable((ZT_entry*)gbuf_rptr(mn),i,j); @@ -600,9 +603,9 @@ int elap_wput(gref, m) if (!tabsize) { dPrintf(D_M_ELAP,D_L_WARNING, ("elap_wput:snmp: empty zip table\n")); - total = 0; + totalsize = 0; } - *(int*)gbuf_rptr(gbuf_cont(m)) = total; /* return table size */ + *(int*)gbuf_rptr(gbuf_cont(m)) = totalsize; /* return table size */ gbuf_wset(gbuf_cont(m),sizeof(int)); iocbp->ioc_count = sizeof(int); ioc_ack(0, m, gref); @@ -645,11 +648,11 @@ int elap_wput(gref, m) } if (!mo) { /* if first new one */ mt = mn; - total = size; + totalsize = size; } else { gbuf_cont(mo) = mn; - total += size; + totalsize += size; } mo = mn; getRtmpTable((RT_entry*)gbuf_rptr(mn),i,j); @@ -663,8 +666,8 @@ int elap_wput(gref, m) break; } if (!tabsize) - total = 0; - *(int*)gbuf_rptr(gbuf_cont(m)) = total; /* return table size */ + totalsize = 0; + *(int*)gbuf_rptr(gbuf_cont(m)) = totalsize; /* return table size */ gbuf_wset(gbuf_cont(m),sizeof(int)); iocbp->ioc_count = sizeof(int); ioc_ack(0, m, gref); @@ -711,7 +714,7 @@ int elap_wput(gref, m) } if (!mo) { /* if first new one */ mt = mn; - total = size; + totalsize = size; nbp = (snmpNbpTable_t*)gbuf_rptr(mn); nbp->nbpt_entries = tabsize; nbp->nbpt_zone = ifID_home->ifZoneName; @@ -719,7 +722,7 @@ int elap_wput(gref, m) } else { gbuf_cont(mo) = mn; - total += size; + totalsize += size; getNbpTable((snmpNbpEntry_t *)gbuf_rptr(mn),i,j); } mo = mn; @@ -733,8 +736,8 @@ int elap_wput(gref, m) break; } if (!tabsize) - total = 0; - *(int*)gbuf_rptr(gbuf_cont(m)) = total; /* return table size */ + totalsize = 0; + *(int*)gbuf_rptr(gbuf_cont(m)) = totalsize; /* return table size */ gbuf_wset(gbuf_cont(m),sizeof(int)); iocbp->ioc_count = sizeof(int); ioc_ack(0, m, gref); @@ -770,6 +773,7 @@ int elap_wput(gref, m) /* Called directly by ddp/zip. */ +int elap_dataput(m, elapp, addr_flag, addr) register gbuf_t *m; register at_ifaddr_t *elapp; @@ -777,11 +781,9 @@ elap_dataput(m, elapp, addr_flag, addr) char *addr; { register int size; - int error; - extern int zip_type_packet(); + int error = 0; struct etalk_addr dest_addr; struct atalk_addr dest_at_addr; - extern gbuf_t *growmsg(); int loop = TRUE; /* flag to aarp to loopback (default) */ @@ -855,10 +857,10 @@ elap_dataput(m, elapp, addr_flag, addr) * it doesn't know net#, consequently can't do * AMT_LOOKUP. That task left to aarp now. */ - error = aarp_send_data(m,elapp,&dest_at_addr, loop); + error = aarp_send_data(m, elapp, &dest_at_addr, loop); break; case ET_ADDR : - error = pat_output(elapp, m, &dest_addr, 0); + error = pat_output(elapp, m, (unsigned char *)&dest_addr, 0); break; } return (error); @@ -887,14 +889,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 */ @@ -943,9 +959,11 @@ static void elap_online2(elapp) /* LD 081694: set the RTR_SEED_PORT flag for seed ports */ elapp->ifFlags |= RTR_SEED_PORT; } +#if DEBUG else dPrintf(D_M_ELAP,D_L_STARTUP_INFO, ("elap_online: it's a router, but non seed\n")); +#endif } if (elapp->flags & ELAP_CFG_ZONELESS) { @@ -995,7 +1013,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 */ @@ -1009,10 +1028,6 @@ void elap_offline(elapp) register at_ifaddr_t *elapp; { - void zip_sched_getnetinfo(); /* forward reference */ - int errno; - int s; - dPrintf(D_M_ELAP, D_L_SHUTDN_INFO, ("elap_offline:%s\n", elapp->ifName)); if (elapp->ifState != LAP_OFFLINE) { @@ -1025,13 +1040,12 @@ void elap_offline(elapp) (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr); elapp->ifState = LAP_OFFLINE; - ATDISABLE(s, ddpinp_lock); if (MULTIPORT_MODE) RT_DELETE(elapp->ifThisCableEnd, elapp->ifThisCableStart); - ATENABLE(s, ddpinp_lock); /* make sure no zip timeouts are left running */ + elapp->ifGNIScheduled = 0; untimeout(zip_sched_getnetinfo, elapp); } ddp_rem_if(elapp); @@ -1080,11 +1094,8 @@ int ddp_shutdown(count_only) struct atp_state *atp, *atp_next; CCB *sp, *sp_next; gref_t *gref; - vm_offset_t temp_rcb_data, temp_state_data; - int i, s, active_skts = 0; /* count of active pids for non-socketized + int i, 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. @@ -1092,8 +1103,6 @@ int ddp_shutdown(count_only) sockets, but return EBUSY and don't complete shutdown. *** */ - s = splimp(); /* *** previously contained mismatched locking - that was ifdef'ed to splimp() *** */ if (!count_only) nbp_shutdown(); /* clear all known NVE */ @@ -1179,11 +1188,9 @@ int ddp_shutdown(count_only) atalk_notify(gref, ESHUTDOWN); } } - if (count_only || active_skts) { - splx(s); + if (count_only) return(active_skts); - } /* if there are no interfaces in the process of going online, continue shutting down DDP */ for (i = 0; i < IF_TOTAL_MAX; i++) { if (at_interfaces[i].startup_inprogress == TRUE) @@ -1235,30 +1242,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 +1250,7 @@ int routerStart(keP) { register at_ifaddr_t *ifID; int error; + struct timespec ts; if (! ifID_home) return(EINVAL); @@ -1290,12 +1274,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) @@ -1312,11 +1302,9 @@ void ZIPwakeup(elapp, ZipError) at_ifaddr_t *elapp; int ZipError; { - int s, error = ZipError; + int error = ZipError; - ATDISABLE(s, ddpinp_lock); if ( (elapp != NULL) && elapp->startup_inprogress) { - ATENABLE(s, ddpinp_lock); /* was ZIPContinue */ /* was elapp_online() with jump to ZIP_sleep */ @@ -1351,21 +1339,17 @@ void ZIPwakeup(elapp, ZipError) dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online: ifZipError=%d\n", error)); } - } else - ATENABLE(s, ddpinp_lock); + } } /* ZIPwakeup */ void AARPwakeup(probe_cb) aarp_amt_t *probe_cb; { - int s; int errno; at_ifaddr_t *elapp; - ATDISABLE(s, arpinp_lock); elapp = probe_cb->elapp; - if ( (elapp != NULL) && elapp->startup_inprogress ) { - ATENABLE(s, arpinp_lock); + if ( (elapp != NULL) && elapp->startup_inprogress && elapp->aa_ifp != 0) { /* was AARPContinue */ errno = aarp_init2(elapp); @@ -1387,8 +1371,7 @@ void AARPwakeup(probe_cb) ("elap_online: aarp_init returns zero\n")); elap_online2(elapp); } - } else - ATENABLE(s, arpinp_lock); + } } /* AARPwakeup */ void ddp_bit_reverse(addr) @@ -1435,6 +1418,8 @@ static unsigned char reverse_data[] = { addr[k] = reverse_data[addr[k]]; } +static int elap_trackMcast(at_ifaddr_t *, int, caddr_t); + static int elap_trackMcast(patp, func, addr) at_ifaddr_t *patp; int func; @@ -1444,7 +1429,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]; @@ -1512,7 +1499,7 @@ static int elap_trackMcast(patp, func, addr) } -static getSnmpCfg(snmp) +static int getSnmpCfg(snmp) snmpCfg_t *snmp; { int i; @@ -1526,11 +1513,13 @@ static getSnmpCfg(snmp) iifState != LAP_OFFLINE) { snmp->cfg_ifCnt++; - strncpy(ifc->ifc_name,elapp->ifName, sizeof(ifc->ifc_name)); + strlcpy(ifc->ifc_name,elapp->ifName, sizeof(ifc->ifc_name)); ifc->ifc_aarpSize = getAarpTableSize(i); 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 +1575,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 +1587,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, (struct sockaddr *)&sdl, 0)) return -1; } return 0; @@ -1619,7 +1614,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 +1625,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 +1641,7 @@ int at_unreg_mcast(ifID, data) (unsigned)ifID)); bzero(data, sizeof(struct etalk_addr)); - if (if_delmulti(nddp, &sa)) + if (if_delmulti(nddp, (struct sockaddr *)&sdl)) return -1; } return 0;