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