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