]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/ddp_lap.c
xnu-517.7.7.tar.gz
[apple/xnu.git] / bsd / netat / ddp_lap.c
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>
59 #include <vm/vm_kern.h> /* for kernel_map */
60
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
82 #include <sys/kern_event.h>
83
84 /* globals */
85
86 at_ifaddr_t at_interfaces[IF_TOTAL_MAX];
87 /* index for at_interfaces is not important */
88 at_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 */
94 at_ifaddr_t *ifID_home;
95 /* always ifID_table[IFID_HOME] for now, but will be used for
96 dynamic "home port" assignment, later */
97
98 at_state_t at_state; /* global state of AT network */
99 snmpFlags_t snmpFlags;
100
101 int 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 */
114 extern TAILQ_HEAD(name_registry, _nve_) name_registry;
115 extern snmpStats_t snmpStats;
116 extern atlock_t ddpinp_lock;
117 extern atlock_t arpinp_lock;
118 extern short appletalk_inited;
119 extern int adspInited;
120 extern struct atpcb ddp_head;
121 extern gref_t *atp_inputQ[];
122 extern struct atp_state *atp_used_list;
123 extern asp_scb_t *asp_scbQ[];
124 extern asp_scb_t *scb_used_list;
125 extern CCB *adsp_inputQ[];
126 extern CCB *ccb_used_list;
127 extern at_ddp_stats_t at_ddp_stats;
128
129 /* protos */
130 extern snmpAarpEnt_t * getAarp(int *);
131 extern void nbp_shutdown(), routershutdown(), ddp_brt_shutdown();
132 extern void ddp_brt_init(), rtmp_init(), rtmp_input();
133 extern rtmp_router_start(at_kern_err_t *);
134 static void getIfNames(at_ifnames_t *);
135 static void add_route();
136 static int set_zones();
137 void elap_offline();
138 static int elap_online1(), re_aarp();
139 int at_reg_mcast(), at_unreg_mcast();
140 void AARPwakeup(), ZIPwakeup();
141 static void elap_hangup();
142 static getSnmpCfg();
143
144 at_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
158 static 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);
219 error:
220 ioc_ack(EMSGSIZE, m, gref);
221 return (EMSGSIZE);
222 } /* validate_msg_size */
223
224 int 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 **********************************************************************/
300 int 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 */
770 elap_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
869 static 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 // check if we still have an interface - can be lost when
889 // ddp_add_if calls malloc
890 // need to make check here after ddp_add_if completes because
891 // lap_online will call ddp_rem_if if we fail here
892 if (elapp->aa_ifp == 0)
893 return ENOENT;
894
895 /* set up multicast address for cable-wide broadcasts */
896 (void)at_reg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
897
898 // need to check again if interface is present
899 // can be lost in at_reg_mcast
900 if (elapp->aa_ifp == 0)
901 return ENOENT;
902
903 elapp->startup_inprogress = TRUE;
904 if (! (elapp->startup_error = re_aarp(elapp)))
905 (void)tsleep(&elapp->startup_inprogress, PSOCK | PCATCH,
906 "elap_online1", 0);
907
908 /* then later, after some timeouts AARPwakeup() is called */
909
910 return(elapp->startup_error);
911 } /* elap_online1 */
912
913 static int re_aarp(elapp)
914 at_ifaddr_t *elapp;
915 {
916 int errno;
917
918 /* We now call aarp_init() to assign an appletalk node addr */
919 errno = aarp_init1(elapp);
920 /* aarp_init1() returns either -1 or ENOTREADY */
921 if (errno == ENOTREADY)
922 return(0);
923 else {
924 dPrintf(D_M_ELAP, D_L_STATE_CHG,
925 ("elap_online aarp_init for %s\n", elapp->ifName));
926 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
927 ddp_rem_if(elapp);
928 elapp->ifState = LAP_OFFLINE;
929 return(EADDRNOTAVAIL);
930 }
931 }
932
933 /* called from AARPwakeup */
934 static void elap_online2(elapp)
935 at_ifaddr_t *elapp;
936 {
937 if (MULTIPORT_MODE) {
938 dPrintf(D_M_ELAP,D_L_STARTUP_INFO,
939 ("elap_online: re_aarp, we know it's a router...\n"));
940
941 if (elapp->flags & ELAP_CFG_SEED) {
942 /* add route table entry (zones to be added later) */
943 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
944 ("elap_online: rt_insert Cable %d-%d port =%d as SEED\n",
945 elapp->ifThisCableStart, elapp->ifThisCableEnd, elapp->ifPort));
946 rt_insert(elapp->ifThisCableEnd,
947 elapp->ifThisCableStart,
948 0,0,0,
949 elapp->ifPort,
950 RTE_STATE_PERMANENT | RTE_STATE_ZKNOWN | RTE_STATE_GOOD
951 );
952 /* LD 081694: set the RTR_SEED_PORT flag for seed ports */
953 elapp->ifFlags |= RTR_SEED_PORT;
954 }
955 else
956 dPrintf(D_M_ELAP,D_L_STARTUP_INFO,
957 ("elap_online: it's a router, but non seed\n"));
958 }
959
960 if (elapp->flags & ELAP_CFG_ZONELESS) {
961 /* ELAP_CFG_ZONELESS tells us that it is a router or in
962 multihome mode, so we don't want to do the GetNetInfo
963 exchange with the router. */
964
965 elapp->ifState = LAP_ONLINE_ZONELESS;
966 elapp->startup_inprogress = FALSE;
967 wakeup(&elapp->startup_inprogress);
968 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online: ack 3\n"));
969 return;
970 }
971
972 /* if we don't already have a zone and a multicast address */
973 if (*(int *)&elapp->ZoneMcastAddr == 0 || elapp->ifZoneName.len == 0) {
974 /* hzonehash is a global containing the nbp hash for the startup_zone */
975 sethzonehash(elapp);
976
977 /* Get ZIP rolling to get zone multicast address, etc. */
978 elapp->ifState = LAP_ONLINE_FOR_ZIP;
979 (void)zip_control(elapp, ZIP_ONLINE);
980 /* zip_control (w. control == ZIP_ONLINE) always returns ENOTREADY */
981
982 /* later, after some timeouts ZIPwakeup() is called. */
983 } else {
984 /* otherwise, we have the zone and the multicast already,
985 so don't bother with another ZIP GetNetInfo request */
986 ZIPwakeup(elapp, 0);
987 }
988 } /* elap_online2 */
989
990 /* called from rtmp_router_start */
991 int elap_online3(elapp)
992 at_ifaddr_t *elapp;
993 {
994 elapp->startup_inprogress = TRUE;
995
996 /* just reset the net range */
997 elapp->initial_addr.s_net = 0;
998 elapp->initial_addr.s_node = 0;
999 dPrintf(D_M_ELAP_LOW, D_L_STARTUP_INFO,
1000 ("elap_online: goto re_aarp port=%d\n", elapp->ifPort));
1001
1002 if ((elapp->startup_error = re_aarp(elapp)))
1003 return(elapp->startup_error);
1004
1005 /* then later, after some timeouts AARPwakeup() is called */
1006
1007 (void)tsleep(&elapp->startup_inprogress, PSOCK | PCATCH,
1008 "elap_online3", 0);
1009 return(elapp->startup_error);
1010 } /* elap_online3 */
1011
1012 /****************************************************************************
1013 * elap_offline()
1014 *
1015 ****************************************************************************/
1016
1017 void elap_offline(elapp)
1018 register at_ifaddr_t *elapp;
1019
1020 {
1021 void zip_sched_getnetinfo(); /* forward reference */
1022 int errno;
1023 int s;
1024
1025 dPrintf(D_M_ELAP, D_L_SHUTDN_INFO, ("elap_offline:%s\n", elapp->ifName));
1026 if (elapp->ifState != LAP_OFFLINE) {
1027
1028 /* Since AppleTalk is going away, remove the cable
1029 * multicast address and turn the interface off so that all
1030 * AppleTalk packets are dropped in the driver itself.
1031 * Get rid of the zone multicast address prior to going Offline.
1032 */
1033 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->ZoneMcastAddr);
1034 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
1035 elapp->ifState = LAP_OFFLINE;
1036
1037 ATDISABLE(s, ddpinp_lock);
1038 if (MULTIPORT_MODE)
1039 RT_DELETE(elapp->ifThisCableEnd,
1040 elapp->ifThisCableStart);
1041 ATENABLE(s, ddpinp_lock);
1042
1043 /* make sure no zip timeouts are left running */
1044 untimeout(zip_sched_getnetinfo, elapp);
1045 }
1046 ddp_rem_if(elapp);
1047 } /* elap_offline */
1048
1049
1050 static void add_route(rt)
1051 RT_entry *rt;
1052
1053 /* support ioctl to manually add routes to table.
1054 this is really only for testing
1055 */
1056 {
1057 rt_insert( rt->NetStop, rt->NetStart, rt->NextIRNet,
1058 rt->NextIRNode, rt->NetDist, rt->NetPort,
1059 rt->EntryState);
1060 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("adding route: %ud:%ud dist:%ud\n",
1061 rt->NetStart, rt->NetStop,rt->NetDist));
1062 }
1063
1064 /*
1065 * ddp_start()
1066 *
1067 * Initialization that takes place each time AppleTalk is restarted.
1068 *
1069 */
1070 void ddp_start()
1071 {
1072 TAILQ_INIT(&at_ifQueueHd);
1073 TAILQ_INIT(&name_registry);
1074 bzero(at_interfaces, sizeof(at_interfaces));
1075 bzero(ifID_table, sizeof(ifID_table));
1076 bzero(&at_ddp_stats, sizeof(at_ddp_stats_t));
1077 rtmp_init(); /* initialize trackedrouters */
1078
1079 add_ddp_handler(RTMP_SOCKET, rtmp_input);
1080 ifID_home = (at_ifaddr_t *)NULL;
1081 xpatcnt = 0;
1082 }
1083
1084 int ddp_shutdown(count_only)
1085 int count_only;
1086 {
1087 at_ifaddr_t *ifID;
1088 asp_scb_t *scb, *scb_next;
1089 struct atp_state *atp, *atp_next;
1090 CCB *sp, *sp_next;
1091 gref_t *gref;
1092 vm_offset_t temp_rcb_data, temp_state_data;
1093 int i, s, active_skts = 0; /* count of active pids for non-socketized
1094 AppleTalk protocols */
1095
1096 /* Network is shutting down... send error messages up on each open
1097 * socket.
1098 *** For now, for ASP, ATP and ADSP, attempt to notify open
1099 sockets, but return EBUSY and don't complete shutdown. ***
1100 */
1101
1102 s = splimp(); /* *** previously contained mismatched locking
1103 that was ifdef'ed to splimp() *** */
1104 if (!count_only)
1105 nbp_shutdown(); /* clear all known NVE */
1106
1107 /* ASP */
1108 for (scb = scb_used_list; scb; ) {
1109 scb_next = scb->next_scb;
1110 active_skts++;
1111 if (!count_only) {
1112 dPrintf(D_M_ASP, D_L_TRACE, ("asp pid=%d\n", scb->pid));
1113 atalk_notify(scb->gref, ESHUTDOWN);
1114 }
1115 scb = scb_next;
1116 }
1117 for (i = 0; i < 256 ; i++) {
1118 if ((scb = asp_scbQ[i]))
1119 do {
1120 scb_next = scb->next_scb;
1121 active_skts++;
1122 if (!count_only) {
1123 dPrintf(D_M_ASP, D_L_TRACE,
1124 ("asp pid=%d\n", scb->pid));
1125 atalk_notify(scb->gref, ESHUTDOWN);
1126 }
1127 scb = scb_next;
1128 } while (scb);
1129 }
1130
1131 /* ATP */
1132 for (atp = atp_used_list; atp; ) {
1133 atp_next = atp->atp_trans_waiting;
1134 active_skts++;
1135 if (!count_only) {
1136 dPrintf(D_M_ATP, D_L_TRACE, ("atp pid=%d\n", atp->atp_pid));
1137 atalk_notify(atp->atp_gref, ESHUTDOWN);
1138 }
1139 atp = atp_next;
1140 }
1141 for (i = 0; i < 256; i++) {
1142 if ((gref = atp_inputQ[i]) && (gref != (gref_t *)1)) {
1143 atp = (struct atp_state *)gref->info;
1144 if (!atp->dflag) {
1145 active_skts++;
1146 if (!count_only) {
1147 dPrintf(D_M_ATP, D_L_TRACE,
1148 ("atp pid=%d\n", atp->atp_pid));
1149 atalk_notify(atp->atp_gref, ESHUTDOWN);
1150 }
1151 }
1152 }
1153 }
1154
1155 /* ADSP */
1156 for (sp = ccb_used_list; sp ; ) {
1157 sp_next = sp->otccbLink;
1158 active_skts++;
1159 if (!count_only) {
1160 dPrintf(D_M_ADSP, D_L_TRACE, ("adsp pid=%d\n", sp->pid));
1161 atalk_notify(sp->gref, ESHUTDOWN);
1162 }
1163 sp = sp_next;
1164 }
1165 for (i = 0; i < 256 ; i++) {
1166 if ((sp = adsp_inputQ[i]))
1167 do {
1168 sp_next = sp->otccbLink;
1169 active_skts++;
1170 if (!count_only) {
1171 dPrintf(D_M_ADSP, D_L_TRACE,
1172 ("adsp pid=%d\n", sp->pid));
1173 atalk_notify(sp->gref, ESHUTDOWN);
1174 }
1175 sp = sp_next;
1176 } while (sp);
1177 }
1178
1179 /* DDP */
1180 for (gref = ddp_head.atpcb_next; gref != &ddp_head;
1181 gref = gref->atpcb_next) {
1182 if (count_only) {
1183 active_skts++;
1184 } else {
1185 dPrintf(D_M_DDP,D_L_TRACE, ("ddp pid=%d\n", gref->pid));
1186 atalk_notify(gref, ESHUTDOWN);
1187 }
1188 }
1189 if (count_only || active_skts) {
1190 splx(s);
1191 return(active_skts);
1192
1193 }
1194 /* if there are no interfaces in the process of going online, continue shutting down DDP */
1195 for (i = 0; i < IF_TOTAL_MAX; i++) {
1196 if (at_interfaces[i].startup_inprogress == TRUE)
1197 return(1);
1198 }
1199 if (MULTIPORT_MODE) {
1200 rtmp_shutdown();
1201 /* free memory allocated for the rtmp/zip tables */
1202 if (ZT_table) {
1203 FREE(ZT_table, M_RTABLE);
1204 ZT_table = (ZT_entry *)NULL;
1205 }
1206 if (RT_table) {
1207 FREE(RT_table, M_RTABLE);
1208 RT_table = (RT_entry *)NULL;
1209 }
1210 }
1211
1212 at_state.flags = 0; /* make sure inits are done on restart */
1213
1214 wakeup(&ifID_home->startup_inprogress); /* if rtmp_router_start still starting up */
1215
1216 /* from original ddp_shutdown() */
1217 routershutdown();
1218 ddp_brt_shutdown();
1219
1220 if (adspInited) {
1221 CleanupGlobals();
1222 adspInited = 0;
1223 }
1224
1225
1226 dPrintf(D_M_DDP, D_L_VERBOSE, ("DDP shutdown completed"));
1227
1228 /*
1229 * make sure we don't have a probe timeout hanging around
1230 * it's going to try and make use of an entry in at_interfaces
1231 * which is going to be zero'd out by the call to ddp_start a
1232 * little further down
1233 */
1234 untimeout(aarp_sched_probe, 0);
1235
1236 /* *** after an SIOCSIFADDR and before an AIOCSIFADDR,
1237 this is the only place to find the ifID *** */
1238 for (i = 0; i < IF_TOTAL_MAX; i++) {
1239 ifID = &at_interfaces[i];
1240 /* do LAP_IOC_OFFLINE processing */
1241 elap_offline(ifID);
1242 }
1243 ddp_start();
1244
1245 splx(s);
1246 return(0);
1247 } /* ddp_shutdown */
1248
1249 int routerStart(keP)
1250 at_kern_err_t *keP;
1251 {
1252 register at_ifaddr_t *ifID;
1253 int error;
1254
1255 if (! ifID_home)
1256 return(EINVAL);
1257
1258 /*
1259 * this will cause the ports to glean from the net the relevant
1260 * information before forwarding
1261 */
1262 TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
1263 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
1264 ("routerStart Port %d (%s) set to activating\n",
1265 ifID->ifPort, ifID->ifName));
1266 ifID->ifRoutingState = PORT_ACTIVATING;
1267 ifID->ifFlags |= RTR_XNET_PORT;
1268 }
1269
1270 /*
1271 * The next step is to check the information for each port before
1272 * declaring the ports up and forwarding
1273 */
1274 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
1275 ("router_start: waiting 20 sec before starting up\n"));
1276
1277 /* sleep for 20 seconds */
1278 if ((error =
1279 /* *** eventually this will be the ifID for the interface
1280 being brought up in router mode *** */
1281 tsleep(&ifID_home->startup_inprogress,
1282 PSOCK | PCATCH, "routerStart", 20 * SYS_HZ))
1283 != EWOULDBLOCK) {
1284 /*
1285 if (!error)
1286 panic("routerStart: spurious interrupt");
1287 */
1288 return(error);
1289 }
1290
1291 return(rtmp_router_start(keP));
1292 /* was timeout(rtmp_router_start, 0, 20 * SYS_HZ); */
1293 } /* routerStart */
1294
1295 void ZIPwakeup(elapp, ZipError)
1296 at_ifaddr_t *elapp;
1297 int ZipError;
1298 {
1299 int s, error = ZipError;
1300
1301 ATDISABLE(s, ddpinp_lock);
1302 if ( (elapp != NULL) && elapp->startup_inprogress) {
1303 ATENABLE(s, ddpinp_lock);
1304
1305 /* was ZIPContinue */
1306 /* was elapp_online() with jump to ZIP_sleep */
1307
1308 /* instead of the goto ZIP_sleep ... */
1309 switch (ZipError) {
1310 case 0 : /* success */
1311 elapp->ifState = LAP_ONLINE;
1312
1313 /* Send event with zone info. */
1314 atalk_post_msg(elapp->aa_ifp, KEV_ATALK_ZONEUPDATED, 0, &(elapp->ifZoneName));
1315
1316 break;
1317 case ZIP_RE_AARP :
1318 /* instead of goto re_aarp; */
1319 /* We now call aarp_init() to assign an
1320 appletalk node addr */
1321 if ((elapp->startup_error = re_aarp(elapp))) {
1322 elapp->startup_inprogress = FALSE;
1323 wakeup(&elapp->startup_inprogress);
1324 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
1325 ("elap_online: ack 2\n"));
1326 }
1327 break;
1328 default :
1329 break;
1330 }
1331 if (ZipError != ZIP_RE_AARP) {
1332 elapp->startup_error = error;
1333 elapp->startup_inprogress = FALSE;
1334 wakeup(&elapp->startup_inprogress);
1335 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
1336 ("elap_online: ifZipError=%d\n", error));
1337 }
1338 } else
1339 ATENABLE(s, ddpinp_lock);
1340 } /* ZIPwakeup */
1341
1342 void AARPwakeup(probe_cb)
1343 aarp_amt_t *probe_cb;
1344 {
1345 int s;
1346 int errno;
1347 at_ifaddr_t *elapp;
1348
1349 ATDISABLE(s, arpinp_lock);
1350 elapp = probe_cb->elapp;
1351 if ( (elapp != NULL) && elapp->startup_inprogress && elapp->aa_ifp != 0) {
1352 ATENABLE(s, arpinp_lock);
1353
1354 /* was AARPContinue */
1355 errno = aarp_init2(elapp);
1356 /* aarp_init2() returns either -1 or 0 */
1357 if (errno != 0) {
1358 dPrintf(D_M_ELAP, D_L_STATE_CHG,
1359 ("elap_online aarp_init for %s\n",
1360 elapp->ifName));
1361 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->ZoneMcastAddr);
1362 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
1363 elapp->ifState = LAP_OFFLINE;
1364 ddp_rem_if(elapp);
1365 elapp->startup_error = EADDRNOTAVAIL;
1366 elapp->startup_inprogress = FALSE;
1367 wakeup(&elapp->startup_inprogress);
1368 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online: ack 2\n"));
1369 } else {
1370 dPrintf(D_M_ELAP,D_L_STARTUP_INFO,
1371 ("elap_online: aarp_init returns zero\n"));
1372 elap_online2(elapp);
1373 }
1374 } else
1375 ATENABLE(s, arpinp_lock);
1376 } /* AARPwakeup */
1377
1378 void ddp_bit_reverse(addr)
1379 unsigned char *addr;
1380 {
1381 static unsigned char reverse_data[] = {
1382 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1383 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1384 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1385 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1386 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1387 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1388 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1389 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1390 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1391 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1392 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1393 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1394 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1395 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1396 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1397 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1398 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1399 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1400 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1401 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1402 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1403 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1404 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1405 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1406 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1407 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1408 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1409 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1410 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1411 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1412 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1413 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1414 };
1415
1416 unsigned char k;
1417
1418 for (k=0; k < 6; k++)
1419 addr[k] = reverse_data[addr[k]];
1420 }
1421
1422 static int elap_trackMcast(patp, func, addr)
1423 at_ifaddr_t *patp;
1424 int func;
1425 caddr_t addr;
1426 {
1427 int i, loc=-1;
1428 u_char c;
1429 switch(patp->aa_ifp->if_type) {
1430 case IFT_ETHER:
1431 case IFT_FDDI:
1432 /* set addr to point to unique part of addr */
1433 c = addr[5];
1434
1435 /* first try to find match */
1436 /* *** save just one byte of the multicast address? *** */
1437 for (i=0; i< MAX_MCASTS; i++)
1438 if (c == patp->mcast[i]) {
1439 loc = i;
1440 break;
1441 }
1442
1443 switch (func) {
1444 case MCAST_TRACK_DELETE:
1445 if (loc >= 0)
1446 patp->mcast[loc] = 0;
1447
1448 break;
1449 case MCAST_TRACK_ADD:
1450 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add loc:%d\n", i));
1451 if (loc >= 0) {
1452 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, addr was there\n"));
1453 return(1);
1454 break; /* already there */
1455 }
1456 for (i=0; i< MAX_MCASTS; i++)
1457 if (patp->mcast[i] == 0) {
1458 loc = i;
1459 break;
1460 }
1461 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add1 loc:%d\n", i));
1462 if (loc >= 0) {
1463 patp->mcast[loc] = c;
1464 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, adding(%x)\n",
1465 (*(int*)addr)&0xffffff));
1466 }
1467 else {
1468 /*errno = ENOMEM; */ /*LD 5/7/97 nobody is using that */
1469 return(-1);
1470 }
1471 break;
1472 case MCAST_TRACK_CHECK:
1473 if (loc >= 0) {
1474 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:check, addr was there\n"));
1475 return(0);
1476 }
1477 else {
1478 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, addr was NOT there\n"));
1479 return(-1);
1480 }
1481
1482 default:
1483 /*errno = EINVAL;*/ /*LD 5/7/97 nobody is using that */
1484 return(-1);
1485 }
1486
1487 case IFT_ISO88025: /* token ring */
1488 /* we would use the lowest byte of the addr argument as a value
1489 to shift left a 1 to form the mcast mask for TR. We'll do this
1490 when the time comes
1491 */
1492 default:
1493 ;
1494 }
1495 return(0);
1496 }
1497
1498
1499 static getSnmpCfg(snmp)
1500 snmpCfg_t *snmp;
1501 {
1502 int i;
1503 at_ifaddr_t *elapp;
1504 snmpIfCfg_t *ifc;
1505
1506 snmp->cfg_ifCnt = 0;
1507
1508 bzero(snmp,sizeof(snmpCfg_t));
1509 for (i=0, elapp=at_interfaces,ifc=snmp->cfg_ifCfg;
1510 i<IF_TOTAL_MAX; i++, elapp++, ifc++) {
1511 if (elapp->ifState != LAP_OFFLINE) {
1512 snmp->cfg_ifCnt++;
1513 strncpy(ifc->ifc_name,elapp->ifName, sizeof(ifc->ifc_name));
1514 ifc->ifc_aarpSize = getAarpTableSize(i);
1515 ifc->ifc_addrSize = getPhysAddrSize(i);
1516 switch (elapp->aa_ifp->if_type) {
1517 case IFT_ETHER:
1518 ifc->ifc_type = SNMP_TYPE_ETHER2;
1519 break;
1520 case IFT_ISO88025: /* token ring */
1521 ifc->ifc_type = SNMP_TYPE_TOKEN;
1522 break;
1523 case IFT_FDDI:
1524 default:
1525 ifc->ifc_type = SNMP_TYPE_OTHER;
1526 break;
1527 }
1528 ifc->ifc_start = elapp->ifThisCableStart;
1529 ifc->ifc_end = elapp->ifThisCableEnd;
1530 ifc->ifc_ddpAddr= elapp->ifThisNode;
1531 ifc->ifc_status = elapp->ifState == LAP_ONLINE ? 1 : 2;
1532 ifc->ifc_zoneName.len = 0;
1533 if (elapp->ifZoneName.len != 0) {
1534 ifc->ifc_zoneName = elapp->ifZoneName;
1535 }
1536 else if (elapp->ifDefZone) {
1537 ifc->ifc_zoneName = ZT_table[elapp->ifDefZone-1].Zone;
1538 }
1539 else /* temp, debug only */
1540 ifc->ifc_zoneName = ZT_table[0].Zone;
1541 if (ROUTING_MODE) {
1542 if (elapp->ifFlags & RTR_SEED_PORT) {
1543 ifc->ifc_netCfg = SNMP_CFG_CONFIGURED;
1544 ifc->ifc_zoneCfg = SNMP_CFG_CONFIGURED;
1545 }
1546 else {
1547 ifc->ifc_netCfg = SNMP_CFG_GARNERED;
1548 ifc->ifc_zoneCfg = SNMP_CFG_GARNERED;
1549 }
1550 }
1551 else { /* single-port mode */
1552 if (elapp->ifRouterState == ROUTER_AROUND) {
1553 ifc->ifc_netCfg = SNMP_CFG_GARNERED;
1554 }
1555 else {
1556 ifc->ifc_netCfg = SNMP_CFG_GUESSED;
1557 ifc->ifc_zoneCfg = SNMP_CFG_UNCONFIG;
1558 }
1559 }
1560 }
1561 }
1562 snmp->cfg_flags = at_state.flags;
1563
1564
1565 return(0);
1566 }
1567
1568 int at_reg_mcast(ifID, data)
1569 at_ifaddr_t *ifID;
1570 caddr_t data;
1571 {
1572 struct ifnet *nddp = ifID->aa_ifp;
1573 struct sockaddr sa;
1574
1575 if (*(int *)data) {
1576 if (!nddp) {
1577 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
1578 return(-1);
1579 }
1580
1581 if (elap_trackMcast(ifID, MCAST_TRACK_ADD, data) == 1)
1582 return(0);
1583
1584 /* this is for ether_output */
1585 sa.sa_family = AF_UNSPEC;
1586 sa.sa_len = 2 + sizeof(struct etalk_addr);
1587 bcopy (data, &sa.sa_data[0], sizeof(struct etalk_addr));
1588
1589 dPrintf(D_M_PAT, D_L_STARTUP,
1590 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1591 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff,
1592 (unsigned)ifID));
1593
1594 if (if_addmulti(nddp, &sa, 0))
1595 return -1;
1596 }
1597 return 0;
1598
1599 }
1600
1601 int at_unreg_mcast(ifID, data)
1602 at_ifaddr_t *ifID;
1603 caddr_t data;
1604 {
1605 struct ifnet *nddp = ifID->aa_ifp;
1606 struct sockaddr sa;
1607
1608 if (*(int *)data) {
1609 if (!nddp) {
1610 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
1611 return(-1);
1612 }
1613
1614 elap_trackMcast(ifID, MCAST_TRACK_DELETE, data);
1615
1616 /* this is for ether_output */
1617 sa.sa_family = AF_UNSPEC;
1618 sa.sa_len = 2 + sizeof(struct etalk_addr);
1619 bcopy (data, &sa.sa_data[0], sizeof(struct etalk_addr));
1620
1621 dPrintf(D_M_PAT, D_L_STARTUP,
1622 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1623 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff,
1624 (unsigned)ifID));
1625 bzero(data, sizeof(struct etalk_addr));
1626
1627 if (if_delmulti(nddp, &sa))
1628 return -1;
1629 }
1630 return 0;
1631 }
1632 #ifdef NOT_YET
1633 /* *** at_reg_mcast() and at_unreg_mcast() should be replaced as soon as the
1634 new code to allow an AF_LINK address family multicast to be (un)registered
1635 using the SIOCADDMULTI / SIOCDELMULTI ioctls has been completed.
1636
1637 The issue is that the "struct sockaddr_dl" needed for the AF_LINK does not
1638 fit in the "struct ifreq" that is used for these ioctls, and we do not want
1639 Blue/Classic, which currently uses AF_UNSPEC, to use a different address
1640 family multicast address than Mac OS X uses.
1641 *** */
1642
1643 int at_reg_mcast(ifID, data)
1644 at_ifaddr_t *ifID;
1645 caddr_t data;
1646 {
1647 struct ifnet *nddp = ifID->aa_ifp;
1648 struct sockaddr_dl sdl;
1649
1650 if (*(int *)data) {
1651 if (!nddp) {
1652 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
1653 return(-1);
1654 }
1655 if (elap_trackMcast(ifID, MCAST_TRACK_ADD, data) == 1)
1656 return(0);
1657
1658 sdl.sdl_len = sizeof(struct sockaddr_dl);
1659 sdl.sdl_family = AF_LINK;
1660 sdl.sdl_index = 0;
1661 sdl.sdl_type = nddp->if_type;
1662 sdl.sdl_alen = nddp->if_addrlen;
1663 sdl.sdl_slen = 0;
1664 sdl.sdl_nlen = sprintf(sdl.sdl_data, "%s%d",
1665 nddp->if_name , nddp->if_unit);
1666 bcopy(data, LLADDR(&sdl), sdl.sdl_alen);
1667
1668 dPrintf(D_M_PAT, D_L_STARTUP,
1669 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1670 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff,
1671 (unsigned)ifID));
1672
1673 if (if_addmulti(nddp, (struct sockaddr *)&sdl, 0))
1674 return -1;
1675 }
1676
1677 return 0;
1678 }
1679
1680 int at_unreg_mcast(ifID, data)
1681 at_ifaddr_t *ifID;
1682 caddr_t data;
1683 {
1684 struct ifnet *nddp = ifID->aa_ifp;
1685 struct sockaddr_dl sdl;
1686
1687 if (*(int *)data) {
1688 if (!nddp) {
1689 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
1690 return(-1);
1691 }
1692
1693 elap_trackMcast(ifID, MCAST_TRACK_DELETE, data);
1694
1695 sdl.sdl_len = sizeof(struct sockaddr_dl);
1696 sdl.sdl_family = AF_LINK;
1697 sdl.sdl_index = 0;
1698 sdl.sdl_type = nddp->if_type;
1699 sdl.sdl_alen = nddp->if_addrlen;
1700 sdl.sdl_slen = 0;
1701 sdl.sdl_nlen = sprintf(sdl.sdl_data, "%s%d",
1702 nddp->if_name , nddp->if_unit);
1703
1704 dPrintf(D_M_PAT, D_L_STARTUP,
1705 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1706 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff,
1707 (unsigned)ifID));
1708 bzero(data, ETHERNET_ADDR_LEN);
1709
1710 if (if_delmulti(nddp, (struct sockaddr *)&sdl))
1711 return(-1);
1712 }
1713
1714 return 0;
1715 }
1716
1717 #endif