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