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