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