2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
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
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
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.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * Copyright (c) 1988, 1989, 1993-1998 Apple Computer, Inc.
34 /* at_elap.c: 2.0, 1.29; 10/4/93; Apple Computer, Inc. */
36 /* This is the file which implements all the streams driver
37 * functionality required for EtherTalk.
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').
46 Modified for MP, 1996 by Tuyen Nguyen
47 Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
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>
59 #include <sys/filedesc.h>
60 #include <sys/fcntl.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 */
73 #include <net/if_types.h>
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>
92 #include <sys/kern_event.h>
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
101 * NOTE: for MH, entry 0 in this table is
102 * now defined to be the default I/F
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 */
108 at_state_t at_state
; /* global state of AT network */
109 snmpFlags_t snmpFlags
;
114 #define MAX_BUFSIZE 8192
115 #define MAX_RTMP (MAX_BUFSIZE/sizeof(RT_entry)-1)
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))
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
;
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();
149 static int elap_online1(), re_aarp();
150 int at_reg_mcast(), at_unreg_mcast();
151 void AARPwakeup(), ZIPwakeup();
152 static void elap_hangup();
155 at_ifaddr_t
*find_ifID(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
]);
166 return((at_ifaddr_t
*)NULL
);
169 static int validate_msg_size(m
, gref
, elapp
)
174 /* checks ioctl message type for minimum expected message size &
175 sends error back if size invalid
178 register ioc_t
*iocbp
;
179 register at_if_cfg_t
*cfgp
;
183 iocbp
= (ioc_t
*) gbuf_rptr(m
);
185 dPrintf(D_M_ELAP
, D_L_INFO
, ("validate_msg_size: ioc_cmd = %d\n",
187 switch (iocbp
->ioc_cmd
) {
188 case LAP_IOC_ADD_ROUTE
:
189 size
= sizeof(RT_entry
);
191 case LAP_IOC_GET_ROUTE
:
192 size
= sizeof(RT_entry
);
194 case LAP_IOC_GET_ZONE
:
195 size
= sizeof(ZT_entryno
);
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
:
205 case ELAP_IOC_GET_STATS
:
206 case LAP_IOC_SNMP_GET_DDP
:
211 dPrintf(D_M_ELAP
, D_L_ERROR
, ("validate_msg_size: unknown ioctl\n"));
215 if (size
== 0) { /* a non-data ioctl */
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
));
231 ioc_ack(EMSGSIZE
, m
, gref
);
233 } /* validate_msg_size */
235 int lap_online(elapp
, cfgp
)
241 if (elapp
->ifState
!= LAP_OFFLINE
) {
246 if (cfgp
->flags
& ELAP_CFG_HOME
) {
248 /* only 1 home allowed! */
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
;
256 if (MULTIPORT_MODE
) {
257 elapp
->flags
|= ELAP_CFG_ZONELESS
;
258 if (ROUTING_MODE
&& cfgp
->netStart
)
259 elapp
->flags
|= ELAP_CFG_SEED
;
262 if (!DEFAULT_ZONE(&cfgp
->zonename
) &&
263 (elapp
->flags
& ELAP_CFG_HOME
) || MULTIHOME_MODE
) {
264 elapp
->startup_zone
= cfgp
->zonename
;
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
;
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
)) {
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
)))) {
288 elapp
->initial_addr
= cfgp
->node
;
293 elapp
->startup_error
= 0;
294 elapp
->startup_inprogress
= FALSE
;
295 if ((error
= elap_online1(elapp
)))
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
);
307 /***********************************************************************
310 **********************************************************************/
311 int elap_wput(gref
, m
)
316 register ioc_t
*iocbp
;
317 register at_if_cfg_t
*cfgp
;
318 at_elap_stats_t
*statsp
;
325 switch (gbuf_type(m
)) {
328 dPrintf(D_M_ELAP
,D_L_ERROR
,
329 ("Output data to control channel is ignored\n"));
333 iocbp
= (ioc_t
*) gbuf_rptr(m
);
335 if (validate_msg_size(m
, gref
, &elapp
))
339 cfgp
= (at_if_cfg_t
*) gbuf_rptr(gbuf_cont(m
));
341 if (LAP_IOC_MYIOCTL(iocbp
->ioc_cmd
) ||
342 ELAP_IOC_MYIOCTL(iocbp
->ioc_cmd
)) {
344 switch (iocbp
->ioc_cmd
) {
345 case ELAP_IOC_GET_STATS
:
346 #ifdef APPLETALK_DEBUG
347 kprintf("LAP_IOC_GET_STATS\n");
349 if ( (gbuf_cont(m
) == NULL
)
350 || (elapp
= find_ifID(gbuf_rptr(gbuf_cont(m
)))) == NULL
) {
351 ioc_ack(EINVAL
, m
, gref
);
354 gbuf_freem(gbuf_cont(m
));
355 if ((gbuf_cont(m
) =gbuf_alloc(sizeof(at_elap_stats_t
),
357 ioc_ack(ENOBUFS
, m
, gref
);
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
);
367 case LAP_IOC_ADD_ROUTE
:
368 #ifdef APPLETALK_DEBUG
369 kprintf("LAP_IOC_ADD_ROUTE\n");
371 add_route((RT_entry
*)gbuf_rptr(gbuf_cont(m
)));
375 case LAP_IOC_GET_ZONE
:
376 #ifdef APPLETALK_DEBUG
377 kprintf("LAP_IOC_GET_ZONE\n");
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
390 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
391 gbuf_freem(gbuf_cont(m
));
394 pZTe
= zt_getNextZone(i
);
396 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(ZT_entryno
), PRI_MED
)) == NULL
) {
397 ioc_ack(ENOBUFS
, m
, gref
);
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
);
406 ioc_ack(EINVAL
, m
, gref
);
410 case LAP_IOC_GET_ROUTE
:
411 #ifdef APPLETALK_DEBUG
412 kprintf("LAP_IOC_GET_ROUTE\n");
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
427 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
428 gbuf_freem(gbuf_cont(m
));
431 pRT
= rt_getNextRoute(i
);
433 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(RT_entry
), PRI_MED
)) == NULL
) {
434 ioc_ack(ENOBUFS
, m
, gref
);
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
);
443 ioc_ack(EINVAL
, m
, gref
);
447 case LAP_IOC_SNMP_GET_DDP
:
448 #ifdef APPLETALK_DEBUG
449 kprintf("LAP_IOC_SNMP_GET_DDP\n");
451 if (!(at_state
.flags
& AT_ST_STARTED
)) {
452 ioc_ack(ENOTREADY
, m
, gref
);
455 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(snmpStats_t
),
457 ioc_ack(ENOBUFS
, m
, gref
);
461 *(snmpStats_t
*)gbuf_rptr(gbuf_cont(m
)) = snmpStats
;
462 gbuf_wset(gbuf_cont(m
),sizeof(snmpStats
));
463 iocbp
->ioc_count
= sizeof(snmpStats
);
466 case LAP_IOC_SNMP_GET_CFG
:
467 #ifdef APPLETALK_DEBUG
468 kprintf("LAP_IOC_SNMP_GET_CFG\n");
474 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
475 gbuf_freem(gbuf_cont(m
));
477 if (!(at_state
.flags
& AT_ST_STARTED
)) {
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"));
485 if (i
== UPDATE_IF_CHANGED
&&
486 !(at_state
.flags
& AT_ST_IF_CHANGED
)) {
487 iocbp
->ioc_count
= 0;
489 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
490 ("elap_wput: cfg req, unchanged\n"));
493 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
494 ("elap_wput: cfg req, changed\n"));
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
);
502 /* send up only used part of table */
503 size
= sizeof(snmp
) -
504 sizeof(snmpIfCfg_t
) * (MAX_IFS
- snmp
.cfg_ifCnt
);
506 if ((gbuf_cont(m
) = gbuf_alloc(size
, PRI_MED
)) == NULL
) {
507 ioc_ack(ENOBUFS
, m
, gref
);
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
;
518 case LAP_IOC_SNMP_GET_AARP
:
520 snmpAarpEnt_t
*snmpp
;
522 #ifdef APPLETALK_DEBUG
523 kprintf("LAP_IOC_SNMP_GET_AARP\n");
525 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
526 gbuf_freem(gbuf_cont(m
));
528 dPrintf(D_M_ELAP
,D_L_INFO
,
529 ("elap_wput:calling getarp,i=%d\n", 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",
536 if ((gbuf_cont(m
) = gbuf_alloc(bytes
, PRI_MED
)) == NULL
) {
537 ioc_ack(ENOBUFS
, m
, gref
);
540 bcopy(snmpp
, gbuf_rptr(gbuf_cont(m
)), bytes
);
541 gbuf_wset(gbuf_cont(m
),bytes
);
542 iocbp
->ioc_count
= bytes
;
546 ioc_ack(EOPNOTSUPP
, m
, gref
);
550 case LAP_IOC_SNMP_GET_ZIP
:
551 #ifdef APPLETALK_DEBUG
552 kprintf("LAP_IOC_SNMP_GET_ZIP\n");
554 { /* matching brace NOT in this case */
556 register int size
, total
, tabsize
;
557 gbuf_t
*mn
; /* new gbuf */
558 gbuf_t
*mo
; /* old gbuf */
559 gbuf_t
*mt
; /* temp */
562 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
563 gbuf_freem(gbuf_cont(m
));
565 if (!(at_state
.flags
& AT_ST_STARTED
)) {
566 ioc_ack(ENOTREADY
, m
, gref
);
569 if (i
== UPDATE_IF_CHANGED
&&
570 !(at_state
.flags
& AT_ST_ZT_CHANGED
)) {
571 iocbp
->ioc_count
= 0;
576 tabsize
= getZipTableSize();
578 /* retrieve table into multiple gbufs */
579 for (i
=0; i
<tabsize
; i
+=j
) {
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
) {
585 gbuf_freem(gbuf_cont(m
));
586 ioc_ack(ENOBUFS
, m
, gref
);
589 if (!mo
) { /* if first new one */
598 getZipTable((ZT_entry
*)gbuf_rptr(mn
),i
,j
);
601 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
604 iocbp
->ioc_count
= 0;
605 ioc_ack(ENOBUFS
, m
, gref
);
609 dPrintf(D_M_ELAP
,D_L_WARNING
,
610 ("elap_wput:snmp: empty zip table\n"));
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);
618 atalk_putnext(gref
,mt
); /* send up table */
619 at_state
.flags
&= ~AT_ST_ZT_CHANGED
;
622 case LAP_IOC_SNMP_GET_RTMP
:
623 #ifdef APPLETALK_DEBUG
624 kprintf("LAP_IOC_SNMP_GET_RTMP\n");
626 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
627 gbuf_freem(gbuf_cont(m
));
629 if (!(at_state
.flags
& AT_ST_STARTED
)) {
630 ioc_ack(ENOTREADY
, m
, gref
);
633 if (i
== UPDATE_IF_CHANGED
&&
634 !(at_state
.flags
& AT_ST_RT_CHANGED
)) {
635 iocbp
->ioc_count
= 0;
641 tabsize
= getRtmpTableSize();
643 /* retrieve table into multiple gbufs */
644 for (i
=0; i
<tabsize
; i
+=j
) {
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
) {
650 gbuf_freem(gbuf_cont(m
));
651 ioc_ack(ENOBUFS
, m
, gref
);
654 if (!mo
) { /* if first new one */
663 getRtmpTable((RT_entry
*)gbuf_rptr(mn
),i
,j
);
666 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
669 iocbp
->ioc_count
= 0;
670 ioc_ack(ENOBUFS
, m
, gref
);
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);
680 atalk_putnext(gref
,mt
); /* send up table */
681 at_state
.flags
&= ~AT_ST_RT_CHANGED
;
684 case LAP_IOC_SNMP_GET_NBP
:
685 #ifdef APPLETALK_DEBUG
686 kprintf("LAP_IOC_SNMP_GET_NBP\n");
688 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
689 gbuf_freem(gbuf_cont(m
));
691 if (!(at_state
.flags
& AT_ST_STARTED
)) {
692 ioc_ack(ENOTREADY
, m
, gref
);
695 if (i
== UPDATE_IF_CHANGED
&&
696 !(at_state
.flags
& AT_ST_NBP_CHANGED
)) {
697 iocbp
->ioc_count
= 0;
699 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
700 ("elap_wput: nbp req denied, no change\n"));
705 tabsize
= getNbpTableSize();
707 /* retrieve table into multiple gbufs */
708 for (i
=0; i
<tabsize
; i
+=j
) {
710 MAX_NBP
? MAX_NBP
: tabsize
- i
;
711 size
= j
< MAX_NBP
? sizeof(snmpNbpEntry_t
)*j
: MAX_NBP_BYTES
;
713 size
+= SNMP_NBP_HEADER_SIZE
;
714 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
716 gbuf_freem(gbuf_cont(m
));
717 ioc_ack(ENOBUFS
, m
, gref
);
720 if (!mo
) { /* if first new one */
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
);
731 getNbpTable((snmpNbpEntry_t
*)gbuf_rptr(mn
),i
,j
);
736 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
739 iocbp
->ioc_count
= 0;
740 ioc_ack(ENOBUFS
, m
, gref
);
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);
750 atalk_putnext(gref
,mt
); /* send up table */
751 at_state
.flags
&= ~AT_ST_NBP_CHANGED
;
756 #ifdef APPLETALK_DEBUG
757 kprintf("unknown ioctl %d\n", iocbp
->ioc_cmd
);
759 ioc_ack(ENOTTY
, m
, gref
);
760 dPrintf(D_M_ELAP
, D_L_WARNING
,
761 ("elap_wput: unknown ioctl (%d)\n", iocbp
->ioc_cmd
));
764 elapp
->stats
.unknown_mblks
++;
779 /* Called directly by ddp/zip.
781 elap_dataput(m
, elapp
, addr_flag
, addr
)
783 register at_ifaddr_t
*elapp
;
789 extern int zip_type_packet();
790 struct etalk_addr dest_addr
;
791 struct atalk_addr dest_at_addr
;
792 extern gbuf_t
*growmsg();
794 /* flag to aarp to loopback (default) */
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.
807 addr_flag
= *(u_char
*)gbuf_rptr(m
);
812 case AT_ADDR_NO_LOOP
:
817 dest_at_addr
= *(struct atalk_addr
*)gbuf_rptr(m
);
818 gbuf_rinc(m
,sizeof(struct atalk_addr
));
820 dest_at_addr
= *(struct atalk_addr
*)addr
;
824 dest_addr
= *(struct etalk_addr
*)gbuf_rptr(m
);
825 gbuf_rinc(m
,sizeof(struct etalk_addr
));
827 dest_addr
= *(struct etalk_addr
*)addr
;
830 gbuf_freel(m
); /* unknown address type, chuck it */
836 /* At this point, rptr points to ddp header for sure */
837 if (elapp
->ifState
== LAP_OFFLINE
) {
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
847 if (zip_type_packet(m
) == 0) {
853 elapp
->stats
.xmit_packets
++;
854 size
= gbuf_msgsize(m
);
855 elapp
->stats
.xmit_bytes
+= size
;
856 snmpStats
.dd_outLong
++;
859 case AT_ADDR_NO_LOOP
:
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.
866 error
= aarp_send_data(m
,elapp
,&dest_at_addr
, loop
);
869 error
= pat_output(elapp
, m
, &dest_addr
, 0);
875 /************************************************************************
878 ************************************************************************/
880 static int elap_online1(elapp
)
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
)
890 at_state
.flags
|= AT_ST_IF_CHANGED
;
892 if (elapp
->flags
& ELAP_CFG_HOME
) /* tell ddp_add_if if this is home */
893 elapp
->ifFlags
|= AT_IFF_DEFAULT
;
895 /* Get DDP started */
896 if ((errno
= ddp_add_if(elapp
)))
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)
906 /* set up multicast address for cable-wide broadcasts */
907 (void)at_reg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
909 // need to check again if interface is present
910 // can be lost in at_reg_mcast
911 if (elapp
->aa_ifp
== 0)
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
,
921 /* then later, after some timeouts AARPwakeup() is called */
923 return(elapp
->startup_error
);
926 static int re_aarp(elapp
)
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
)
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
);
941 elapp
->ifState
= LAP_OFFLINE
;
942 return(EADDRNOTAVAIL
);
946 /* called from AARPwakeup */
947 static void elap_online2(elapp
)
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"));
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
,
963 RTE_STATE_PERMANENT
| RTE_STATE_ZKNOWN
| RTE_STATE_GOOD
965 /* LD 081694: set the RTR_SEED_PORT flag for seed ports */
966 elapp
->ifFlags
|= RTR_SEED_PORT
;
969 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
970 ("elap_online: it's a router, but non seed\n"));
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. */
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"));
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 */
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 */
995 /* later, after some timeouts ZIPwakeup() is called. */
997 /* otherwise, we have the zone and the multicast already,
998 so don't bother with another ZIP GetNetInfo request */
1001 } /* elap_online2 */
1003 /* called from rtmp_router_start */
1004 int elap_online3(elapp
)
1007 elapp
->startup_inprogress
= TRUE
;
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
));
1015 if ((elapp
->startup_error
= re_aarp(elapp
)))
1016 return(elapp
->startup_error
);
1018 /* then later, after some timeouts AARPwakeup() is called */
1020 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
1021 (void)msleep(&elapp
->startup_inprogress
, atalk_mutex
, PSOCK
| PCATCH
,
1023 return(elapp
->startup_error
);
1024 } /* elap_online3 */
1026 /****************************************************************************
1029 ****************************************************************************/
1031 void elap_offline(elapp
)
1032 register at_ifaddr_t
*elapp
;
1035 void zip_sched_getnetinfo(); /* forward reference */
1039 dPrintf(D_M_ELAP
, D_L_SHUTDN_INFO
, ("elap_offline:%s\n", elapp
->ifName
));
1040 if (elapp
->ifState
!= LAP_OFFLINE
) {
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.
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
;
1051 ATDISABLE(s
, ddpinp_lock
);
1053 RT_DELETE(elapp
->ifThisCableEnd
,
1054 elapp
->ifThisCableStart
);
1055 ATENABLE(s
, ddpinp_lock
);
1057 /* make sure no zip timeouts are left running */
1058 elapp
->ifGNIScheduled
= 0;
1059 untimeout(zip_sched_getnetinfo
, elapp
);
1062 } /* elap_offline */
1065 static void add_route(rt
)
1068 /* support ioctl to manually add routes to table.
1069 this is really only for testing
1072 rt_insert( rt
->NetStop
, rt
->NetStart
, rt
->NextIRNet
,
1073 rt
->NextIRNode
, rt
->NetDist
, rt
->NetPort
,
1075 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("adding route: %ud:%ud dist:%ud\n",
1076 rt
->NetStart
, rt
->NetStop
,rt
->NetDist
));
1082 * Initialization that takes place each time AppleTalk is restarted.
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 */
1094 add_ddp_handler(RTMP_SOCKET
, rtmp_input
);
1095 ifID_home
= (at_ifaddr_t
*)NULL
;
1099 int ddp_shutdown(count_only
)
1103 asp_scb_t
*scb
, *scb_next
;
1104 struct atp_state
*atp
, *atp_next
;
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 */
1111 /* Network is shutting down... send error messages up on each open
1113 *** For now, for ASP, ATP and ADSP, attempt to notify open
1114 sockets, but return EBUSY and don't complete shutdown. ***
1117 s
= splimp(); /* *** previously contained mismatched locking
1118 that was ifdef'ed to splimp() *** */
1120 nbp_shutdown(); /* clear all known NVE */
1123 for (scb
= scb_used_list
; scb
; ) {
1124 scb_next
= scb
->next_scb
;
1127 dPrintf(D_M_ASP
, D_L_TRACE
, ("asp pid=%d\n", scb
->pid
));
1128 atalk_notify(scb
->gref
, ESHUTDOWN
);
1132 for (i
= 0; i
< 256 ; i
++) {
1133 if ((scb
= asp_scbQ
[i
]))
1135 scb_next
= scb
->next_scb
;
1138 dPrintf(D_M_ASP
, D_L_TRACE
,
1139 ("asp pid=%d\n", scb
->pid
));
1140 atalk_notify(scb
->gref
, ESHUTDOWN
);
1147 for (atp
= atp_used_list
; atp
; ) {
1148 atp_next
= atp
->atp_trans_waiting
;
1151 dPrintf(D_M_ATP
, D_L_TRACE
, ("atp pid=%d\n", atp
->atp_pid
));
1152 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1156 for (i
= 0; i
< 256; i
++) {
1157 if ((gref
= atp_inputQ
[i
]) && (gref
!= (gref_t
*)1)) {
1158 atp
= (struct atp_state
*)gref
->info
;
1162 dPrintf(D_M_ATP
, D_L_TRACE
,
1163 ("atp pid=%d\n", atp
->atp_pid
));
1164 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1171 for (sp
= ccb_used_list
; sp
; ) {
1172 sp_next
= sp
->otccbLink
;
1175 dPrintf(D_M_ADSP
, D_L_TRACE
, ("adsp pid=%d\n", sp
->pid
));
1176 atalk_notify(sp
->gref
, ESHUTDOWN
);
1180 for (i
= 0; i
< 256 ; i
++) {
1181 if ((sp
= adsp_inputQ
[i
]))
1183 sp_next
= sp
->otccbLink
;
1186 dPrintf(D_M_ADSP
, D_L_TRACE
,
1187 ("adsp pid=%d\n", sp
->pid
));
1188 atalk_notify(sp
->gref
, ESHUTDOWN
);
1195 for (gref
= ddp_head
.atpcb_next
; gref
!= &ddp_head
;
1196 gref
= gref
->atpcb_next
) {
1200 dPrintf(D_M_DDP
,D_L_TRACE
, ("ddp pid=%d\n", gref
->pid
));
1201 atalk_notify(gref
, ESHUTDOWN
);
1206 return(active_skts
);
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
)
1214 if (MULTIPORT_MODE
) {
1216 /* free memory allocated for the rtmp/zip tables */
1218 FREE(ZT_table
, M_RTABLE
);
1219 ZT_table
= (ZT_entry
*)NULL
;
1222 FREE(RT_table
, M_RTABLE
);
1223 RT_table
= (RT_entry
*)NULL
;
1227 at_state
.flags
= 0; /* make sure inits are done on restart */
1229 wakeup(&ifID_home
->startup_inprogress
); /* if rtmp_router_start still starting up */
1231 /* from original ddp_shutdown() */
1241 dPrintf(D_M_DDP
, D_L_VERBOSE
, ("DDP shutdown completed"));
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
1249 untimeout(aarp_sched_probe
, 0);
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 */
1262 } /* ddp_shutdown */
1264 int routerStart(keP
)
1267 register at_ifaddr_t
*ifID
;
1275 * this will cause the ports to glean from the net the relevant
1276 * information before forwarding
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
;
1287 * The next step is to check the information for each port before
1288 * declaring the ports up and forwarding
1290 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1291 ("router_start: waiting 20 sec before starting up\n"));
1293 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
1294 /* sleep for 20 seconds */
1296 /* the vaue of 10n terms of hz is 100ms */
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
))
1308 panic("routerStart: spurious interrupt");
1313 return(rtmp_router_start(keP
));
1314 /* was timeout(rtmp_router_start, 0, 20 * SYS_HZ); */
1317 void ZIPwakeup(elapp
, ZipError
)
1321 int s
, error
= ZipError
;
1323 ATDISABLE(s
, ddpinp_lock
);
1324 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
) {
1325 ATENABLE(s
, ddpinp_lock
);
1327 /* was ZIPContinue */
1328 /* was elapp_online() with jump to ZIP_sleep */
1330 /* instead of the goto ZIP_sleep ... */
1332 case 0 : /* success */
1333 elapp
->ifState
= LAP_ONLINE
;
1335 /* Send event with zone info. */
1336 atalk_post_msg(elapp
->aa_ifp
, KEV_ATALK_ZONEUPDATED
, 0, &(elapp
->ifZoneName
));
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"));
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
));
1361 ATENABLE(s
, ddpinp_lock
);
1364 void AARPwakeup(probe_cb
)
1365 aarp_amt_t
*probe_cb
;
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
);
1376 /* was AARPContinue */
1377 errno
= aarp_init2(elapp
);
1378 /* aarp_init2() returns either -1 or 0 */
1380 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
1381 ("elap_online aarp_init for %s\n",
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
;
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"));
1392 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
1393 ("elap_online: aarp_init returns zero\n"));
1394 elap_online2(elapp
);
1397 ATENABLE(s
, arpinp_lock
);
1400 void ddp_bit_reverse(addr
)
1401 unsigned char *addr
;
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
1440 for (k
=0; k
< 6; k
++)
1441 addr
[k
] = reverse_data
[addr
[k
]];
1444 static int elap_trackMcast(patp
, func
, addr
)
1451 switch(patp
->aa_ifp
->if_type
) {
1455 case IFT_IEEE8023ADLAG
: /* bonded ethernet */
1456 /* set addr to point to unique part of addr */
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
]) {
1468 case MCAST_TRACK_DELETE
:
1470 patp
->mcast
[loc
] = 0;
1473 case MCAST_TRACK_ADD
:
1474 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add loc:%d\n", i
));
1476 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was there\n"));
1478 break; /* already there */
1480 for (i
=0; i
< MAX_MCASTS
; i
++)
1481 if (patp
->mcast
[i
] == 0) {
1485 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add1 loc:%d\n", i
));
1487 patp
->mcast
[loc
] = c
;
1488 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, adding(%x)\n",
1489 (*(int*)addr
)&0xffffff));
1492 /*errno = ENOMEM; */ /*LD 5/7/97 nobody is using that */
1496 case MCAST_TRACK_CHECK
:
1498 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:check, addr was there\n"));
1502 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was NOT there\n"));
1507 /*errno = EINVAL;*/ /*LD 5/7/97 nobody is using that */
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
1523 static getSnmpCfg(snmp
)
1530 snmp
->cfg_ifCnt
= 0;
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
) {
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
) {
1543 case IFT_IEEE8023ADLAG
: /* bonded ethernet */
1544 ifc
->ifc_type
= SNMP_TYPE_ETHER2
;
1546 case IFT_ISO88025
: /* token ring */
1547 ifc
->ifc_type
= SNMP_TYPE_TOKEN
;
1551 ifc
->ifc_type
= SNMP_TYPE_OTHER
;
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
;
1562 else if (elapp
->ifDefZone
) {
1563 ifc
->ifc_zoneName
= ZT_table
[elapp
->ifDefZone
-1].Zone
;
1565 else /* temp, debug only */
1566 ifc
->ifc_zoneName
= ZT_table
[0].Zone
;
1568 if (elapp
->ifFlags
& RTR_SEED_PORT
) {
1569 ifc
->ifc_netCfg
= SNMP_CFG_CONFIGURED
;
1570 ifc
->ifc_zoneCfg
= SNMP_CFG_CONFIGURED
;
1573 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1574 ifc
->ifc_zoneCfg
= SNMP_CFG_GARNERED
;
1577 else { /* single-port mode */
1578 if (elapp
->ifRouterState
== ROUTER_AROUND
) {
1579 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1582 ifc
->ifc_netCfg
= SNMP_CFG_GUESSED
;
1583 ifc
->ifc_zoneCfg
= SNMP_CFG_UNCONFIG
;
1588 snmp
->cfg_flags
= at_state
.flags
;
1594 int at_reg_mcast(ifID
, data
)
1598 struct ifnet
*nddp
= ifID
->aa_ifp
;
1599 struct sockaddr_dl sdl
;
1603 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1607 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
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
;
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,
1626 if (if_addmulti(nddp
, &sdl
, 0))
1633 int at_unreg_mcast(ifID
, data
)
1637 struct ifnet
*nddp
= ifID
->aa_ifp
;
1638 struct sockaddr_dl sdl
;
1642 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1646 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
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
;
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,
1663 bzero(data
, sizeof(struct etalk_addr
));
1665 if (if_delmulti(nddp
, &sdl
))
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.
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.
1681 int at_reg_mcast(ifID
, data
)
1685 struct ifnet
*nddp
= ifID
->aa_ifp
;
1686 struct sockaddr_dl sdl
;
1690 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1693 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1696 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1697 sdl
.sdl_family
= AF_LINK
;
1699 sdl
.sdl_type
= nddp
->if_type
;
1700 sdl
.sdl_alen
= nddp
->if_addrlen
;
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
);
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,
1711 if (if_addmulti(nddp
, (struct sockaddr
*)&sdl
, 0))
1718 int at_unreg_mcast(ifID
, data
)
1722 struct ifnet
*nddp
= ifID
->aa_ifp
;
1723 struct sockaddr_dl sdl
;
1727 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1731 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1733 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1734 sdl
.sdl_family
= AF_LINK
;
1736 sdl
.sdl_type
= nddp
->if_type
;
1737 sdl
.sdl_alen
= nddp
->if_addrlen
;
1739 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1740 nddp
->if_name
, nddp
->if_unit
);
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,
1746 bzero(data
, ETHERNET_ADDR_LEN
);
1748 if (if_delmulti(nddp
, (struct sockaddr
*)&sdl
))