2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1988, 1989, 1993-1998 Apple Computer, Inc.
26 /* at_elap.c: 2.0, 1.29; 10/4/93; Apple Computer, Inc. */
28 /* This is the file which implements all the streams driver
29 * functionality required for EtherTalk.
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').
38 Modified for MP, 1996 by Tuyen Nguyen
39 Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
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>
51 #include <sys/filedesc.h>
52 #include <sys/fcntl.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 #include <vm/vm_kern.h> /* for kernel_map */
63 #include <net/if_types.h>
65 #include <netat/sysglue.h>
66 #include <netat/appletalk.h>
67 #include <netat/at_var.h>
68 #include <netat/ddp.h>
69 #include <netat/lap.h>
70 #include <netat/routing_tables.h> /* rtmp+zip table structs */
71 #include <netat/zip.h>
72 #include <netat/nbp.h>
73 #include <netat/at_snmp.h>
74 #include <netat/at_pcb.h>
75 #include <netat/at_aarp.h>
76 #include <netat/asp.h>
77 #include <netat/atp.h>
78 #include <netat/debug.h>
79 #include <netat/adsp.h>
80 #include <netat/adsp_internal.h>
82 #include <sys/kern_event.h>
86 at_ifaddr_t at_interfaces
[IF_TOTAL_MAX
];
87 /* index for at_interfaces is not important */
88 at_ifaddr_t
*ifID_table
[IF_TOTAL_MAX
];
89 /* the table of ifID structures, one per interface
91 * NOTE: for MH, entry 0 in this table is
92 * now defined to be the default I/F
94 at_ifaddr_t
*ifID_home
;
95 /* always ifID_table[IFID_HOME] for now, but will be used for
96 dynamic "home port" assignment, later */
98 at_state_t at_state
; /* global state of AT network */
99 snmpFlags_t snmpFlags
;
104 #define MAX_BUFSIZE 8192
105 #define MAX_RTMP (MAX_BUFSIZE/sizeof(RT_entry)-1)
107 ((MAX_BUFSIZE - SNMP_NBP_HEADER_SIZE)/sizeof(snmpNbpEntry_t)-1)
108 #define MAX_NBP_BYTES (MAX_NBP * sizeof(snmpNbpEntry_t))
109 #define MAX_ZIP (MAX_BUFSIZE/sizeof(ZT_entry)-1)
110 #define MAX_RTMP_BYTES (MAX_RTMP * sizeof(RT_entry))
111 #define MAX_ZIP_BYTES (MAX_ZIP * sizeof(ZT_entry))
114 extern TAILQ_HEAD(name_registry
, _nve_
) name_registry
;
115 extern snmpStats_t snmpStats
;
116 extern atlock_t ddpinp_lock
;
117 extern atlock_t arpinp_lock
;
118 extern short appletalk_inited
;
119 extern int adspInited
;
120 extern struct atpcb ddp_head
;
121 extern gref_t
*atp_inputQ
[];
122 extern struct atp_state
*atp_used_list
;
123 extern asp_scb_t
*asp_scbQ
[];
124 extern asp_scb_t
*scb_used_list
;
125 extern CCB
*adsp_inputQ
[];
126 extern CCB
*ccb_used_list
;
127 extern at_ddp_stats_t at_ddp_stats
;
130 extern snmpAarpEnt_t
* getAarp(int *);
131 extern void nbp_shutdown(), routershutdown(), ddp_brt_shutdown();
132 extern void ddp_brt_init(), rtmp_init(), rtmp_input();
133 extern rtmp_router_start(at_kern_err_t
*);
134 static void getIfNames(at_ifnames_t
*);
135 static void add_route();
136 static int set_zones();
138 static int elap_online1(), re_aarp();
139 int at_reg_mcast(), at_unreg_mcast();
140 void AARPwakeup(), ZIPwakeup();
141 static void elap_hangup();
144 at_ifaddr_t
*find_ifID(if_name
)
150 for (pat_id
=0; pat_id
< xpatcnt
; pat_id
++) {
151 if (!strcmp(at_interfaces
[pat_id
].ifName
, if_name
))
152 return(&at_interfaces
[pat_id
]);
155 return((at_ifaddr_t
*)NULL
);
158 static int validate_msg_size(m
, gref
, elapp
)
163 /* checks ioctl message type for minimum expected message size &
164 sends error back if size invalid
167 register ioc_t
*iocbp
;
168 register at_if_cfg_t
*cfgp
;
172 iocbp
= (ioc_t
*) gbuf_rptr(m
);
174 dPrintf(D_M_ELAP
, D_L_INFO
, ("validate_msg_size: ioc_cmd = %d\n",
176 switch (iocbp
->ioc_cmd
) {
177 case LAP_IOC_ADD_ROUTE
:
178 size
= sizeof(RT_entry
);
180 case LAP_IOC_GET_ROUTE
:
181 size
= sizeof(RT_entry
);
183 case LAP_IOC_GET_ZONE
:
184 size
= sizeof(ZT_entryno
);
186 case LAP_IOC_SNMP_GET_CFG
:
187 case LAP_IOC_SNMP_GET_AARP
:
188 case LAP_IOC_SNMP_GET_ZIP
:
189 case LAP_IOC_SNMP_GET_RTMP
:
190 case LAP_IOC_SNMP_GET_NBP
:
194 case ELAP_IOC_GET_STATS
:
195 case LAP_IOC_SNMP_GET_DDP
:
200 dPrintf(D_M_ELAP
, D_L_ERROR
, ("validate_msg_size: unknown ioctl\n"));
204 if (size
== 0) { /* a non-data ioctl */
208 if (gbuf_cont(m
) != NULL
)
209 i
= gbuf_len(gbuf_cont(m
));
210 if (iocbp
->ioc_count
< size
|| (gbuf_cont(m
) == NULL
) || i
< size
) {
211 dPrintf(D_M_ELAP
, D_L_ERROR
,
212 ("ioctl msg error:s:%d c:%d bcont:%c delta:%d\n",
213 size
, iocbp
->ioc_count
,
214 gbuf_cont(m
)? 'Y' : 'N', i
));
220 ioc_ack(EMSGSIZE
, m
, gref
);
222 } /* validate_msg_size */
224 int lap_online(elapp
, cfgp
)
230 if (elapp
->ifState
!= LAP_OFFLINE
) {
235 if (cfgp
->flags
& ELAP_CFG_HOME
) {
237 /* only 1 home allowed! */
240 dPrintf(D_M_ELAP
, D_L_STARTUP
,
241 ("elap_wput home I/F:%s\n", cfgp
->ifr_name
));
242 elapp
->flags
|= ELAP_CFG_HOME
;
245 if (MULTIPORT_MODE
) {
246 elapp
->flags
|= ELAP_CFG_ZONELESS
;
247 if (ROUTING_MODE
&& cfgp
->netStart
)
248 elapp
->flags
|= ELAP_CFG_SEED
;
251 if (!DEFAULT_ZONE(&cfgp
->zonename
) &&
252 (elapp
->flags
& ELAP_CFG_HOME
) || MULTIHOME_MODE
) {
253 elapp
->startup_zone
= cfgp
->zonename
;
256 if (elapp
->flags
& ELAP_CFG_SEED
) {
257 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
258 ("elap_wput: found to be seed\n"));
259 elapp
->ifThisCableStart
= cfgp
->netStart
;
260 elapp
->ifThisCableEnd
= cfgp
->netEnd
;
263 dPrintf(D_M_ELAP
,D_L_ERROR
,
264 ("elap_wput: we believe we're not seed\n"));
265 /* from ELAP_IOC_SET_CFG */
266 if (ATALK_VALUE(cfgp
->node
)) {
270 initial_node
= cfgp
->node
.s_node
;
271 initial_net
= cfgp
->node
.s_net
;
272 if ((initial_node
<0xfe) && (initial_node
>0) &&
273 !((initial_net
== 0) ||
274 ((initial_net
>= DDP_STARTUP_LOW
)&&
275 (initial_net
<= DDP_STARTUP_HIGH
)))) {
277 elapp
->initial_addr
= cfgp
->node
;
282 elapp
->startup_error
= 0;
283 elapp
->startup_inprogress
= FALSE
;
284 if ((error
= elap_online1(elapp
)))
287 if (!(MULTIPORT_MODE
) &&
288 elapp
->ifZoneName
.len
== 1 &&
289 elapp
->ifZoneName
.str
[0] == '*' &&
290 !DEFAULT_ZONE(&cfgp
->zonename
)) {
291 nbp_add_multicast(&cfgp
->zonename
, elapp
);
296 /***********************************************************************
299 **********************************************************************/
300 int elap_wput(gref
, m
)
305 register ioc_t
*iocbp
;
306 register at_if_cfg_t
*cfgp
;
307 at_elap_stats_t
*statsp
;
314 switch (gbuf_type(m
)) {
317 dPrintf(D_M_ELAP
,D_L_ERROR
,
318 ("Output data to control channel is ignored\n"));
322 iocbp
= (ioc_t
*) gbuf_rptr(m
);
324 if (validate_msg_size(m
, gref
, &elapp
))
328 cfgp
= (at_if_cfg_t
*) gbuf_rptr(gbuf_cont(m
));
330 if (LAP_IOC_MYIOCTL(iocbp
->ioc_cmd
) ||
331 ELAP_IOC_MYIOCTL(iocbp
->ioc_cmd
)) {
333 switch (iocbp
->ioc_cmd
) {
334 case ELAP_IOC_GET_STATS
:
335 #ifdef APPLETALK_DEBUG
336 kprintf("LAP_IOC_GET_STATS\n");
338 if ( (gbuf_cont(m
) == NULL
)
339 || (elapp
= find_ifID(gbuf_rptr(gbuf_cont(m
)))) == NULL
) {
340 ioc_ack(EINVAL
, m
, gref
);
343 gbuf_freem(gbuf_cont(m
));
344 if ((gbuf_cont(m
) =gbuf_alloc(sizeof(at_elap_stats_t
),
346 ioc_ack(ENOBUFS
, m
, gref
);
349 statsp
= ((at_elap_stats_t
*)gbuf_rptr(gbuf_cont(m
)));
350 *statsp
= elapp
->stats
;
351 gbuf_wset(gbuf_cont(m
),sizeof(at_elap_stats_t
));
352 iocbp
->ioc_count
= sizeof(at_elap_stats_t
);
356 case LAP_IOC_ADD_ROUTE
:
357 #ifdef APPLETALK_DEBUG
358 kprintf("LAP_IOC_ADD_ROUTE\n");
360 add_route((RT_entry
*)gbuf_rptr(gbuf_cont(m
)));
364 case LAP_IOC_GET_ZONE
:
365 #ifdef APPLETALK_DEBUG
366 kprintf("LAP_IOC_GET_ZONE\n");
368 /* return next ZT_entryno from ZT_table
369 a pointer to the struct ZT_entryno is passed down from
370 user space and the first byte is cast to a int, if
371 this int is non-zero, then the first ZT_entry is
372 returned and subsequent calls with a zero value
373 will return the next entry in the table. The next
374 read after the last valid entry will return EINVAL
379 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
380 gbuf_freem(gbuf_cont(m
));
383 pZTe
= zt_getNextZone(i
);
385 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(ZT_entryno
), PRI_MED
)) == NULL
) {
386 ioc_ack(ENOBUFS
, m
, gref
);
389 *(ZT_entryno
*)gbuf_rptr(gbuf_cont(m
)) = *pZTe
;
390 gbuf_wset(gbuf_cont(m
),sizeof(ZT_entryno
));
391 iocbp
->ioc_count
= sizeof(ZT_entryno
);
395 ioc_ack(EINVAL
, m
, gref
);
399 case LAP_IOC_GET_ROUTE
:
400 #ifdef APPLETALK_DEBUG
401 kprintf("LAP_IOC_GET_ROUTE\n");
403 /* return next RT_entry from RT_table
404 * a pointer to the struct RT_entry is
405 * passed down from user space and the first
406 * byte is cast to a int, if this int is
407 * non-zero, then the first RT_entry is
408 * returned and subsequent calls with a
409 * zero value will return the next entry in
410 * the table. The next read after the last
411 * valid entry will return EINVAL
416 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
417 gbuf_freem(gbuf_cont(m
));
420 pRT
= rt_getNextRoute(i
);
422 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(RT_entry
), PRI_MED
)) == NULL
) {
423 ioc_ack(ENOBUFS
, m
, gref
);
426 *(RT_entry
*)gbuf_rptr(gbuf_cont(m
)) = *pRT
;
427 gbuf_wset(gbuf_cont(m
),sizeof(RT_entry
));
428 iocbp
->ioc_count
= sizeof(RT_entry
);
432 ioc_ack(EINVAL
, m
, gref
);
436 case LAP_IOC_SNMP_GET_DDP
:
437 #ifdef APPLETALK_DEBUG
438 kprintf("LAP_IOC_SNMP_GET_DDP\n");
440 if (!(at_state
.flags
& AT_ST_STARTED
)) {
441 ioc_ack(ENOTREADY
, m
, gref
);
444 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(snmpStats_t
),
446 ioc_ack(ENOBUFS
, m
, gref
);
450 *(snmpStats_t
*)gbuf_rptr(gbuf_cont(m
)) = snmpStats
;
451 gbuf_wset(gbuf_cont(m
),sizeof(snmpStats
));
452 iocbp
->ioc_count
= sizeof(snmpStats
);
455 case LAP_IOC_SNMP_GET_CFG
:
456 #ifdef APPLETALK_DEBUG
457 kprintf("LAP_IOC_SNMP_GET_CFG\n");
463 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
464 gbuf_freem(gbuf_cont(m
));
466 if (!(at_state
.flags
& AT_ST_STARTED
)) {
468 iocbp
->ioc_count
= 0;
469 ioc_ack(ENOTREADY
, m
, gref
);
470 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
471 ("elap_wput: cfg req, stack down\n"));
474 if (i
== UPDATE_IF_CHANGED
&&
475 !(at_state
.flags
& AT_ST_IF_CHANGED
)) {
476 iocbp
->ioc_count
= 0;
478 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
479 ("elap_wput: cfg req, unchanged\n"));
482 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
483 ("elap_wput: cfg req, changed\n"));
485 if (getSnmpCfg(&snmp
)) {
486 dPrintf(D_M_ELAP
,D_L_ERROR
,
487 ("elap_wput:SNMP_GET_CFG error\n"));
488 ioc_ack(EOPNOTSUPP
, m
, gref
);
491 /* send up only used part of table */
492 size
= sizeof(snmp
) -
493 sizeof(snmpIfCfg_t
) * (MAX_IFS
- snmp
.cfg_ifCnt
);
495 if ((gbuf_cont(m
) = gbuf_alloc(size
, PRI_MED
)) == NULL
) {
496 ioc_ack(ENOBUFS
, m
, gref
);
499 bcopy(&snmp
,gbuf_rptr(gbuf_cont(m
)),size
);
500 gbuf_wset(gbuf_cont(m
),size
);
501 iocbp
->ioc_count
= size
;
502 at_state
.flags
&= ~AT_ST_IF_CHANGED
;
507 case LAP_IOC_SNMP_GET_AARP
:
509 snmpAarpEnt_t
*snmpp
;
511 #ifdef APPLETALK_DEBUG
512 kprintf("LAP_IOC_SNMP_GET_AARP\n");
514 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
515 gbuf_freem(gbuf_cont(m
));
517 dPrintf(D_M_ELAP
,D_L_INFO
,
518 ("elap_wput:calling getarp,i=%d\n", i
));
520 bytes
= i
* sizeof(snmpAarpEnt_t
);
521 dPrintf(D_M_ELAP
,D_L_INFO
,
522 ("elap_wput:getarp returned, i=%d,bytes=%d\n",
525 if ((gbuf_cont(m
) = gbuf_alloc(bytes
, PRI_MED
)) == NULL
) {
526 ioc_ack(ENOBUFS
, m
, gref
);
529 bcopy(snmpp
, gbuf_rptr(gbuf_cont(m
)), bytes
);
530 gbuf_wset(gbuf_cont(m
),bytes
);
531 iocbp
->ioc_count
= bytes
;
535 ioc_ack(EOPNOTSUPP
, m
, gref
);
539 case LAP_IOC_SNMP_GET_ZIP
:
540 #ifdef APPLETALK_DEBUG
541 kprintf("LAP_IOC_SNMP_GET_ZIP\n");
543 { /* matching brace NOT in this case */
545 register int size
, total
, tabsize
;
546 gbuf_t
*mn
; /* new gbuf */
547 gbuf_t
*mo
; /* old gbuf */
548 gbuf_t
*mt
; /* temp */
551 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
552 gbuf_freem(gbuf_cont(m
));
554 if (!(at_state
.flags
& AT_ST_STARTED
)) {
555 ioc_ack(ENOTREADY
, m
, gref
);
558 if (i
== UPDATE_IF_CHANGED
&&
559 !(at_state
.flags
& AT_ST_ZT_CHANGED
)) {
560 iocbp
->ioc_count
= 0;
565 tabsize
= getZipTableSize();
567 /* retrieve table into multiple gbufs */
568 for (i
=0; i
<tabsize
; i
+=j
) {
570 MAX_ZIP
? MAX_ZIP
: tabsize
- i
;
571 size
= j
< MAX_ZIP
? sizeof(ZT_entry
)*j
: MAX_ZIP_BYTES
;
572 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
574 gbuf_freem(gbuf_cont(m
));
575 ioc_ack(ENOBUFS
, m
, gref
);
578 if (!mo
) { /* if first new one */
587 getZipTable((ZT_entry
*)gbuf_rptr(mn
),i
,j
);
590 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
593 iocbp
->ioc_count
= 0;
594 ioc_ack(ENOBUFS
, m
, gref
);
598 dPrintf(D_M_ELAP
,D_L_WARNING
,
599 ("elap_wput:snmp: empty zip table\n"));
602 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
603 gbuf_wset(gbuf_cont(m
),sizeof(int));
604 iocbp
->ioc_count
= sizeof(int);
607 atalk_putnext(gref
,mt
); /* send up table */
608 at_state
.flags
&= ~AT_ST_ZT_CHANGED
;
611 case LAP_IOC_SNMP_GET_RTMP
:
612 #ifdef APPLETALK_DEBUG
613 kprintf("LAP_IOC_SNMP_GET_RTMP\n");
615 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
616 gbuf_freem(gbuf_cont(m
));
618 if (!(at_state
.flags
& AT_ST_STARTED
)) {
619 ioc_ack(ENOTREADY
, m
, gref
);
622 if (i
== UPDATE_IF_CHANGED
&&
623 !(at_state
.flags
& AT_ST_RT_CHANGED
)) {
624 iocbp
->ioc_count
= 0;
630 tabsize
= getRtmpTableSize();
632 /* retrieve table into multiple gbufs */
633 for (i
=0; i
<tabsize
; i
+=j
) {
635 MAX_RTMP
? MAX_RTMP
: tabsize
- i
;
636 size
= j
< MAX_RTMP
? sizeof(RT_entry
)*j
: MAX_RTMP_BYTES
;
637 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
639 gbuf_freem(gbuf_cont(m
));
640 ioc_ack(ENOBUFS
, m
, gref
);
643 if (!mo
) { /* if first new one */
652 getRtmpTable((RT_entry
*)gbuf_rptr(mn
),i
,j
);
655 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
658 iocbp
->ioc_count
= 0;
659 ioc_ack(ENOBUFS
, m
, gref
);
664 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
665 gbuf_wset(gbuf_cont(m
),sizeof(int));
666 iocbp
->ioc_count
= sizeof(int);
669 atalk_putnext(gref
,mt
); /* send up table */
670 at_state
.flags
&= ~AT_ST_RT_CHANGED
;
673 case LAP_IOC_SNMP_GET_NBP
:
674 #ifdef APPLETALK_DEBUG
675 kprintf("LAP_IOC_SNMP_GET_NBP\n");
677 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
678 gbuf_freem(gbuf_cont(m
));
680 if (!(at_state
.flags
& AT_ST_STARTED
)) {
681 ioc_ack(ENOTREADY
, m
, gref
);
684 if (i
== UPDATE_IF_CHANGED
&&
685 !(at_state
.flags
& AT_ST_NBP_CHANGED
)) {
686 iocbp
->ioc_count
= 0;
688 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
689 ("elap_wput: nbp req denied, no change\n"));
694 tabsize
= getNbpTableSize();
696 /* retrieve table into multiple gbufs */
697 for (i
=0; i
<tabsize
; i
+=j
) {
699 MAX_NBP
? MAX_NBP
: tabsize
- i
;
700 size
= j
< MAX_NBP
? sizeof(snmpNbpEntry_t
)*j
: MAX_NBP_BYTES
;
702 size
+= SNMP_NBP_HEADER_SIZE
;
703 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
705 gbuf_freem(gbuf_cont(m
));
706 ioc_ack(ENOBUFS
, m
, gref
);
709 if (!mo
) { /* if first new one */
712 nbp
= (snmpNbpTable_t
*)gbuf_rptr(mn
);
713 nbp
->nbpt_entries
= tabsize
;
714 nbp
->nbpt_zone
= ifID_home
->ifZoneName
;
715 getNbpTable(nbp
->nbpt_table
,i
,j
);
720 getNbpTable((snmpNbpEntry_t
*)gbuf_rptr(mn
),i
,j
);
725 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
728 iocbp
->ioc_count
= 0;
729 ioc_ack(ENOBUFS
, m
, gref
);
734 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
735 gbuf_wset(gbuf_cont(m
),sizeof(int));
736 iocbp
->ioc_count
= sizeof(int);
739 atalk_putnext(gref
,mt
); /* send up table */
740 at_state
.flags
&= ~AT_ST_NBP_CHANGED
;
745 #ifdef APPLETALK_DEBUG
746 kprintf("unknown ioctl %d\n", iocbp
->ioc_cmd
);
748 ioc_ack(ENOTTY
, m
, gref
);
749 dPrintf(D_M_ELAP
, D_L_WARNING
,
750 ("elap_wput: unknown ioctl (%d)\n", iocbp
->ioc_cmd
));
753 elapp
->stats
.unknown_mblks
++;
768 /* Called directly by ddp/zip.
770 elap_dataput(m
, elapp
, addr_flag
, addr
)
772 register at_ifaddr_t
*elapp
;
778 extern int zip_type_packet();
779 struct etalk_addr dest_addr
;
780 struct atalk_addr dest_at_addr
;
781 extern gbuf_t
*growmsg();
783 /* flag to aarp to loopback (default) */
785 /* the incoming frame is of the form {flag, address, ddp...}
786 * where "flag" indicates whether the address is an 802.3
787 * (link) address, or an appletalk address. If it's an
788 * 802.3 address, the packet can just go out to the network
789 * through PAT, if it's an appletalk address, AT->802.3 address
790 * resolution needs to be done.
791 * If 802.3 address is known, strip off the flag and 802.3
792 * address, and prepend 802.2 and 802.3 headers.
796 addr_flag
= *(u_char
*)gbuf_rptr(m
);
801 case AT_ADDR_NO_LOOP
:
806 dest_at_addr
= *(struct atalk_addr
*)gbuf_rptr(m
);
807 gbuf_rinc(m
,sizeof(struct atalk_addr
));
809 dest_at_addr
= *(struct atalk_addr
*)addr
;
813 dest_addr
= *(struct etalk_addr
*)gbuf_rptr(m
);
814 gbuf_rinc(m
,sizeof(struct etalk_addr
));
816 dest_addr
= *(struct etalk_addr
*)addr
;
819 gbuf_freel(m
); /* unknown address type, chuck it */
825 /* At this point, rptr points to ddp header for sure */
826 if (elapp
->ifState
== LAP_OFFLINE
) {
831 if (elapp
->ifState
== LAP_ONLINE_FOR_ZIP
) {
832 /* see if this is a ZIP packet that we need
833 * to let through even though network is
836 if (zip_type_packet(m
) == 0) {
842 elapp
->stats
.xmit_packets
++;
843 size
= gbuf_msgsize(m
);
844 elapp
->stats
.xmit_bytes
+= size
;
845 snmpStats
.dd_outLong
++;
848 case AT_ADDR_NO_LOOP
:
851 * we don't want elap to be looking into ddp header, so
852 * it doesn't know net#, consequently can't do
853 * AMT_LOOKUP. That task left to aarp now.
855 error
= aarp_send_data(m
,elapp
,&dest_at_addr
, loop
);
858 error
= pat_output(elapp
, m
, &dest_addr
, 0);
864 /************************************************************************
867 ************************************************************************/
869 static int elap_online1(elapp
)
874 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online:%s elapp:0x%x\n",
875 (elapp
->ifName
) ? &elapp
->ifName
[0] : "NULL interface", (u_int
) elapp
));
876 if (elapp
->ifState
!= LAP_OFFLINE
|| elapp
->startup_inprogress
== TRUE
)
879 at_state
.flags
|= AT_ST_IF_CHANGED
;
881 if (elapp
->flags
& ELAP_CFG_HOME
) /* tell ddp_add_if if this is home */
882 elapp
->ifFlags
|= AT_IFF_DEFAULT
;
884 /* Get DDP started */
885 if ((errno
= ddp_add_if(elapp
)))
888 /* set up multicast address for cable-wide broadcasts */
889 (void)at_reg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
891 elapp
->startup_inprogress
= TRUE
;
892 if (! (elapp
->startup_error
= re_aarp(elapp
)))
893 (void)tsleep(&elapp
->startup_inprogress
, PSOCK
| PCATCH
,
896 /* then later, after some timeouts AARPwakeup() is called */
898 return(elapp
->startup_error
);
901 static int re_aarp(elapp
)
906 /* We now call aarp_init() to assign an appletalk node addr */
907 errno
= aarp_init1(elapp
);
908 /* aarp_init1() returns either -1 or ENOTREADY */
909 if (errno
== ENOTREADY
)
912 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
913 ("elap_online aarp_init for %s\n", elapp
->ifName
));
914 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
916 elapp
->ifState
= LAP_OFFLINE
;
917 return(EADDRNOTAVAIL
);
921 /* called from AARPwakeup */
922 static void elap_online2(elapp
)
925 if (MULTIPORT_MODE
) {
926 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
927 ("elap_online: re_aarp, we know it's a router...\n"));
929 if (elapp
->flags
& ELAP_CFG_SEED
) {
930 /* add route table entry (zones to be added later) */
931 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
932 ("elap_online: rt_insert Cable %d-%d port =%d as SEED\n",
933 elapp
->ifThisCableStart
, elapp
->ifThisCableEnd
, elapp
->ifPort
));
934 rt_insert(elapp
->ifThisCableEnd
,
935 elapp
->ifThisCableStart
,
938 RTE_STATE_PERMANENT
| RTE_STATE_ZKNOWN
| RTE_STATE_GOOD
940 /* LD 081694: set the RTR_SEED_PORT flag for seed ports */
941 elapp
->ifFlags
|= RTR_SEED_PORT
;
944 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
945 ("elap_online: it's a router, but non seed\n"));
948 if (elapp
->flags
& ELAP_CFG_ZONELESS
) {
949 /* ELAP_CFG_ZONELESS tells us that it is a router or in
950 multihome mode, so we don't want to do the GetNetInfo
951 exchange with the router. */
953 elapp
->ifState
= LAP_ONLINE_ZONELESS
;
954 elapp
->startup_inprogress
= FALSE
;
955 wakeup(&elapp
->startup_inprogress
);
956 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online: ack 3\n"));
960 /* if we don't already have a zone and a multicast address */
961 if (*(int *)&elapp
->ZoneMcastAddr
== 0 || elapp
->ifZoneName
.len
== 0) {
962 /* hzonehash is a global containing the nbp hash for the startup_zone */
965 /* Get ZIP rolling to get zone multicast address, etc. */
966 elapp
->ifState
= LAP_ONLINE_FOR_ZIP
;
967 (void)zip_control(elapp
, ZIP_ONLINE
);
968 /* zip_control (w. control == ZIP_ONLINE) always returns ENOTREADY */
970 /* later, after some timeouts ZIPwakeup() is called. */
972 /* otherwise, we have the zone and the multicast already,
973 so don't bother with another ZIP GetNetInfo request */
978 /* called from rtmp_router_start */
979 int elap_online3(elapp
)
982 elapp
->startup_inprogress
= TRUE
;
984 /* just reset the net range */
985 elapp
->initial_addr
.s_net
= 0;
986 elapp
->initial_addr
.s_node
= 0;
987 dPrintf(D_M_ELAP_LOW
, D_L_STARTUP_INFO
,
988 ("elap_online: goto re_aarp port=%d\n", elapp
->ifPort
));
990 if ((elapp
->startup_error
= re_aarp(elapp
)))
991 return(elapp
->startup_error
);
993 /* then later, after some timeouts AARPwakeup() is called */
995 (void)tsleep(&elapp
->startup_inprogress
, PSOCK
| PCATCH
,
997 return(elapp
->startup_error
);
1000 /****************************************************************************
1003 ****************************************************************************/
1005 void elap_offline(elapp
)
1006 register at_ifaddr_t
*elapp
;
1009 void zip_sched_getnetinfo(); /* forward reference */
1013 dPrintf(D_M_ELAP
, D_L_SHUTDN_INFO
, ("elap_offline:%s\n", elapp
->ifName
));
1014 if (elapp
->ifState
!= LAP_OFFLINE
) {
1016 /* Since AppleTalk is going away, remove the cable
1017 * multicast address and turn the interface off so that all
1018 * AppleTalk packets are dropped in the driver itself.
1019 * Get rid of the zone multicast address prior to going Offline.
1021 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->ZoneMcastAddr
);
1022 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
1023 elapp
->ifState
= LAP_OFFLINE
;
1025 ATDISABLE(s
, ddpinp_lock
);
1027 RT_DELETE(elapp
->ifThisCableEnd
,
1028 elapp
->ifThisCableStart
);
1029 ATENABLE(s
, ddpinp_lock
);
1031 /* make sure no zip timeouts are left running */
1032 untimeout(zip_sched_getnetinfo
, elapp
);
1035 } /* elap_offline */
1038 static void add_route(rt
)
1041 /* support ioctl to manually add routes to table.
1042 this is really only for testing
1045 rt_insert( rt
->NetStop
, rt
->NetStart
, rt
->NextIRNet
,
1046 rt
->NextIRNode
, rt
->NetDist
, rt
->NetPort
,
1048 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("adding route: %ud:%ud dist:%ud\n",
1049 rt
->NetStart
, rt
->NetStop
,rt
->NetDist
));
1055 * Initialization that takes place each time AppleTalk is restarted.
1060 TAILQ_INIT(&at_ifQueueHd
);
1061 TAILQ_INIT(&name_registry
);
1062 bzero(at_interfaces
, sizeof(at_interfaces
));
1063 bzero(ifID_table
, sizeof(ifID_table
));
1064 bzero(&at_ddp_stats
, sizeof(at_ddp_stats_t
));
1065 rtmp_init(); /* initialize trackedrouters */
1067 add_ddp_handler(RTMP_SOCKET
, rtmp_input
);
1068 ifID_home
= (at_ifaddr_t
*)NULL
;
1072 int ddp_shutdown(count_only
)
1076 asp_scb_t
*scb
, *scb_next
;
1077 struct atp_state
*atp
, *atp_next
;
1080 vm_offset_t temp_rcb_data
, temp_state_data
;
1081 int i
, s
, active_skts
= 0; /* count of active pids for non-socketized
1082 AppleTalk protocols */
1083 extern int aarp_sched_probe();
1086 /* Network is shutting down... send error messages up on each open
1088 *** For now, for ASP, ATP and ADSP, attempt to notify open
1089 sockets, but return EBUSY and don't complete shutdown. ***
1092 s
= splimp(); /* *** previously contained mismatched locking
1093 that was ifdef'ed to splimp() *** */
1095 nbp_shutdown(); /* clear all known NVE */
1098 for (scb
= scb_used_list
; scb
; ) {
1099 scb_next
= scb
->next_scb
;
1102 dPrintf(D_M_ASP
, D_L_TRACE
, ("asp pid=%d\n", scb
->pid
));
1103 atalk_notify(scb
->gref
, ESHUTDOWN
);
1107 for (i
= 0; i
< 256 ; i
++) {
1108 if ((scb
= asp_scbQ
[i
]))
1110 scb_next
= scb
->next_scb
;
1113 dPrintf(D_M_ASP
, D_L_TRACE
,
1114 ("asp pid=%d\n", scb
->pid
));
1115 atalk_notify(scb
->gref
, ESHUTDOWN
);
1122 for (atp
= atp_used_list
; atp
; ) {
1123 atp_next
= atp
->atp_trans_waiting
;
1126 dPrintf(D_M_ATP
, D_L_TRACE
, ("atp pid=%d\n", atp
->atp_pid
));
1127 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1131 for (i
= 0; i
< 256; i
++) {
1132 if ((gref
= atp_inputQ
[i
]) && (gref
!= (gref_t
*)1)) {
1133 atp
= (struct atp_state
*)gref
->info
;
1137 dPrintf(D_M_ATP
, D_L_TRACE
,
1138 ("atp pid=%d\n", atp
->atp_pid
));
1139 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1146 for (sp
= ccb_used_list
; sp
; ) {
1147 sp_next
= sp
->otccbLink
;
1150 dPrintf(D_M_ADSP
, D_L_TRACE
, ("adsp pid=%d\n", sp
->pid
));
1151 atalk_notify(sp
->gref
, ESHUTDOWN
);
1155 for (i
= 0; i
< 256 ; i
++) {
1156 if ((sp
= adsp_inputQ
[i
]))
1158 sp_next
= sp
->otccbLink
;
1161 dPrintf(D_M_ADSP
, D_L_TRACE
,
1162 ("adsp pid=%d\n", sp
->pid
));
1163 atalk_notify(sp
->gref
, ESHUTDOWN
);
1170 for (gref
= ddp_head
.atpcb_next
; gref
!= &ddp_head
;
1171 gref
= gref
->atpcb_next
) {
1175 dPrintf(D_M_DDP
,D_L_TRACE
, ("ddp pid=%d\n", gref
->pid
));
1176 atalk_notify(gref
, ESHUTDOWN
);
1179 if (count_only
|| active_skts
) {
1181 return(active_skts
);
1184 /* if there are no interfaces in the process of going online, continue shutting down DDP */
1185 for (i
= 0; i
< IF_TOTAL_MAX
; i
++) {
1186 if (at_interfaces
[i
].startup_inprogress
== TRUE
)
1189 if (MULTIPORT_MODE
) {
1191 /* free memory allocated for the rtmp/zip tables */
1193 FREE(ZT_table
, M_RTABLE
);
1194 ZT_table
= (ZT_entry
*)NULL
;
1197 FREE(RT_table
, M_RTABLE
);
1198 RT_table
= (RT_entry
*)NULL
;
1202 at_state
.flags
= 0; /* make sure inits are done on restart */
1204 wakeup(&ifID_home
->startup_inprogress
); /* if rtmp_router_start still starting up */
1206 /* from original ddp_shutdown() */
1216 dPrintf(D_M_DDP
, D_L_VERBOSE
, ("DDP shutdown completed"));
1219 * make sure we don't have a probe timeout hanging around
1220 * it's going to try and make use of an entry in at_interfaces
1221 * which is going to be zero'd out by the call to ddp_start a
1222 * little further down
1224 untimeout(aarp_sched_probe
, 0);
1226 /* *** after an SIOCSIFADDR and before an AIOCSIFADDR,
1227 this is the only place to find the ifID *** */
1228 for (i
= 0; i
< IF_TOTAL_MAX
; i
++) {
1229 ifID
= &at_interfaces
[i
];
1230 /* do LAP_IOC_OFFLINE processing */
1235 /* free buffers for large arrays used by atp.
1236 * to prevent a race condition if the funnel is dropped
1237 * while calling kmem_free, the fields are grabbed and
1240 if (atp_rcb_data
!= NULL
) {
1241 temp_rcb_data
= (vm_offset_t
)atp_rcb_data
;
1242 atp_rcb_data
= NULL
;
1243 atp_rcb_free_list
= NULL
;
1245 temp_rcb_data
= NULL
;
1246 if (atp_state_data
!= NULL
) {
1247 temp_state_data
= (vm_offset_t
)atp_state_data
;
1248 atp_state_data
= NULL
;
1249 atp_free_list
= NULL
;
1251 temp_state_data
= NULL
;
1254 kmem_free(kernel_map
, temp_rcb_data
, sizeof(struct atp_rcb
) * NATP_RCB
);
1255 if (temp_state_data
)
1256 kmem_free(kernel_map
, temp_state_data
, sizeof(struct atp_state
) * NATP_STATE
);
1260 } /* ddp_shutdown */
1262 int routerStart(keP
)
1265 register at_ifaddr_t
*ifID
;
1272 * this will cause the ports to glean from the net the relevant
1273 * information before forwarding
1275 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1276 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1277 ("routerStart Port %d (%s) set to activating\n",
1278 ifID
->ifPort
, ifID
->ifName
));
1279 ifID
->ifRoutingState
= PORT_ACTIVATING
;
1280 ifID
->ifFlags
|= RTR_XNET_PORT
;
1284 * The next step is to check the information for each port before
1285 * declaring the ports up and forwarding
1287 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1288 ("router_start: waiting 20 sec before starting up\n"));
1290 /* sleep for 20 seconds */
1292 /* *** eventually this will be the ifID for the interface
1293 being brought up in router mode *** */
1294 tsleep(&ifID_home
->startup_inprogress
,
1295 PSOCK
| PCATCH
, "routerStart", 20 * SYS_HZ
))
1299 panic("routerStart: spurious interrupt");
1304 return(rtmp_router_start(keP
));
1305 /* was timeout(rtmp_router_start, 0, 20 * SYS_HZ); */
1308 void ZIPwakeup(elapp
, ZipError
)
1312 int s
, error
= ZipError
;
1314 ATDISABLE(s
, ddpinp_lock
);
1315 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
) {
1316 ATENABLE(s
, ddpinp_lock
);
1318 /* was ZIPContinue */
1319 /* was elapp_online() with jump to ZIP_sleep */
1321 /* instead of the goto ZIP_sleep ... */
1323 case 0 : /* success */
1324 elapp
->ifState
= LAP_ONLINE
;
1326 /* Send event with zone info. */
1327 atalk_post_msg(elapp
->aa_ifp
, KEV_ATALK_ZONEUPDATED
, 0, &(elapp
->ifZoneName
));
1331 /* instead of goto re_aarp; */
1332 /* We now call aarp_init() to assign an
1333 appletalk node addr */
1334 if ((elapp
->startup_error
= re_aarp(elapp
))) {
1335 elapp
->startup_inprogress
= FALSE
;
1336 wakeup(&elapp
->startup_inprogress
);
1337 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1338 ("elap_online: ack 2\n"));
1344 if (ZipError
!= ZIP_RE_AARP
) {
1345 elapp
->startup_error
= error
;
1346 elapp
->startup_inprogress
= FALSE
;
1347 wakeup(&elapp
->startup_inprogress
);
1348 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1349 ("elap_online: ifZipError=%d\n", error
));
1352 ATENABLE(s
, ddpinp_lock
);
1355 void AARPwakeup(probe_cb
)
1356 aarp_amt_t
*probe_cb
;
1362 ATDISABLE(s
, arpinp_lock
);
1363 elapp
= probe_cb
->elapp
;
1364 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
) {
1365 ATENABLE(s
, arpinp_lock
);
1367 /* was AARPContinue */
1368 errno
= aarp_init2(elapp
);
1369 /* aarp_init2() returns either -1 or 0 */
1371 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
1372 ("elap_online aarp_init for %s\n",
1374 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->ZoneMcastAddr
);
1375 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
1376 elapp
->ifState
= LAP_OFFLINE
;
1378 elapp
->startup_error
= EADDRNOTAVAIL
;
1379 elapp
->startup_inprogress
= FALSE
;
1380 wakeup(&elapp
->startup_inprogress
);
1381 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online: ack 2\n"));
1383 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
1384 ("elap_online: aarp_init returns zero\n"));
1385 elap_online2(elapp
);
1388 ATENABLE(s
, arpinp_lock
);
1391 void ddp_bit_reverse(addr
)
1392 unsigned char *addr
;
1394 static unsigned char reverse_data
[] = {
1395 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1396 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1397 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1398 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1399 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1400 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1401 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1402 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1403 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1404 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1405 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1406 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1407 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1408 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1409 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1410 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1411 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1412 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1413 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1414 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1415 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1416 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1417 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1418 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1419 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1420 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1421 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1422 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1423 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1424 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1425 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1426 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1431 for (k
=0; k
< 6; k
++)
1432 addr
[k
] = reverse_data
[addr
[k
]];
1435 static int elap_trackMcast(patp
, func
, addr
)
1442 switch(patp
->aa_ifp
->if_type
) {
1445 /* set addr to point to unique part of addr */
1448 /* first try to find match */
1449 /* *** save just one byte of the multicast address? *** */
1450 for (i
=0; i
< MAX_MCASTS
; i
++)
1451 if (c
== patp
->mcast
[i
]) {
1457 case MCAST_TRACK_DELETE
:
1459 patp
->mcast
[loc
] = 0;
1462 case MCAST_TRACK_ADD
:
1463 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add loc:%d\n", i
));
1465 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was there\n"));
1467 break; /* already there */
1469 for (i
=0; i
< MAX_MCASTS
; i
++)
1470 if (patp
->mcast
[i
] == 0) {
1474 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add1 loc:%d\n", i
));
1476 patp
->mcast
[loc
] = c
;
1477 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, adding(%x)\n",
1478 (*(int*)addr
)&0xffffff));
1481 /*errno = ENOMEM; */ /*LD 5/7/97 nobody is using that */
1485 case MCAST_TRACK_CHECK
:
1487 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:check, addr was there\n"));
1491 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was NOT there\n"));
1496 /*errno = EINVAL;*/ /*LD 5/7/97 nobody is using that */
1500 case IFT_ISO88025
: /* token ring */
1501 /* we would use the lowest byte of the addr argument as a value
1502 to shift left a 1 to form the mcast mask for TR. We'll do this
1512 static getSnmpCfg(snmp
)
1519 snmp
->cfg_ifCnt
= 0;
1521 bzero(snmp
,sizeof(snmpCfg_t
));
1522 for (i
=0, elapp
=at_interfaces
,ifc
=snmp
->cfg_ifCfg
;
1523 i
<IF_TOTAL_MAX
; i
++, elapp
++, ifc
++) {
1524 if (elapp
->ifState
!= LAP_OFFLINE
) {
1526 strncpy(ifc
->ifc_name
,elapp
->ifName
, sizeof(ifc
->ifc_name
));
1527 ifc
->ifc_aarpSize
= getAarpTableSize(i
);
1528 ifc
->ifc_addrSize
= getPhysAddrSize(i
);
1529 switch (elapp
->aa_ifp
->if_type
) {
1531 ifc
->ifc_type
= SNMP_TYPE_ETHER2
;
1533 case IFT_ISO88025
: /* token ring */
1534 ifc
->ifc_type
= SNMP_TYPE_TOKEN
;
1538 ifc
->ifc_type
= SNMP_TYPE_OTHER
;
1541 ifc
->ifc_start
= elapp
->ifThisCableStart
;
1542 ifc
->ifc_end
= elapp
->ifThisCableEnd
;
1543 ifc
->ifc_ddpAddr
= elapp
->ifThisNode
;
1544 ifc
->ifc_status
= elapp
->ifState
== LAP_ONLINE
? 1 : 2;
1545 ifc
->ifc_zoneName
.len
= 0;
1546 if (elapp
->ifZoneName
.len
!= 0) {
1547 ifc
->ifc_zoneName
= elapp
->ifZoneName
;
1549 else if (elapp
->ifDefZone
) {
1550 ifc
->ifc_zoneName
= ZT_table
[elapp
->ifDefZone
-1].Zone
;
1552 else /* temp, debug only */
1553 ifc
->ifc_zoneName
= ZT_table
[0].Zone
;
1555 if (elapp
->ifFlags
& RTR_SEED_PORT
) {
1556 ifc
->ifc_netCfg
= SNMP_CFG_CONFIGURED
;
1557 ifc
->ifc_zoneCfg
= SNMP_CFG_CONFIGURED
;
1560 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1561 ifc
->ifc_zoneCfg
= SNMP_CFG_GARNERED
;
1564 else { /* single-port mode */
1565 if (elapp
->ifRouterState
== ROUTER_AROUND
) {
1566 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1569 ifc
->ifc_netCfg
= SNMP_CFG_GUESSED
;
1570 ifc
->ifc_zoneCfg
= SNMP_CFG_UNCONFIG
;
1575 snmp
->cfg_flags
= at_state
.flags
;
1581 int at_reg_mcast(ifID
, data
)
1585 struct ifnet
*nddp
= ifID
->aa_ifp
;
1590 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1594 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1597 /* this is for ether_output */
1598 sa
.sa_family
= AF_UNSPEC
;
1599 sa
.sa_len
= 2 + sizeof(struct etalk_addr
);
1600 bcopy (data
, &sa
.sa_data
[0], sizeof(struct etalk_addr
));
1602 dPrintf(D_M_PAT
, D_L_STARTUP
,
1603 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1604 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1607 if (if_addmulti(nddp
, &sa
, 0))
1614 int at_unreg_mcast(ifID
, data
)
1618 struct ifnet
*nddp
= ifID
->aa_ifp
;
1623 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1627 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1629 /* this is for ether_output */
1630 sa
.sa_family
= AF_UNSPEC
;
1631 sa
.sa_len
= 2 + sizeof(struct etalk_addr
);
1632 bcopy (data
, &sa
.sa_data
[0], sizeof(struct etalk_addr
));
1634 dPrintf(D_M_PAT
, D_L_STARTUP
,
1635 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1636 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1638 bzero(data
, sizeof(struct etalk_addr
));
1640 if (if_delmulti(nddp
, &sa
))
1646 /* *** at_reg_mcast() and at_unreg_mcast() should be replaced as soon as the
1647 new code to allow an AF_LINK address family multicast to be (un)registered
1648 using the SIOCADDMULTI / SIOCDELMULTI ioctls has been completed.
1650 The issue is that the "struct sockaddr_dl" needed for the AF_LINK does not
1651 fit in the "struct ifreq" that is used for these ioctls, and we do not want
1652 Blue/Classic, which currently uses AF_UNSPEC, to use a different address
1653 family multicast address than Mac OS X uses.
1656 int at_reg_mcast(ifID
, data
)
1660 struct ifnet
*nddp
= ifID
->aa_ifp
;
1661 struct sockaddr_dl sdl
;
1665 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1668 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1671 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1672 sdl
.sdl_family
= AF_LINK
;
1674 sdl
.sdl_type
= nddp
->if_type
;
1675 sdl
.sdl_alen
= nddp
->if_addrlen
;
1677 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1678 nddp
->if_name
, nddp
->if_unit
);
1679 bcopy(data
, LLADDR(&sdl
), sdl
.sdl_alen
);
1681 dPrintf(D_M_PAT
, D_L_STARTUP
,
1682 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1683 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1686 if (if_addmulti(nddp
, (struct sockaddr
*)&sdl
, 0))
1693 int at_unreg_mcast(ifID
, data
)
1697 struct ifnet
*nddp
= ifID
->aa_ifp
;
1698 struct sockaddr_dl sdl
;
1702 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1706 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1708 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1709 sdl
.sdl_family
= AF_LINK
;
1711 sdl
.sdl_type
= nddp
->if_type
;
1712 sdl
.sdl_alen
= nddp
->if_addrlen
;
1714 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1715 nddp
->if_name
, nddp
->if_unit
);
1717 dPrintf(D_M_PAT
, D_L_STARTUP
,
1718 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1719 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1721 bzero(data
, ETHERNET_ADDR_LEN
);
1723 if (if_delmulti(nddp
, (struct sockaddr
*)&sdl
))