1/* 2 * Copyright (c) 2000-2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1988, 1989, 1993-1998 Apple Computer, Inc. 30 */ 31 32/* at_elap.c: 2.0, 1.29; 10/4/93; Apple Computer, Inc. */ 33 34/* This is the file which implements all the streams driver 35 * functionality required for EtherTalk. 36 */ 37 38/* revision history 39 40 03-14-94 jjs Changed all functions which assumed only one port would 41 ever be used. Added validate_msg_size, changed elap_online 42 to work with the h/w name only (e.g. 'et2'). 43 44 Modified for MP, 1996 by Tuyen Nguyen 45 Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. 46 47*/ 48 49#define RESOLVE_DBG /* for debug.h global resolution */ 50#include <sys/errno.h> 51#include <sys/types.h> 52#include <sys/param.h> 53#include <machine/spl.h> 54#include <sys/systm.h> 55#include <sys/kernel.h> 56#include <sys/proc.h> 57#include <sys/filedesc.h> 58#include <sys/fcntl.h> 59#include <sys/mbuf.h> 60#include <sys/ioctl.h> 61#include <sys/socket.h> 62#include <net/if_dl.h> 63#include <sys/socketvar.h> 64#include <sys/malloc.h> 65#include <sys/domain.h> 66#include <sys/sockio.h> 67#include <vm/vm_kern.h> /* for kernel_map */ 68 69 70#include <net/if.h> 71#include <net/if_types.h> 72 73#include <netat/sysglue.h> 74#include <netat/appletalk.h> 75#include <netat/at_pcb.h> 76#include <netat/at_var.h> 77#include <netat/ddp.h> 78#include <netat/lap.h> 79#include <netat/routing_tables.h> /* rtmp+zip table structs */ 80#include <netat/zip.h> 81#include <netat/nbp.h> 82#include <netat/at_snmp.h> 83#include <netat/at_aarp.h> 84#include <netat/asp.h> 85#include <netat/atp.h> 86#include <netat/debug.h> 87#include <netat/adsp.h> 88#include <netat/adsp_internal.h> 89#include <netat/at_pat.h> 90#include <netat/rtmp.h> 91 92#include <sys/kern_event.h> 93 94/* globals */ 95 96at_ifaddr_t at_interfaces[IF_TOTAL_MAX]; 97 /* index for at_interfaces is not important */ 98at_ifaddr_t *ifID_table[IF_TOTAL_MAX]; 99 /* the table of ifID structures, one per interface 100 (not just ethernet), 101 * NOTE: for MH, entry 0 in this table is 102 * now defined to be the default I/F 103 */ 104at_ifaddr_t *ifID_home; 105 /* always ifID_table[IFID_HOME] for now, but will be used for 106 dynamic "home port" assignment, later */ 107 108at_state_t at_state; /* global state of AT network */ 109snmpFlags_t snmpFlags; 110 111int xpatcnt = 0; 112 113/* snmp defines */ 114#define MAX_BUFSIZE 8192 115#define MAX_RTMP (MAX_BUFSIZE/sizeof(RT_entry)-1) 116#define MAX_NBP \ 117 ((MAX_BUFSIZE - SNMP_NBP_HEADER_SIZE)/sizeof(snmpNbpEntry_t)-1) 118#define MAX_NBP_BYTES (MAX_NBP * sizeof(snmpNbpEntry_t)) 119#define MAX_ZIP (MAX_BUFSIZE/sizeof(ZT_entry)-1) 120#define MAX_RTMP_BYTES (MAX_RTMP * sizeof(RT_entry)) 121#define MAX_ZIP_BYTES (MAX_ZIP * sizeof(ZT_entry)) 122 123/* externs */ 124extern TAILQ_HEAD(name_registry, _nve_) name_registry; 125extern snmpStats_t snmpStats; 126extern short appletalk_inited; 127extern int adspInited; 128extern struct atpcb ddp_head; 129extern gref_t *atp_inputQ[]; 130extern struct atp_state *atp_used_list; 131extern asp_scb_t *asp_scbQ[]; 132extern asp_scb_t *scb_used_list; 133extern CCB *adsp_inputQ[]; 134extern CCB *ccb_used_list; 135extern at_ddp_stats_t at_ddp_stats; 136extern lck_mtx_t * atalk_mutex; 137 138/* protos */ 139int rtmp_router_start(at_kern_err_t *); 140static void add_route(RT_entry *); 141void elap_offline(at_ifaddr_t *); 142static int elap_online1(at_ifaddr_t *); 143static void elap_online2(at_ifaddr_t *); 144 int elap_online3(at_ifaddr_t *); 145static int re_aarp(at_ifaddr_t *); 146static int getSnmpCfg(snmpCfg_t *); 147 148int routerStart(at_kern_err_t *); 149 150static int validate_msg_size(gbuf_t *, gref_t *, at_ifaddr_t **); 151at_ifaddr_t *find_ifID(char *); 152int lap_online( at_ifaddr_t *, at_if_cfg_t *cfgp); 153 154 155at_ifaddr_t *find_ifID(if_name) 156 char *if_name; 157{ 158 int pat_id; 159 160 if (strlen(if_name)) 161 for (pat_id=0; pat_id < xpatcnt; pat_id++) { 162 if (!strcmp(at_interfaces[pat_id].ifName, if_name)) 163 return(&at_interfaces[pat_id]); 164 } 165 166 return((at_ifaddr_t *)NULL); 167} 168 169static int validate_msg_size(m, gref, elapp) 170 register gbuf_t *m; 171 gref_t *gref; 172 at_ifaddr_t **elapp; 173 174/* checks ioctl message type for minimum expected message size & 175 sends error back if size invalid 176*/ 177{ 178 register ioc_t *iocbp; 179 int i = 0, size = 1; 180 181 *elapp = NULL; 182 iocbp = (ioc_t *) gbuf_rptr(m); 183 184 dPrintf(D_M_ELAP, D_L_INFO, ("validate_msg_size: ioc_cmd = %d\n", 185 iocbp->ioc_cmd)); 186 switch (iocbp->ioc_cmd) { 187 case LAP_IOC_ADD_ROUTE: 188 size = sizeof(RT_entry); 189 break; 190 case LAP_IOC_GET_ROUTE: 191 size = sizeof(RT_entry); 192 break; 193 case LAP_IOC_GET_ZONE: 194 size = sizeof(ZT_entryno); 195 break; 196 case LAP_IOC_SNMP_GET_CFG: 197 case LAP_IOC_SNMP_GET_AARP: 198 case LAP_IOC_SNMP_GET_ZIP: 199 case LAP_IOC_SNMP_GET_RTMP: 200 case LAP_IOC_SNMP_GET_NBP: 201 size = sizeof(int); 202 break; 203 204 case ELAP_IOC_GET_STATS: 205 case LAP_IOC_SNMP_GET_DDP: 206 size = 0; 207 break; 208 209 default: 210 dPrintf(D_M_ELAP, D_L_ERROR, ("validate_msg_size: unknown ioctl\n")); 211 goto error; 212 } 213 214 if (size == 0) { /* a non-data ioctl */ 215 return(0); 216 } 217 218 if (gbuf_cont(m) != NULL) 219 i = gbuf_len(gbuf_cont(m)); 220 if (iocbp->ioc_count < size || (gbuf_cont(m) == NULL) || i < size) { 221 dPrintf(D_M_ELAP, D_L_ERROR, 222 ("ioctl msg error:s:%d c:%d bcont:%c delta:%d\n", 223 size, iocbp->ioc_count, 224 gbuf_cont(m)? 'Y' : 'N', i)); 225 goto error; 226 } 227 else 228 return(0); 229error: 230 ioc_ack(EMSGSIZE, m, gref); 231 return (EMSGSIZE); 232} /* validate_msg_size */ 233 234int lap_online(elapp, cfgp) 235 at_ifaddr_t *elapp; 236 at_if_cfg_t *cfgp; 237{ 238 int error; 239 240 if (elapp->ifState != LAP_OFFLINE) { 241 return(EALREADY); 242 } 243 244 elapp->flags = 0; 245 if (cfgp->flags & ELAP_CFG_HOME) { 246 if (ifID_home) { 247 /* only 1 home allowed! */ 248 return(EEXIST); 249 } 250 dPrintf(D_M_ELAP, D_L_STARTUP, 251 ("elap_wput home I/F:%s\n", cfgp->ifr_name)); 252 elapp->flags |= ELAP_CFG_HOME; 253 } 254 255 if (MULTIPORT_MODE) { 256 elapp->flags |= ELAP_CFG_ZONELESS; 257 if (ROUTING_MODE && cfgp->netStart) 258 elapp->flags |= ELAP_CFG_SEED; 259 } 260 261 /* (VL) !? */ 262 if ((!DEFAULT_ZONE(&cfgp->zonename) && 263 (elapp->flags & ELAP_CFG_HOME)) || MULTIHOME_MODE) { 264 elapp->startup_zone = cfgp->zonename; 265 } 266 267 if (elapp->flags & ELAP_CFG_SEED) { 268 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, 269 ("elap_wput: found to be seed\n")); 270 elapp->ifThisCableStart = cfgp->netStart; 271 elapp->ifThisCableEnd = cfgp->netEnd; 272 } 273 else { 274 dPrintf(D_M_ELAP,D_L_ERROR, 275 ("elap_wput: we believe we're not seed\n")); 276 /* from ELAP_IOC_SET_CFG */ 277 if (ATALK_VALUE(cfgp->node)) { 278 u_short initial_net; 279 u_char initial_node; 280 281 initial_node = cfgp->node.s_node; 282 initial_net = cfgp->node.s_net; 283 if ((initial_node<0xfe) && (initial_node>0) && 284 !((initial_net == 0) || 285 ((initial_net >= DDP_STARTUP_LOW)&& 286 (initial_net <= DDP_STARTUP_HIGH)))) { 287 288 elapp->initial_addr = cfgp->node; 289 } 290 } 291 } 292 293 elapp->startup_error = 0; 294 elapp->startup_inprogress = FALSE; 295 if ((error = elap_online1(elapp))) 296 ddp_rem_if(elapp); 297 else 298 if (!(MULTIPORT_MODE) && 299 elapp->ifZoneName.len == 1 && 300 elapp->ifZoneName.str[0] == '*' && 301 !DEFAULT_ZONE(&cfgp->zonename)) { 302 nbp_add_multicast(&cfgp->zonename, elapp); 303 } 304 return(error); 305} /* lap_online */ 306 307/*********************************************************************** 308 * elap_wput() 309 * 310 **********************************************************************/ 311int elap_wput(gref, m) 312 gref_t *gref; 313 register gbuf_t *m; 314{ 315 at_ifaddr_t *elapp; 316 register ioc_t *iocbp; 317 register at_if_cfg_t *cfgp; 318 at_elap_stats_t *statsp; 319 int i,j; 320 int size, totalsize = 0, tabsize; 321 gbuf_t *mn; /* new gbuf */ 322 gbuf_t *mo; /* old gbuf */ 323 gbuf_t *mt = NULL; /* temp */ 324 snmpNbpTable_t *nbp; 325 326 327 switch (gbuf_type(m)) { 328 case MSG_DATA: 329 gbuf_freem(m); 330 dPrintf(D_M_ELAP,D_L_ERROR, 331 ("Output data to control channel is ignored\n")); 332 break; 333 334 case MSG_IOCTL: 335 iocbp = (ioc_t *) gbuf_rptr(m); 336 337 if (validate_msg_size(m, gref, &elapp)) 338 break; 339 340 if (elapp) 341 cfgp = (at_if_cfg_t*) gbuf_rptr(gbuf_cont(m)); 342 343 if (LAP_IOC_MYIOCTL(iocbp->ioc_cmd) || 344 ELAP_IOC_MYIOCTL(iocbp->ioc_cmd)) { 345 346 switch (iocbp->ioc_cmd) { 347 case ELAP_IOC_GET_STATS: 348#ifdef APPLETALK_DEBUG 349 kprintf("LAP_IOC_GET_STATS\n"); 350#endif 351 if ( (gbuf_cont(m) == NULL) 352 || (elapp = find_ifID(gbuf_rptr(gbuf_cont(m)))) == NULL) { 353 ioc_ack(EINVAL, m, gref); 354 break; 355 } 356 gbuf_freem(gbuf_cont(m)); 357 if ((gbuf_cont(m) =gbuf_alloc(sizeof(at_elap_stats_t), 358 PRI_MED)) == NULL) { 359 ioc_ack(ENOBUFS, m, gref); 360 break; 361 } 362 statsp = ((at_elap_stats_t *)gbuf_rptr(gbuf_cont(m))); 363 *statsp = elapp->stats; 364 gbuf_wset(gbuf_cont(m),sizeof(at_elap_stats_t)); 365 iocbp->ioc_count = sizeof(at_elap_stats_t); 366 ioc_ack(0, m, gref); 367 break; 368 369 case LAP_IOC_ADD_ROUTE: 370#ifdef APPLETALK_DEBUG 371 kprintf("LAP_IOC_ADD_ROUTE\n"); 372#endif 373 add_route((RT_entry *)gbuf_rptr(gbuf_cont(m))); 374 ioc_ack(0, m, gref); 375 break; 376 377 case LAP_IOC_GET_ZONE: 378#ifdef APPLETALK_DEBUG 379 kprintf("LAP_IOC_GET_ZONE\n"); 380#endif 381 /* return next ZT_entryno from ZT_table 382 a pointer to the struct ZT_entryno is passed down from 383 user space and the first byte is cast to a int, if 384 this int is non-zero, then the first ZT_entry is 385 returned and subsequent calls with a zero value 386 will return the next entry in the table. The next 387 read after the last valid entry will return EINVAL 388 */ 389 { 390 ZT_entryno *pZTe; 391 392 i = *(int *)gbuf_rptr(gbuf_cont(m)); 393 gbuf_freem(gbuf_cont(m)); 394 gbuf_cont(m) = NULL; 395 396 pZTe = zt_getNextZone(i); 397 if (pZTe) { 398 if ((gbuf_cont(m) = gbuf_alloc(sizeof(ZT_entryno), PRI_MED)) == NULL) { 399 ioc_ack(ENOBUFS, m, gref); 400 break; 401 } 402 *(ZT_entryno *)gbuf_rptr(gbuf_cont(m)) = *pZTe; 403 gbuf_wset(gbuf_cont(m),sizeof(ZT_entryno)); 404 iocbp->ioc_count = sizeof(ZT_entryno); 405 ioc_ack(0, m, gref); 406 } 407 else 408 ioc_ack(EINVAL, m, gref); 409 } 410 break; 411 412 case LAP_IOC_GET_ROUTE: 413#ifdef APPLETALK_DEBUG 414 kprintf("LAP_IOC_GET_ROUTE\n"); 415#endif 416 /* return next RT_entry from RT_table 417 * a pointer to the struct RT_entry is 418 * passed down from user space and the first 419 * byte is cast to a int, if this int is 420 * non-zero, then the first RT_entry is 421 * returned and subsequent calls with a 422 * zero value will return the next entry in 423 * the table. The next read after the last 424 * valid entry will return EINVAL 425 */ 426 { 427 RT_entry *pRT; 428 429 i = *(int *)gbuf_rptr(gbuf_cont(m)); 430 gbuf_freem(gbuf_cont(m)); 431 gbuf_cont(m) = NULL; 432 433 pRT = rt_getNextRoute(i); 434 if (pRT) { 435 if ((gbuf_cont(m) = gbuf_alloc(sizeof(RT_entry), PRI_MED)) == NULL) { 436 ioc_ack(ENOBUFS, m, gref); 437 break; 438 } 439 *(RT_entry *)gbuf_rptr(gbuf_cont(m)) = *pRT; 440 gbuf_wset(gbuf_cont(m),sizeof(RT_entry)); 441 iocbp->ioc_count = sizeof(RT_entry); 442 ioc_ack(0, m, gref); 443 } 444 else 445 ioc_ack(EINVAL, m, gref); 446 } 447 break; 448 449 case LAP_IOC_SNMP_GET_DDP: 450#ifdef APPLETALK_DEBUG 451 kprintf("LAP_IOC_SNMP_GET_DDP\n"); 452#endif 453 if (!(at_state.flags & AT_ST_STARTED)) { 454 ioc_ack(ENOTREADY, m, gref); 455 break; 456 } 457 if ((gbuf_cont(m) = gbuf_alloc(sizeof(snmpStats_t), 458 PRI_MED)) == NULL) { 459 ioc_ack(ENOBUFS, m, gref); 460 break; 461 } 462 463 *(snmpStats_t *)gbuf_rptr(gbuf_cont(m)) = snmpStats; 464 gbuf_wset(gbuf_cont(m),sizeof(snmpStats)); 465 iocbp->ioc_count = sizeof(snmpStats); 466 ioc_ack(0, m, gref); 467 break; 468 case LAP_IOC_SNMP_GET_CFG: 469#ifdef APPLETALK_DEBUG 470 kprintf("LAP_IOC_SNMP_GET_CFG\n"); 471#endif 472 { 473 snmpCfg_t snmp; 474 475 i = *(int *)gbuf_rptr(gbuf_cont(m)); 476 gbuf_freem(gbuf_cont(m)); 477 gbuf_cont(m) = NULL; 478 if (!(at_state.flags & AT_ST_STARTED)) { 479 /* if stack down */ 480 iocbp->ioc_count = 0; 481 ioc_ack(ENOTREADY, m, gref); 482 dPrintf(D_M_ELAP_LOW, D_L_INFO, 483 ("elap_wput: cfg req, stack down\n")); 484 break; 485 } 486 if (i == UPDATE_IF_CHANGED && 487 !(at_state.flags & AT_ST_IF_CHANGED)) { 488 iocbp->ioc_count = 0; 489 ioc_ack(0, m, gref); 490 dPrintf(D_M_ELAP_LOW, D_L_INFO, 491 ("elap_wput: cfg req, unchanged\n")); 492 break; 493 } 494 dPrintf(D_M_ELAP_LOW, D_L_INFO, 495 ("elap_wput: cfg req, changed\n")); 496 497 if (getSnmpCfg(&snmp)) { 498 dPrintf(D_M_ELAP,D_L_ERROR, 499 ("elap_wput:SNMP_GET_CFG error\n")); 500 ioc_ack(EOPNOTSUPP, m, gref); 501 break; 502 } 503 /* send up only used part of table */ 504 size = sizeof(snmp) - 505 sizeof(snmpIfCfg_t) * (MAX_IFS - snmp.cfg_ifCnt); 506 507 if ((gbuf_cont(m) = gbuf_alloc(size, PRI_MED)) == NULL) { 508 ioc_ack(ENOBUFS, m, gref); 509 break; 510 } 511 bcopy(&snmp,gbuf_rptr(gbuf_cont(m)),size); 512 gbuf_wset(gbuf_cont(m),size); 513 iocbp->ioc_count = size; 514 at_state.flags &= ~AT_ST_IF_CHANGED; 515 ioc_ack(0, m, gref); 516 } 517 break; 518 519 case LAP_IOC_SNMP_GET_AARP: 520 { 521 snmpAarpEnt_t *snmpp; 522 int bytes; 523#ifdef APPLETALK_DEBUG 524 kprintf("LAP_IOC_SNMP_GET_AARP\n"); 525#endif 526 i = *(int *)gbuf_rptr(gbuf_cont(m)); 527 gbuf_freem(gbuf_cont(m)); 528 gbuf_cont(m) = NULL; 529 dPrintf(D_M_ELAP,D_L_INFO, 530 ("elap_wput:calling getarp,i=%d\n", i)); 531 snmpp = getAarp(&i); 532 bytes = i * sizeof(snmpAarpEnt_t); 533 dPrintf(D_M_ELAP,D_L_INFO, 534 ("elap_wput:getarp returned, i=%d,bytes=%d\n", 535 i, bytes)); 536 if (snmpp) { 537 if ((gbuf_cont(m) = gbuf_alloc(bytes, PRI_MED)) == NULL) { 538 ioc_ack(ENOBUFS, m, gref); 539 break; 540 } 541 bcopy(snmpp, gbuf_rptr(gbuf_cont(m)), bytes); 542 gbuf_wset(gbuf_cont(m),bytes); 543 iocbp->ioc_count = bytes; 544 ioc_ack(0, m, gref); 545 } 546 else 547 ioc_ack(EOPNOTSUPP, m, gref); 548 } 549 break; 550 551 case LAP_IOC_SNMP_GET_ZIP: 552#ifdef APPLETALK_DEBUG 553 kprintf("LAP_IOC_SNMP_GET_ZIP\n"); 554#endif 555 { /* matching brace NOT in this case */ 556 557 i = *(int *)gbuf_rptr(gbuf_cont(m)); 558 gbuf_freem(gbuf_cont(m)); 559 gbuf_cont(m) = NULL; 560 if (!(at_state.flags & AT_ST_STARTED)) { 561 ioc_ack(ENOTREADY, m, gref); 562 break; 563 } 564 if (i == UPDATE_IF_CHANGED && 565 !(at_state.flags & AT_ST_ZT_CHANGED)) { 566 iocbp->ioc_count = 0; 567 ioc_ack(0, m, gref); 568 break; 569 } 570 mo=(gbuf_t*)NULL; 571 tabsize = getZipTableSize(); 572 573 /* retrieve table into multiple gbufs */ 574 for (i =0; i<tabsize; i+=j) { 575 j = tabsize - i > 576 MAX_ZIP ? MAX_ZIP : tabsize - i; 577 size = j < MAX_ZIP ? sizeof(ZT_entry)*j : MAX_ZIP_BYTES; 578 if ((mn = gbuf_alloc(size, PRI_MED)) == NULL) { 579 if (gbuf_cont(m)) 580 gbuf_freem(gbuf_cont(m)); 581 ioc_ack(ENOBUFS, m, gref); 582 break; 583 } 584 if (!mo) { /* if first new one */ 585 mt = mn; 586 totalsize = size; 587 } 588 else { 589 gbuf_cont(mo) = mn; 590 totalsize += size; 591 } 592 mo = mn; 593 getZipTable((ZT_entry*)gbuf_rptr(mn),i,j); 594 gbuf_wset(mn,size); 595 } 596 if ((gbuf_cont(m) = gbuf_alloc(sizeof(int), PRI_MED)) == NULL) { 597 if (mt) 598 gbuf_freem(mt); 599 iocbp->ioc_count = 0; 600 ioc_ack(ENOBUFS, m, gref); 601 break; 602 } 603 if (!tabsize) { 604 dPrintf(D_M_ELAP,D_L_WARNING, 605 ("elap_wput:snmp: empty zip table\n")); 606 totalsize = 0; 607 } 608 *(int*)gbuf_rptr(gbuf_cont(m)) = totalsize; /* return table size */ 609 gbuf_wset(gbuf_cont(m),sizeof(int)); 610 iocbp->ioc_count = sizeof(int); 611 ioc_ack(0, m, gref); 612 if (tabsize) 613 atalk_putnext(gref,mt); /* send up table */ 614 at_state.flags &= ~AT_ST_ZT_CHANGED; 615 break; 616 617 case LAP_IOC_SNMP_GET_RTMP: 618#ifdef APPLETALK_DEBUG 619 kprintf("LAP_IOC_SNMP_GET_RTMP\n"); 620#endif 621 i = *(int *)gbuf_rptr(gbuf_cont(m)); 622 gbuf_freem(gbuf_cont(m)); 623 gbuf_cont(m) = NULL; 624 if (!(at_state.flags & AT_ST_STARTED)) { 625 ioc_ack(ENOTREADY, m, gref); 626 break; 627 } 628 if (i == UPDATE_IF_CHANGED && 629 !(at_state.flags & AT_ST_RT_CHANGED)) { 630 iocbp->ioc_count = 0; 631 ioc_ack(0, m, gref); 632 break; 633 } 634 635 mo=(gbuf_t*)NULL; 636 tabsize = getRtmpTableSize(); 637 638 /* retrieve table into multiple gbufs */ 639 for (i =0; i<tabsize; i+=j) { 640 j = tabsize - i > 641 MAX_RTMP ? MAX_RTMP : tabsize - i; 642 size = j < MAX_RTMP ? sizeof(RT_entry)*j : MAX_RTMP_BYTES; 643 if ((mn = gbuf_alloc(size, PRI_MED)) == NULL) { 644 if (gbuf_cont(m)) 645 gbuf_freem(gbuf_cont(m)); 646 ioc_ack(ENOBUFS, m, gref); 647 break; 648 } 649 if (!mo) { /* if first new one */ 650 mt = mn; 651 totalsize = size; 652 } 653 else { 654 gbuf_cont(mo) = mn; 655 totalsize += size; 656 } 657 mo = mn; 658 getRtmpTable((RT_entry*)gbuf_rptr(mn),i,j); 659 gbuf_wset(mn,size); 660 } 661 if ((gbuf_cont(m) = gbuf_alloc(sizeof(int), PRI_MED)) == NULL) { 662 if (mt) 663 gbuf_freem(mt); 664 iocbp->ioc_count = 0; 665 ioc_ack(ENOBUFS, m, gref); 666 break; 667 } 668 if (!tabsize) 669 totalsize = 0; 670 *(int*)gbuf_rptr(gbuf_cont(m)) = totalsize; /* return table size */ 671 gbuf_wset(gbuf_cont(m),sizeof(int)); 672 iocbp->ioc_count = sizeof(int); 673 ioc_ack(0, m, gref); 674 if (tabsize) 675 atalk_putnext(gref,mt); /* send up table */ 676 at_state.flags &= ~AT_ST_RT_CHANGED; 677 break; 678 679 case LAP_IOC_SNMP_GET_NBP: 680#ifdef APPLETALK_DEBUG 681 kprintf("LAP_IOC_SNMP_GET_NBP\n"); 682#endif 683 i = *(int *)gbuf_rptr(gbuf_cont(m)); 684 gbuf_freem(gbuf_cont(m)); 685 gbuf_cont(m) = NULL; 686 if (!(at_state.flags & AT_ST_STARTED)) { 687 ioc_ack(ENOTREADY, m, gref); 688 break; 689 } 690 if (i == UPDATE_IF_CHANGED && 691 !(at_state.flags & AT_ST_NBP_CHANGED)) { 692 iocbp->ioc_count = 0; 693 ioc_ack(0, m, gref); 694 dPrintf(D_M_ELAP_LOW, D_L_INFO, 695 ("elap_wput: nbp req denied, no change\n")); 696 break; 697 } 698 699 mo=(gbuf_t*)NULL; 700 tabsize = getNbpTableSize(); 701 702 /* retrieve table into multiple gbufs */ 703 for (i =0; i<tabsize; i+=j) { 704 j = tabsize - i > 705 MAX_NBP ? MAX_NBP : tabsize - i; 706 size = j < MAX_NBP ? sizeof(snmpNbpEntry_t)*j : MAX_NBP_BYTES; 707 if (!i) 708 size += SNMP_NBP_HEADER_SIZE; 709 if ((mn = gbuf_alloc(size, PRI_MED)) == NULL) { 710 if (gbuf_cont(m)) 711 gbuf_freem(gbuf_cont(m)); 712 ioc_ack(ENOBUFS, m, gref); 713 break; 714 } 715 if (!mo) { /* if first new one */ 716 mt = mn; 717 totalsize = size; 718 nbp = (snmpNbpTable_t*)gbuf_rptr(mn); 719 nbp->nbpt_entries = tabsize; 720 nbp->nbpt_zone = ifID_home->ifZoneName; 721 getNbpTable(nbp->nbpt_table,i,j); 722 } 723 else { 724 gbuf_cont(mo) = mn; 725 totalsize += size; 726 getNbpTable((snmpNbpEntry_t *)gbuf_rptr(mn),i,j); 727 } 728 mo = mn; 729 gbuf_wset(mn,size); 730 } 731 if ((gbuf_cont(m) = gbuf_alloc(sizeof(int), PRI_MED)) == NULL) { 732 if (mt) 733 gbuf_freem(mt); 734 iocbp->ioc_count = 0; 735 ioc_ack(ENOBUFS, m, gref); 736 break; 737 } 738 if (!tabsize) 739 totalsize = 0; 740 *(int*)gbuf_rptr(gbuf_cont(m)) = totalsize; /* return table size */ 741 gbuf_wset(gbuf_cont(m),sizeof(int)); 742 iocbp->ioc_count = sizeof(int); 743 ioc_ack(0, m, gref); 744 if (tabsize) 745 atalk_putnext(gref,mt); /* send up table */ 746 at_state.flags &= ~AT_ST_NBP_CHANGED; 747 break; 748 } 749 750 default: 751#ifdef APPLETALK_DEBUG 752 kprintf("unknown ioctl %d\n", iocbp->ioc_cmd); 753#endif 754 ioc_ack(ENOTTY, m, gref); 755 dPrintf(D_M_ELAP, D_L_WARNING, 756 ("elap_wput: unknown ioctl (%d)\n", iocbp->ioc_cmd)); 757 758 if (elapp) 759 elapp->stats.unknown_mblks++; 760 break; 761 } 762 } 763 break; 764 765 default: 766 gbuf_freem(m); 767 break; 768 } 769 770 return 0; 771} /* elap_wput */ 772 773 774/* Called directly by ddp/zip. 775 */ 776int 777elap_dataput(m, elapp, addr_flag, addr) 778 register gbuf_t *m; 779 register at_ifaddr_t *elapp; 780 u_char addr_flag; 781 char *addr; 782{ 783 register int size; 784 int error = 0; 785 struct etalk_addr dest_addr; 786 struct atalk_addr dest_at_addr; 787 int loop = TRUE; 788 /* flag to aarp to loopback (default) */ 789 790 /* the incoming frame is of the form {flag, address, ddp...} 791 * where "flag" indicates whether the address is an 802.3 792 * (link) address, or an appletalk address. If it's an 793 * 802.3 address, the packet can just go out to the network 794 * through PAT, if it's an appletalk address, AT->802.3 address 795 * resolution needs to be done. 796 * If 802.3 address is known, strip off the flag and 802.3 797 * address, and prepend 802.2 and 802.3 headers. 798 */ 799 800 if (addr == NULL) { 801 addr_flag = *(u_char *)gbuf_rptr(m); 802 gbuf_rinc(m,1); 803 } 804 805 switch (addr_flag) { 806 case AT_ADDR_NO_LOOP : 807 loop = FALSE; 808 /* pass thru */ 809 case AT_ADDR : 810 if (addr == NULL) { 811 dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m); 812 gbuf_rinc(m,sizeof(struct atalk_addr)); 813 } else 814 dest_at_addr = *(struct atalk_addr *)addr; 815 break; 816 case ET_ADDR : 817 if (addr == NULL) { 818 dest_addr = *(struct etalk_addr *)gbuf_rptr(m); 819 gbuf_rinc(m,sizeof(struct etalk_addr)); 820 } else 821 dest_addr = *(struct etalk_addr *)addr; 822 break; 823 default : 824 gbuf_freel(m); /* unknown address type, chuck it */ 825 return(EINVAL); 826 } 827 828 m = gbuf_strip(m); 829 830 /* At this point, rptr points to ddp header for sure */ 831 if (elapp->ifState == LAP_OFFLINE) { 832 gbuf_freel(m); 833 return(ENETDOWN); 834 } 835 836 if (elapp->ifState == LAP_ONLINE_FOR_ZIP) { 837 /* see if this is a ZIP packet that we need 838 * to let through even though network is 839 * not yet alive!! 840 */ 841 if (zip_type_packet(m) == 0) { 842 gbuf_freel(m); 843 return(ENETDOWN); 844 } 845 } 846 847 elapp->stats.xmit_packets++; 848 size = gbuf_msgsize(m); 849 elapp->stats.xmit_bytes += size; 850 snmpStats.dd_outLong++; 851 852 switch (addr_flag) { 853 case AT_ADDR_NO_LOOP : 854 case AT_ADDR : 855 /* 856 * we don't want elap to be looking into ddp header, so 857 * it doesn't know net#, consequently can't do 858 * AMT_LOOKUP. That task left to aarp now. 859 */ 860 error = aarp_send_data(m, elapp, &dest_at_addr, loop); 861 break; 862 case ET_ADDR : 863 error = pat_output(elapp, m, (unsigned char *)&dest_addr, 0); 864 break; 865 } 866 return (error); 867} /* elap_dataput */ 868 869/************************************************************************ 870 * elap_online() 871 * 872 ************************************************************************/ 873 874static int elap_online1(elapp) 875 at_ifaddr_t *elapp; 876{ 877 int errno; 878 879 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online:%s elapp:0x%x\n", 880 (elapp->ifName) ? &elapp->ifName[0] : "NULL interface", (u_int) elapp)); 881 if (elapp->ifState != LAP_OFFLINE || elapp->startup_inprogress == TRUE) 882 return (EALREADY); 883 884 at_state.flags |= AT_ST_IF_CHANGED; 885 886 if (elapp->flags & ELAP_CFG_HOME) /* tell ddp_add_if if this is home */ 887 elapp->ifFlags |= AT_IFF_DEFAULT; 888 889 /* Get DDP started */ 890 if ((errno = ddp_add_if(elapp))) 891 return(errno); 892 893 // check if we still have an interface - can be lost when 894 // ddp_add_if calls malloc 895 // need to make check here after ddp_add_if completes because 896 // lap_online will call ddp_rem_if if we fail here 897 if (elapp->aa_ifp == 0) 898 return ENOENT; 899 900 /* set up multicast address for cable-wide broadcasts */ 901 (void)at_reg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr); 902 903 // need to check again if interface is present 904 // can be lost in at_reg_mcast 905 if (elapp->aa_ifp == 0) 906 return ENOENT; 907 908 elapp->startup_inprogress = TRUE; 909 if (! (elapp->startup_error = re_aarp(elapp))) { 910 lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED); 911 (void)msleep(&elapp->startup_inprogress, atalk_mutex, PSOCK | PCATCH, 912 "elap_online1", 0); 913 } 914 915 /* then later, after some timeouts AARPwakeup() is called */ 916 917 return(elapp->startup_error); 918} /* elap_online1 */ 919 920static int re_aarp(elapp) 921 at_ifaddr_t *elapp; 922{ 923 int errno; 924 925 /* We now call aarp_init() to assign an appletalk node addr */ 926 errno = aarp_init1(elapp); 927 /* aarp_init1() returns either -1 or ENOTREADY */ 928 if (errno == ENOTREADY) 929 return(0); 930 else { 931 dPrintf(D_M_ELAP, D_L_STATE_CHG, 932 ("elap_online aarp_init for %s\n", elapp->ifName)); 933 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr); 934 ddp_rem_if(elapp); 935 elapp->ifState = LAP_OFFLINE; 936 return(EADDRNOTAVAIL); 937 } 938} 939 940/* called from AARPwakeup */ 941static void elap_online2(elapp) 942 at_ifaddr_t *elapp; 943{ 944 if (MULTIPORT_MODE) { 945 dPrintf(D_M_ELAP,D_L_STARTUP_INFO, 946 ("elap_online: re_aarp, we know it's a router...\n")); 947 948 if (elapp->flags & ELAP_CFG_SEED) { 949 /* add route table entry (zones to be added later) */ 950 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, 951 ("elap_online: rt_insert Cable %d-%d port =%d as SEED\n", 952 elapp->ifThisCableStart, elapp->ifThisCableEnd, elapp->ifPort)); 953 rt_insert(elapp->ifThisCableEnd, 954 elapp->ifThisCableStart, 955 0,0,0, 956 elapp->ifPort, 957 RTE_STATE_PERMANENT | RTE_STATE_ZKNOWN | RTE_STATE_GOOD 958 ); 959 /* LD 081694: set the RTR_SEED_PORT flag for seed ports */ 960 elapp->ifFlags |= RTR_SEED_PORT; 961 } 962#if DEBUG 963 else 964 dPrintf(D_M_ELAP,D_L_STARTUP_INFO, 965 ("elap_online: it's a router, but non seed\n")); 966#endif 967 } 968 969 if (elapp->flags & ELAP_CFG_ZONELESS) { 970 /* ELAP_CFG_ZONELESS tells us that it is a router or in 971 multihome mode, so we don't want to do the GetNetInfo 972 exchange with the router. */ 973 974 elapp->ifState = LAP_ONLINE_ZONELESS; 975 elapp->startup_inprogress = FALSE; 976 wakeup(&elapp->startup_inprogress); 977 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online: ack 3\n")); 978 return; 979 } 980 981 /* if we don't already have a zone and a multicast address */ 982 if (*(int *)&elapp->ZoneMcastAddr == 0 || elapp->ifZoneName.len == 0) { 983 /* hzonehash is a global containing the nbp hash for the startup_zone */ 984 sethzonehash(elapp); 985 986 /* Get ZIP rolling to get zone multicast address, etc. */ 987 elapp->ifState = LAP_ONLINE_FOR_ZIP; 988 (void)zip_control(elapp, ZIP_ONLINE); 989 /* zip_control (w. control == ZIP_ONLINE) always returns ENOTREADY */ 990 991 /* later, after some timeouts ZIPwakeup() is called. */ 992 } else { 993 /* otherwise, we have the zone and the multicast already, 994 so don't bother with another ZIP GetNetInfo request */ 995 ZIPwakeup(elapp, 0); 996 } 997} /* elap_online2 */ 998 999/* called from rtmp_router_start */ 1000int elap_online3(elapp) 1001 at_ifaddr_t *elapp; 1002{ 1003 elapp->startup_inprogress = TRUE; 1004 1005 /* just reset the net range */ 1006 elapp->initial_addr.s_net = 0; 1007 elapp->initial_addr.s_node = 0; 1008 dPrintf(D_M_ELAP_LOW, D_L_STARTUP_INFO, 1009 ("elap_online: goto re_aarp port=%d\n", elapp->ifPort)); 1010 1011 if ((elapp->startup_error = re_aarp(elapp))) 1012 return(elapp->startup_error); 1013 1014 /* then later, after some timeouts AARPwakeup() is called */ 1015 1016 lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED); 1017 (void)msleep(&elapp->startup_inprogress, atalk_mutex, PSOCK | PCATCH, 1018 "elap_online3", 0); 1019 return(elapp->startup_error); 1020} /* elap_online3 */ 1021 1022/**************************************************************************** 1023 * elap_offline() 1024 * 1025 ****************************************************************************/ 1026 1027void elap_offline(elapp) 1028 register at_ifaddr_t *elapp; 1029 1030{ 1031 dPrintf(D_M_ELAP, D_L_SHUTDN_INFO, ("elap_offline:%s\n", elapp->ifName)); 1032 if (elapp->ifState != LAP_OFFLINE) { 1033 1034 /* Since AppleTalk is going away, remove the cable 1035 * multicast address and turn the interface off so that all 1036 * AppleTalk packets are dropped in the driver itself. 1037 * Get rid of the zone multicast address prior to going Offline. 1038 */ 1039 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->ZoneMcastAddr); 1040 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr); 1041 elapp->ifState = LAP_OFFLINE; 1042 1043 if (MULTIPORT_MODE) 1044 RT_DELETE(elapp->ifThisCableEnd, 1045 elapp->ifThisCableStart); 1046 1047 /* make sure no zip timeouts are left running */ 1048 elapp->ifGNIScheduled = 0; 1049 untimeout(zip_sched_getnetinfo, elapp); 1050 } 1051 ddp_rem_if(elapp); 1052} /* elap_offline */ 1053 1054 1055static void add_route(rt) 1056RT_entry *rt; 1057 1058/* support ioctl to manually add routes to table. 1059 this is really only for testing 1060*/ 1061{ 1062 rt_insert( rt->NetStop, rt->NetStart, rt->NextIRNet, 1063 rt->NextIRNode, rt->NetDist, rt->NetPort, 1064 rt->EntryState); 1065 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("adding route: %ud:%ud dist:%ud\n", 1066 rt->NetStart, rt->NetStop,rt->NetDist)); 1067} 1068 1069/* 1070 * ddp_start() 1071 * 1072 * Initialization that takes place each time AppleTalk is restarted. 1073 * 1074 */ 1075void ddp_start() 1076{ 1077 TAILQ_INIT(&at_ifQueueHd); 1078 TAILQ_INIT(&name_registry); 1079 bzero(at_interfaces, sizeof(at_interfaces)); 1080 bzero(ifID_table, sizeof(ifID_table)); 1081 bzero(&at_ddp_stats, sizeof(at_ddp_stats_t)); 1082 rtmp_init(); /* initialize trackedrouters */ 1083 1084 add_ddp_handler(RTMP_SOCKET, rtmp_input); 1085 ifID_home = (at_ifaddr_t *)NULL; 1086 xpatcnt = 0; 1087} 1088 1089int ddp_shutdown(count_only) 1090 int count_only; 1091{ 1092 at_ifaddr_t *ifID; 1093 asp_scb_t *scb, *scb_next; 1094 struct atp_state *atp, *atp_next; 1095 CCB *sp, *sp_next; 1096 gref_t *gref; 1097 int i, active_skts = 0; /* count of active pids for non-socketized 1098 AppleTalk protocols */ 1099 1100 /* Network is shutting down... send error messages up on each open 1101 * socket. 1102 *** For now, for ASP, ATP and ADSP, attempt to notify open 1103 sockets, but return EBUSY and don't complete shutdown. *** 1104 */ 1105 1106 if (!count_only) 1107 nbp_shutdown(); /* clear all known NVE */ 1108 1109 /* ASP */ 1110 for (scb = scb_used_list; scb; ) { 1111 scb_next = scb->next_scb; 1112 active_skts++; 1113 if (!count_only) { 1114 dPrintf(D_M_ASP, D_L_TRACE, ("asp pid=%d\n", scb->pid)); 1115 atalk_notify(scb->gref, ESHUTDOWN); 1116 } 1117 scb = scb_next; 1118 } 1119 for (i = 0; i < 256 ; i++) { 1120 if ((scb = asp_scbQ[i])) 1121 do { 1122 scb_next = scb->next_scb; 1123 active_skts++; 1124 if (!count_only) { 1125 dPrintf(D_M_ASP, D_L_TRACE, 1126 ("asp pid=%d\n", scb->pid)); 1127 atalk_notify(scb->gref, ESHUTDOWN); 1128 } 1129 scb = scb_next; 1130 } while (scb); 1131 } 1132 1133 /* ATP */ 1134 for (atp = atp_used_list; atp; ) { 1135 atp_next = atp->atp_trans_waiting; 1136 active_skts++; 1137 if (!count_only) { 1138 dPrintf(D_M_ATP, D_L_TRACE, ("atp pid=%d\n", atp->atp_pid)); 1139 atalk_notify(atp->atp_gref, ESHUTDOWN); 1140 } 1141 atp = atp_next; 1142 } 1143 for (i = 0; i < 256; i++) { 1144 if ((gref = atp_inputQ[i]) && (gref != (gref_t *)1)) { 1145 atp = (struct atp_state *)gref->info; 1146 if (!atp->dflag) { 1147 active_skts++; 1148 if (!count_only) { 1149 dPrintf(D_M_ATP, D_L_TRACE, 1150 ("atp pid=%d\n", atp->atp_pid)); 1151 atalk_notify(atp->atp_gref, ESHUTDOWN); 1152 } 1153 } 1154 } 1155 } 1156 1157 /* ADSP */ 1158 for (sp = ccb_used_list; sp ; ) { 1159 sp_next = sp->otccbLink; 1160 active_skts++; 1161 if (!count_only) { 1162 dPrintf(D_M_ADSP, D_L_TRACE, ("adsp pid=%d\n", sp->pid)); 1163 atalk_notify(sp->gref, ESHUTDOWN); 1164 } 1165 sp = sp_next; 1166 } 1167 for (i = 0; i < 256 ; i++) { 1168 if ((sp = adsp_inputQ[i])) 1169 do { 1170 sp_next = sp->otccbLink; 1171 active_skts++; 1172 if (!count_only) { 1173 dPrintf(D_M_ADSP, D_L_TRACE, 1174 ("adsp pid=%d\n", sp->pid)); 1175 atalk_notify(sp->gref, ESHUTDOWN); 1176 } 1177 sp = sp_next; 1178 } while (sp); 1179 } 1180 1181 /* DDP */ 1182 for (gref = ddp_head.atpcb_next; gref != &ddp_head; 1183 gref = gref->atpcb_next) { 1184 if (count_only) { 1185 active_skts++; 1186 } else { 1187 dPrintf(D_M_DDP,D_L_TRACE, ("ddp pid=%d\n", gref->pid)); 1188 atalk_notify(gref, ESHUTDOWN); 1189 } 1190 } 1191 if (count_only) 1192 return(active_skts); 1193 1194 /* if there are no interfaces in the process of going online, continue shutting down DDP */ 1195 for (i = 0; i < IF_TOTAL_MAX; i++) { 1196 if (at_interfaces[i].startup_inprogress == TRUE) 1197 return(1); 1198 } 1199 if (MULTIPORT_MODE) { 1200 rtmp_shutdown(); 1201 /* free memory allocated for the rtmp/zip tables */ 1202 if (ZT_table) { 1203 FREE(ZT_table, M_RTABLE); 1204 ZT_table = (ZT_entry *)NULL; 1205 } 1206 if (RT_table) { 1207 FREE(RT_table, M_RTABLE); 1208 RT_table = (RT_entry *)NULL; 1209 } 1210 } 1211 1212 at_state.flags = 0; /* make sure inits are done on restart */ 1213 1214 wakeup(&ifID_home->startup_inprogress); /* if rtmp_router_start still starting up */ 1215 1216 /* from original ddp_shutdown() */ 1217 routershutdown(); 1218 ddp_brt_shutdown(); 1219 1220 if (adspInited) { 1221 CleanupGlobals(); 1222 adspInited = 0; 1223 } 1224 1225 1226 dPrintf(D_M_DDP, D_L_VERBOSE, ("DDP shutdown completed")); 1227 1228 /* 1229 * make sure we don't have a probe timeout hanging around 1230 * it's going to try and make use of an entry in at_interfaces 1231 * which is going to be zero'd out by the call to ddp_start a 1232 * little further down 1233 */ 1234 untimeout(aarp_sched_probe, 0); 1235 1236 /* *** after an SIOCSIFADDR and before an AIOCSIFADDR, 1237 this is the only place to find the ifID *** */ 1238 for (i = 0; i < IF_TOTAL_MAX; i++) { 1239 ifID = &at_interfaces[i]; 1240 /* do LAP_IOC_OFFLINE processing */ 1241 elap_offline(ifID); 1242 } 1243 ddp_start(); 1244 1245 return(0); 1246} /* ddp_shutdown */ 1247 1248int routerStart(keP) 1249 at_kern_err_t *keP; 1250{ 1251 register at_ifaddr_t *ifID; 1252 int error; 1253 struct timespec ts; 1254 1255 if (! ifID_home) 1256 return(EINVAL); 1257 1258 /* 1259 * this will cause the ports to glean from the net the relevant 1260 * information before forwarding 1261 */ 1262 TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { 1263 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, 1264 ("routerStart Port %d (%s) set to activating\n", 1265 ifID->ifPort, ifID->ifName)); 1266 ifID->ifRoutingState = PORT_ACTIVATING; 1267 ifID->ifFlags |= RTR_XNET_PORT; 1268 } 1269 1270 /* 1271 * The next step is to check the information for each port before 1272 * declaring the ports up and forwarding 1273 */ 1274 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, 1275 ("router_start: waiting 20 sec before starting up\n")); 1276 1277 lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED); 1278 /* sleep for 20 seconds */ 1279 1280 /* the vaue of 10n terms of hz is 100ms */ 1281 ts.tv_sec = 20; 1282 ts.tv_nsec = 0; 1283 1284 if ((error = 1285 /* *** eventually this will be the ifID for the interface 1286 being brought up in router mode *** */ 1287 msleep(&ifID_home->startup_inprogress, atalk_mutex, 1288 PSOCK | PCATCH, "routerStart", &ts)) 1289 != EWOULDBLOCK) { 1290/* 1291 if (!error) 1292 panic("routerStart: spurious interrupt"); 1293*/ 1294 return(error); 1295 } 1296 1297 return(rtmp_router_start(keP)); 1298 /* was timeout(rtmp_router_start, 0, 20 * SYS_HZ); */ 1299} /* routerStart */ 1300 1301void ZIPwakeup(elapp, ZipError) 1302 at_ifaddr_t *elapp; 1303 int ZipError; 1304{ 1305 int error = ZipError; 1306 1307 if ( (elapp != NULL) && elapp->startup_inprogress) { 1308 1309 /* was ZIPContinue */ 1310 /* was elapp_online() with jump to ZIP_sleep */ 1311 1312 /* instead of the goto ZIP_sleep ... */ 1313 switch (ZipError) { 1314 case 0 : /* success */ 1315 elapp->ifState = LAP_ONLINE; 1316 1317 /* Send event with zone info. */ 1318 atalk_post_msg(elapp->aa_ifp, KEV_ATALK_ZONEUPDATED, 0, &(elapp->ifZoneName)); 1319 1320 break; 1321 case ZIP_RE_AARP : 1322 /* instead of goto re_aarp; */ 1323 /* We now call aarp_init() to assign an 1324 appletalk node addr */ 1325 if ((elapp->startup_error = re_aarp(elapp))) { 1326 elapp->startup_inprogress = FALSE; 1327 wakeup(&elapp->startup_inprogress); 1328 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, 1329 ("elap_online: ack 2\n")); 1330 } 1331 break; 1332 default : 1333 break; 1334 } 1335 if (ZipError != ZIP_RE_AARP) { 1336 elapp->startup_error = error; 1337 elapp->startup_inprogress = FALSE; 1338 wakeup(&elapp->startup_inprogress); 1339 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, 1340 ("elap_online: ifZipError=%d\n", error)); 1341 } 1342 } 1343} /* ZIPwakeup */ 1344 1345void AARPwakeup(probe_cb) 1346 aarp_amt_t *probe_cb; 1347{ 1348 int errno; 1349 at_ifaddr_t *elapp; 1350 1351 elapp = probe_cb->elapp; 1352 if ( (elapp != NULL) && elapp->startup_inprogress && elapp->aa_ifp != 0) { 1353 1354 /* was AARPContinue */ 1355 errno = aarp_init2(elapp); 1356 /* aarp_init2() returns either -1 or 0 */ 1357 if (errno != 0) { 1358 dPrintf(D_M_ELAP, D_L_STATE_CHG, 1359 ("elap_online aarp_init for %s\n", 1360 elapp->ifName)); 1361 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->ZoneMcastAddr); 1362 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr); 1363 elapp->ifState = LAP_OFFLINE; 1364 ddp_rem_if(elapp); 1365 elapp->startup_error = EADDRNOTAVAIL; 1366 elapp->startup_inprogress = FALSE; 1367 wakeup(&elapp->startup_inprogress); 1368 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online: ack 2\n")); 1369 } else { 1370 dPrintf(D_M_ELAP,D_L_STARTUP_INFO, 1371 ("elap_online: aarp_init returns zero\n")); 1372 elap_online2(elapp); 1373 } 1374 } 1375} /* AARPwakeup */ 1376 1377void ddp_bit_reverse(addr) 1378 unsigned char *addr; 1379{ 1380static unsigned char reverse_data[] = { 1381 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 1382 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 1383 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 1384 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 1385 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 1386 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 1387 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 1388 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 1389 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 1390 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 1391 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 1392 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 1393 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 1394 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 1395 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 1396 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 1397 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 1398 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 1399 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 1400 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 1401 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 1402 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 1403 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 1404 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 1405 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 1406 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 1407 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 1408 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 1409 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 1410 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 1411 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 1412 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff 1413 }; 1414 1415 unsigned char k; 1416 1417 for (k=0; k < 6; k++) 1418 addr[k] = reverse_data[addr[k]]; 1419} 1420 1421static int elap_trackMcast(at_ifaddr_t *, int, caddr_t); 1422 1423static int elap_trackMcast(patp, func, addr) 1424 at_ifaddr_t *patp; 1425 int func; 1426 caddr_t addr; 1427{ 1428 int i, loc=-1; 1429 u_char c; 1430 switch(patp->aa_ifp->if_type) { 1431 case IFT_ETHER: 1432 case IFT_FDDI: 1433 case IFT_L2VLAN: 1434 case IFT_IEEE8023ADLAG: /* bonded ethernet */ 1435 /* set addr to point to unique part of addr */ 1436 c = addr[5]; 1437 1438 /* first try to find match */ 1439 /* *** save just one byte of the multicast address? *** */ 1440 for (i=0; i< MAX_MCASTS; i++) 1441 if (c == patp->mcast[i]) { 1442 loc = i; 1443 break; 1444 } 1445 1446 switch (func) { 1447 case MCAST_TRACK_DELETE: 1448 if (loc >= 0) 1449 patp->mcast[loc] = 0; 1450 1451 break; 1452 case MCAST_TRACK_ADD: 1453 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add loc:%d\n", i)); 1454 if (loc >= 0) { 1455 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, addr was there\n")); 1456 return(1); 1457 break; /* already there */ 1458 } 1459 for (i=0; i< MAX_MCASTS; i++) 1460 if (patp->mcast[i] == 0) { 1461 loc = i; 1462 break; 1463 } 1464 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add1 loc:%d\n", i)); 1465 if (loc >= 0) { 1466 patp->mcast[loc] = c; 1467 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, adding(%x)\n", 1468 (*(int*)addr)&0xffffff)); 1469 } 1470 else { 1471 /*errno = ENOMEM; */ /*LD 5/7/97 nobody is using that */ 1472 return(-1); 1473 } 1474 break; 1475 case MCAST_TRACK_CHECK: 1476 if (loc >= 0) { 1477 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:check, addr was there\n")); 1478 return(0); 1479 } 1480 else { 1481 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, addr was NOT there\n")); 1482 return(-1); 1483 } 1484 1485 default: 1486 /*errno = EINVAL;*/ /*LD 5/7/97 nobody is using that */ 1487 return(-1); 1488 } 1489 1490 case IFT_ISO88025: /* token ring */ 1491 /* we would use the lowest byte of the addr argument as a value 1492 to shift left a 1 to form the mcast mask for TR. We'll do this 1493 when the time comes 1494 */ 1495 default: 1496 ; 1497 } 1498 return(0); 1499} 1500 1501 1502static int getSnmpCfg(snmp) 1503 snmpCfg_t *snmp; 1504{ 1505 int i; 1506 at_ifaddr_t *elapp; 1507 snmpIfCfg_t *ifc; 1508 1509 snmp->cfg_ifCnt = 0; 1510 1511 bzero(snmp,sizeof(snmpCfg_t)); 1512 for (i=0, elapp=at_interfaces,ifc=snmp->cfg_ifCfg; 1513 i<IF_TOTAL_MAX; i++, elapp++, ifc++) { 1514 if (elapp->ifState != LAP_OFFLINE) { 1515 snmp->cfg_ifCnt++; 1516 strlcpy(ifc->ifc_name,elapp->ifName, sizeof(ifc->ifc_name)); 1517 ifc->ifc_aarpSize = getAarpTableSize(i); 1518 ifc->ifc_addrSize = getPhysAddrSize(i); 1519 switch (elapp->aa_ifp->if_type) { 1520 case IFT_ETHER: 1521 case IFT_L2VLAN: 1522 case IFT_IEEE8023ADLAG: /* bonded ethernet */ 1523 ifc->ifc_type = SNMP_TYPE_ETHER2; 1524 break; 1525 case IFT_ISO88025: /* token ring */ 1526 ifc->ifc_type = SNMP_TYPE_TOKEN; 1527 break; 1528 case IFT_FDDI: 1529 default: 1530 ifc->ifc_type = SNMP_TYPE_OTHER; 1531 break; 1532 } 1533 ifc->ifc_start = elapp->ifThisCableStart; 1534 ifc->ifc_end = elapp->ifThisCableEnd; 1535 ifc->ifc_ddpAddr= elapp->ifThisNode; 1536 ifc->ifc_status = elapp->ifState == LAP_ONLINE ? 1 : 2; 1537 ifc->ifc_zoneName.len = 0; 1538 if (elapp->ifZoneName.len != 0) { 1539 ifc->ifc_zoneName = elapp->ifZoneName; 1540 } 1541 else if (elapp->ifDefZone) { 1542 ifc->ifc_zoneName = ZT_table[elapp->ifDefZone-1].Zone; 1543 } 1544 else /* temp, debug only */ 1545 ifc->ifc_zoneName = ZT_table[0].Zone; 1546 if (ROUTING_MODE) { 1547 if (elapp->ifFlags & RTR_SEED_PORT) { 1548 ifc->ifc_netCfg = SNMP_CFG_CONFIGURED; 1549 ifc->ifc_zoneCfg = SNMP_CFG_CONFIGURED; 1550 } 1551 else { 1552 ifc->ifc_netCfg = SNMP_CFG_GARNERED; 1553 ifc->ifc_zoneCfg = SNMP_CFG_GARNERED; 1554 } 1555 } 1556 else { /* single-port mode */ 1557 if (elapp->ifRouterState == ROUTER_AROUND) { 1558 ifc->ifc_netCfg = SNMP_CFG_GARNERED; 1559 } 1560 else { 1561 ifc->ifc_netCfg = SNMP_CFG_GUESSED; 1562 ifc->ifc_zoneCfg = SNMP_CFG_UNCONFIG; 1563 } 1564 } 1565 } 1566 } 1567 snmp->cfg_flags = at_state.flags; 1568 1569 1570 return(0); 1571} 1572 1573int at_reg_mcast(ifID, data) 1574 at_ifaddr_t *ifID; 1575 caddr_t data; 1576{ 1577 struct ifnet *nddp = ifID->aa_ifp; 1578 struct sockaddr_dl sdl; 1579 1580 if (*(int *)data) { 1581 if (!nddp) { 1582 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n")); 1583 return(-1); 1584 } 1585 1586 if (elap_trackMcast(ifID, MCAST_TRACK_ADD, data) == 1) 1587 return(0); 1588 1589 /* this is for ether_output */ 1590 bzero(&sdl, sizeof(sdl)); 1591 sdl.sdl_family = AF_LINK; 1592 sdl.sdl_alen = sizeof(struct etalk_addr); 1593 sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data) 1594 + sizeof(struct etalk_addr); 1595 bcopy(data, sdl.sdl_data, sizeof(struct etalk_addr)); 1596 /* these next two lines should not really be needed XXX */ 1597 sdl.sdl_index = nddp->if_index; 1598 sdl.sdl_type = IFT_ETHER; 1599 1600 dPrintf(D_M_PAT, D_L_STARTUP, 1601 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n", 1602 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff, 1603 (unsigned)ifID)); 1604 1605 if (if_addmulti_anon(nddp, (struct sockaddr *)&sdl, NULL)) 1606 return -1; 1607 } 1608 return 0; 1609 1610} 1611 1612int at_unreg_mcast(ifID, data) 1613 at_ifaddr_t *ifID; 1614 caddr_t data; 1615{ 1616 struct ifnet *nddp = ifID->aa_ifp; 1617 struct sockaddr_dl sdl; 1618 1619 if (*(int *)data) { 1620 if (!nddp) { 1621 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n")); 1622 return(-1); 1623 } 1624 1625 elap_trackMcast(ifID, MCAST_TRACK_DELETE, data); 1626 1627 /* this is for ether_output */ 1628 bzero(&sdl, sizeof(sdl)); 1629 sdl.sdl_family = AF_LINK; 1630 sdl.sdl_alen = sizeof(struct etalk_addr); 1631 sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data) 1632 + sizeof(struct etalk_addr); 1633 bcopy(data, sdl.sdl_data, sizeof(struct etalk_addr)); 1634 /* these next two lines should not really be needed XXX */ 1635 sdl.sdl_index = nddp->if_index; 1636 sdl.sdl_type = IFT_ETHER; 1637 1638 dPrintf(D_M_PAT, D_L_STARTUP, 1639 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n", 1640 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff, 1641 (unsigned)ifID)); 1642 bzero(data, sizeof(struct etalk_addr)); 1643 1644 if (if_delmulti_anon(nddp, (struct sockaddr *)&sdl)) 1645 return -1; 1646 } 1647 return 0; 1648} 1649#ifdef NOT_YET 1650/* *** at_reg_mcast() and at_unreg_mcast() should be replaced as soon as the 1651 new code to allow an AF_LINK address family multicast to be (un)registered 1652 using the SIOCADDMULTI / SIOCDELMULTI ioctls has been completed. 1653 1654 The issue is that the "struct sockaddr_dl" needed for the AF_LINK does not 1655 fit in the "struct ifreq" that is used for these ioctls, and we do not want 1656 Blue/Classic, which currently uses AF_UNSPEC, to use a different address 1657 family multicast address than Mac OS X uses. 1658 *** */ 1659 1660int at_reg_mcast(ifID, data) 1661 at_ifaddr_t *ifID; 1662 caddr_t data; 1663{ 1664 struct ifnet *nddp = ifID->aa_ifp; 1665 struct sockaddr_dl sdl; 1666 1667 if (*(int *)data) { 1668 if (!nddp) { 1669 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n")); 1670 return(-1); 1671 } 1672 if (elap_trackMcast(ifID, MCAST_TRACK_ADD, data) == 1) 1673 return(0); 1674 1675 sdl.sdl_len = sizeof(struct sockaddr_dl); 1676 sdl.sdl_family = AF_LINK; 1677 sdl.sdl_index = 0; 1678 sdl.sdl_type = nddp->if_type; 1679 sdl.sdl_alen = nddp->if_addrlen; 1680 sdl.sdl_slen = 0; 1681 sdl.sdl_nlen = sprintf(sdl.sdl_data, "%s%d", 1682 nddp->if_name , nddp->if_unit); 1683 bcopy(data, LLADDR(&sdl), sdl.sdl_alen); 1684 1685 dPrintf(D_M_PAT, D_L_STARTUP, 1686 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n", 1687 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff, 1688 (unsigned)ifID)); 1689 1690 if (if_addmulti_anon(nddp, (struct sockaddr *)&sdl, NULL)) 1691 return -1; 1692 } 1693 1694 return 0; 1695} 1696 1697int at_unreg_mcast(ifID, data) 1698 at_ifaddr_t *ifID; 1699 caddr_t data; 1700{ 1701 struct ifnet *nddp = ifID->aa_ifp; 1702 struct sockaddr_dl sdl; 1703 1704 if (*(int *)data) { 1705 if (!nddp) { 1706 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n")); 1707 return(-1); 1708 } 1709 1710 elap_trackMcast(ifID, MCAST_TRACK_DELETE, data); 1711 1712 sdl.sdl_len = sizeof(struct sockaddr_dl); 1713 sdl.sdl_family = AF_LINK; 1714 sdl.sdl_index = 0; 1715 sdl.sdl_type = nddp->if_type; 1716 sdl.sdl_alen = nddp->if_addrlen; 1717 sdl.sdl_slen = 0; 1718 sdl.sdl_nlen = sprintf(sdl.sdl_data, "%s%d", 1719 nddp->if_name , nddp->if_unit); 1720 1721 dPrintf(D_M_PAT, D_L_STARTUP, 1722 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n", 1723 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff, 1724 (unsigned)ifID)); 1725 bzero(data, ETHERNET_ADDR_LEN); 1726 1727 if (if_delmulti_anon(nddp, (struct sockaddr *)&sdl)) 1728 return(-1); 1729 } 1730 1731 return 0; 1732} 1733 1734#endif 1735