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