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