2 * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1988, 1989, 1993-1998 Apple Computer, Inc.
32 /* at_elap.c: 2.0, 1.29; 10/4/93; Apple Computer, Inc. */
34 /* This is the file which implements all the streams driver
35 * functionality required for EtherTalk.
40 03-14-94 jjs Changed all functions which assumed only one port would
41 ever be used. Added validate_msg_size, changed elap_online
42 to work with the h/w name only (e.g. 'et2').
44 Modified for MP, 1996 by Tuyen Nguyen
45 Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
49 #define RESOLVE_DBG /* for debug.h global resolution */
50 #include <sys/errno.h>
51 #include <sys/types.h>
52 #include <sys/param.h>
53 #include <machine/spl.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
57 #include <sys/filedesc.h>
58 #include <sys/fcntl.h>
60 #include <sys/ioctl.h>
61 #include <sys/socket.h>
62 #include <net/if_dl.h>
63 #include <sys/socketvar.h>
64 #include <sys/malloc.h>
65 #include <sys/domain.h>
66 #include <sys/sockio.h>
67 #include <vm/vm_kern.h> /* for kernel_map */
71 #include <net/if_types.h>
73 #include <netat/sysglue.h>
74 #include <netat/appletalk.h>
75 #include <netat/at_pcb.h>
76 #include <netat/at_var.h>
77 #include <netat/ddp.h>
78 #include <netat/lap.h>
79 #include <netat/routing_tables.h> /* rtmp+zip table structs */
80 #include <netat/zip.h>
81 #include <netat/nbp.h>
82 #include <netat/at_snmp.h>
83 #include <netat/at_aarp.h>
84 #include <netat/asp.h>
85 #include <netat/atp.h>
86 #include <netat/debug.h>
87 #include <netat/adsp.h>
88 #include <netat/adsp_internal.h>
89 #include <netat/at_pat.h>
90 #include <netat/rtmp.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 short appletalk_inited
;
127 extern int adspInited
;
128 extern struct atpcb ddp_head
;
129 extern gref_t
*atp_inputQ
[];
130 extern struct atp_state
*atp_used_list
;
131 extern asp_scb_t
*asp_scbQ
[];
132 extern asp_scb_t
*scb_used_list
;
133 extern CCB
*adsp_inputQ
[];
134 extern CCB
*ccb_used_list
;
135 extern at_ddp_stats_t at_ddp_stats
;
136 extern lck_mtx_t
* atalk_mutex
;
139 int rtmp_router_start(at_kern_err_t
*);
140 static void add_route(RT_entry
*);
141 void elap_offline(at_ifaddr_t
*);
142 static int elap_online1(at_ifaddr_t
*);
143 static void elap_online2(at_ifaddr_t
*);
144 int elap_online3(at_ifaddr_t
*);
145 static int re_aarp(at_ifaddr_t
*);
146 static int getSnmpCfg(snmpCfg_t
*);
148 int routerStart(at_kern_err_t
*);
150 static int validate_msg_size(gbuf_t
*, gref_t
*, at_ifaddr_t
**);
151 at_ifaddr_t
*find_ifID(char *);
152 int lap_online( at_ifaddr_t
*, at_if_cfg_t
*cfgp
);
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
;
182 iocbp
= (ioc_t
*) gbuf_rptr(m
);
184 dPrintf(D_M_ELAP
, D_L_INFO
, ("validate_msg_size: ioc_cmd = %d\n",
186 switch (iocbp
->ioc_cmd
) {
187 case LAP_IOC_ADD_ROUTE
:
188 size
= sizeof(RT_entry
);
190 case LAP_IOC_GET_ROUTE
:
191 size
= sizeof(RT_entry
);
193 case LAP_IOC_GET_ZONE
:
194 size
= sizeof(ZT_entryno
);
196 case LAP_IOC_SNMP_GET_CFG
:
197 case LAP_IOC_SNMP_GET_AARP
:
198 case LAP_IOC_SNMP_GET_ZIP
:
199 case LAP_IOC_SNMP_GET_RTMP
:
200 case LAP_IOC_SNMP_GET_NBP
:
204 case ELAP_IOC_GET_STATS
:
205 case LAP_IOC_SNMP_GET_DDP
:
210 dPrintf(D_M_ELAP
, D_L_ERROR
, ("validate_msg_size: unknown ioctl\n"));
214 if (size
== 0) { /* a non-data ioctl */
218 if (gbuf_cont(m
) != NULL
)
219 i
= gbuf_len(gbuf_cont(m
));
220 if (iocbp
->ioc_count
< size
|| (gbuf_cont(m
) == NULL
) || i
< size
) {
221 dPrintf(D_M_ELAP
, D_L_ERROR
,
222 ("ioctl msg error:s:%d c:%d bcont:%c delta:%d\n",
223 size
, iocbp
->ioc_count
,
224 gbuf_cont(m
)? 'Y' : 'N', i
));
230 ioc_ack(EMSGSIZE
, m
, gref
);
232 } /* validate_msg_size */
234 int lap_online(elapp
, cfgp
)
240 if (elapp
->ifState
!= LAP_OFFLINE
) {
245 if (cfgp
->flags
& ELAP_CFG_HOME
) {
247 /* only 1 home allowed! */
250 dPrintf(D_M_ELAP
, D_L_STARTUP
,
251 ("elap_wput home I/F:%s\n", cfgp
->ifr_name
));
252 elapp
->flags
|= ELAP_CFG_HOME
;
255 if (MULTIPORT_MODE
) {
256 elapp
->flags
|= ELAP_CFG_ZONELESS
;
257 if (ROUTING_MODE
&& cfgp
->netStart
)
258 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
;
320 int size
, totalsize
= 0, tabsize
;
321 gbuf_t
*mn
; /* new gbuf */
322 gbuf_t
*mo
; /* old gbuf */
323 gbuf_t
*mt
= NULL
; /* temp */
327 switch (gbuf_type(m
)) {
330 dPrintf(D_M_ELAP
,D_L_ERROR
,
331 ("Output data to control channel is ignored\n"));
335 iocbp
= (ioc_t
*) gbuf_rptr(m
);
337 if (validate_msg_size(m
, gref
, &elapp
))
341 cfgp
= (at_if_cfg_t
*) gbuf_rptr(gbuf_cont(m
));
343 if (LAP_IOC_MYIOCTL(iocbp
->ioc_cmd
) ||
344 ELAP_IOC_MYIOCTL(iocbp
->ioc_cmd
)) {
346 switch (iocbp
->ioc_cmd
) {
347 case ELAP_IOC_GET_STATS
:
348 #ifdef APPLETALK_DEBUG
349 kprintf("LAP_IOC_GET_STATS\n");
351 if ( (gbuf_cont(m
) == NULL
)
352 || (elapp
= find_ifID(gbuf_rptr(gbuf_cont(m
)))) == NULL
) {
353 ioc_ack(EINVAL
, m
, gref
);
356 gbuf_freem(gbuf_cont(m
));
357 if ((gbuf_cont(m
) =gbuf_alloc(sizeof(at_elap_stats_t
),
359 ioc_ack(ENOBUFS
, m
, gref
);
362 statsp
= ((at_elap_stats_t
*)gbuf_rptr(gbuf_cont(m
)));
363 *statsp
= elapp
->stats
;
364 gbuf_wset(gbuf_cont(m
),sizeof(at_elap_stats_t
));
365 iocbp
->ioc_count
= sizeof(at_elap_stats_t
);
369 case LAP_IOC_ADD_ROUTE
:
370 #ifdef APPLETALK_DEBUG
371 kprintf("LAP_IOC_ADD_ROUTE\n");
373 add_route((RT_entry
*)gbuf_rptr(gbuf_cont(m
)));
377 case LAP_IOC_GET_ZONE
:
378 #ifdef APPLETALK_DEBUG
379 kprintf("LAP_IOC_GET_ZONE\n");
381 /* return next ZT_entryno from ZT_table
382 a pointer to the struct ZT_entryno is passed down from
383 user space and the first byte is cast to a int, if
384 this int is non-zero, then the first ZT_entry is
385 returned and subsequent calls with a zero value
386 will return the next entry in the table. The next
387 read after the last valid entry will return EINVAL
392 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
393 gbuf_freem(gbuf_cont(m
));
396 pZTe
= zt_getNextZone(i
);
398 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(ZT_entryno
), PRI_MED
)) == NULL
) {
399 ioc_ack(ENOBUFS
, m
, gref
);
402 *(ZT_entryno
*)gbuf_rptr(gbuf_cont(m
)) = *pZTe
;
403 gbuf_wset(gbuf_cont(m
),sizeof(ZT_entryno
));
404 iocbp
->ioc_count
= sizeof(ZT_entryno
);
408 ioc_ack(EINVAL
, m
, gref
);
412 case LAP_IOC_GET_ROUTE
:
413 #ifdef APPLETALK_DEBUG
414 kprintf("LAP_IOC_GET_ROUTE\n");
416 /* return next RT_entry from RT_table
417 * a pointer to the struct RT_entry is
418 * passed down from user space and the first
419 * byte is cast to a int, if this int is
420 * non-zero, then the first RT_entry is
421 * returned and subsequent calls with a
422 * zero value will return the next entry in
423 * the table. The next read after the last
424 * valid entry will return EINVAL
429 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
430 gbuf_freem(gbuf_cont(m
));
433 pRT
= rt_getNextRoute(i
);
435 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(RT_entry
), PRI_MED
)) == NULL
) {
436 ioc_ack(ENOBUFS
, m
, gref
);
439 *(RT_entry
*)gbuf_rptr(gbuf_cont(m
)) = *pRT
;
440 gbuf_wset(gbuf_cont(m
),sizeof(RT_entry
));
441 iocbp
->ioc_count
= sizeof(RT_entry
);
445 ioc_ack(EINVAL
, m
, gref
);
449 case LAP_IOC_SNMP_GET_DDP
:
450 #ifdef APPLETALK_DEBUG
451 kprintf("LAP_IOC_SNMP_GET_DDP\n");
453 if (!(at_state
.flags
& AT_ST_STARTED
)) {
454 ioc_ack(ENOTREADY
, m
, gref
);
457 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(snmpStats_t
),
459 ioc_ack(ENOBUFS
, m
, gref
);
463 *(snmpStats_t
*)gbuf_rptr(gbuf_cont(m
)) = snmpStats
;
464 gbuf_wset(gbuf_cont(m
),sizeof(snmpStats
));
465 iocbp
->ioc_count
= sizeof(snmpStats
);
468 case LAP_IOC_SNMP_GET_CFG
:
469 #ifdef APPLETALK_DEBUG
470 kprintf("LAP_IOC_SNMP_GET_CFG\n");
475 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
476 gbuf_freem(gbuf_cont(m
));
478 if (!(at_state
.flags
& AT_ST_STARTED
)) {
480 iocbp
->ioc_count
= 0;
481 ioc_ack(ENOTREADY
, m
, gref
);
482 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
483 ("elap_wput: cfg req, stack down\n"));
486 if (i
== UPDATE_IF_CHANGED
&&
487 !(at_state
.flags
& AT_ST_IF_CHANGED
)) {
488 iocbp
->ioc_count
= 0;
490 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
491 ("elap_wput: cfg req, unchanged\n"));
494 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
495 ("elap_wput: cfg req, changed\n"));
497 if (getSnmpCfg(&snmp
)) {
498 dPrintf(D_M_ELAP
,D_L_ERROR
,
499 ("elap_wput:SNMP_GET_CFG error\n"));
500 ioc_ack(EOPNOTSUPP
, m
, gref
);
503 /* send up only used part of table */
504 size
= sizeof(snmp
) -
505 sizeof(snmpIfCfg_t
) * (MAX_IFS
- snmp
.cfg_ifCnt
);
507 if ((gbuf_cont(m
) = gbuf_alloc(size
, PRI_MED
)) == NULL
) {
508 ioc_ack(ENOBUFS
, m
, gref
);
511 bcopy(&snmp
,gbuf_rptr(gbuf_cont(m
)),size
);
512 gbuf_wset(gbuf_cont(m
),size
);
513 iocbp
->ioc_count
= size
;
514 at_state
.flags
&= ~AT_ST_IF_CHANGED
;
519 case LAP_IOC_SNMP_GET_AARP
:
521 snmpAarpEnt_t
*snmpp
;
523 #ifdef APPLETALK_DEBUG
524 kprintf("LAP_IOC_SNMP_GET_AARP\n");
526 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
527 gbuf_freem(gbuf_cont(m
));
529 dPrintf(D_M_ELAP
,D_L_INFO
,
530 ("elap_wput:calling getarp,i=%d\n", i
));
532 bytes
= i
* sizeof(snmpAarpEnt_t
);
533 dPrintf(D_M_ELAP
,D_L_INFO
,
534 ("elap_wput:getarp returned, i=%d,bytes=%d\n",
537 if ((gbuf_cont(m
) = gbuf_alloc(bytes
, PRI_MED
)) == NULL
) {
538 ioc_ack(ENOBUFS
, m
, gref
);
541 bcopy(snmpp
, gbuf_rptr(gbuf_cont(m
)), bytes
);
542 gbuf_wset(gbuf_cont(m
),bytes
);
543 iocbp
->ioc_count
= bytes
;
547 ioc_ack(EOPNOTSUPP
, m
, gref
);
551 case LAP_IOC_SNMP_GET_ZIP
:
552 #ifdef APPLETALK_DEBUG
553 kprintf("LAP_IOC_SNMP_GET_ZIP\n");
555 { /* matching brace NOT in this case */
557 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
558 gbuf_freem(gbuf_cont(m
));
560 if (!(at_state
.flags
& AT_ST_STARTED
)) {
561 ioc_ack(ENOTREADY
, m
, gref
);
564 if (i
== UPDATE_IF_CHANGED
&&
565 !(at_state
.flags
& AT_ST_ZT_CHANGED
)) {
566 iocbp
->ioc_count
= 0;
571 tabsize
= getZipTableSize();
573 /* retrieve table into multiple gbufs */
574 for (i
=0; i
<tabsize
; i
+=j
) {
576 MAX_ZIP
? MAX_ZIP
: tabsize
- i
;
577 size
= j
< MAX_ZIP
? sizeof(ZT_entry
)*j
: MAX_ZIP_BYTES
;
578 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
580 gbuf_freem(gbuf_cont(m
));
581 ioc_ack(ENOBUFS
, m
, gref
);
584 if (!mo
) { /* if first new one */
593 getZipTable((ZT_entry
*)gbuf_rptr(mn
),i
,j
);
596 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
599 iocbp
->ioc_count
= 0;
600 ioc_ack(ENOBUFS
, m
, gref
);
604 dPrintf(D_M_ELAP
,D_L_WARNING
,
605 ("elap_wput:snmp: empty zip table\n"));
608 *(int*)gbuf_rptr(gbuf_cont(m
)) = totalsize
; /* return table size */
609 gbuf_wset(gbuf_cont(m
),sizeof(int));
610 iocbp
->ioc_count
= sizeof(int);
613 atalk_putnext(gref
,mt
); /* send up table */
614 at_state
.flags
&= ~AT_ST_ZT_CHANGED
;
617 case LAP_IOC_SNMP_GET_RTMP
:
618 #ifdef APPLETALK_DEBUG
619 kprintf("LAP_IOC_SNMP_GET_RTMP\n");
621 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
622 gbuf_freem(gbuf_cont(m
));
624 if (!(at_state
.flags
& AT_ST_STARTED
)) {
625 ioc_ack(ENOTREADY
, m
, gref
);
628 if (i
== UPDATE_IF_CHANGED
&&
629 !(at_state
.flags
& AT_ST_RT_CHANGED
)) {
630 iocbp
->ioc_count
= 0;
636 tabsize
= getRtmpTableSize();
638 /* retrieve table into multiple gbufs */
639 for (i
=0; i
<tabsize
; i
+=j
) {
641 MAX_RTMP
? MAX_RTMP
: tabsize
- i
;
642 size
= j
< MAX_RTMP
? sizeof(RT_entry
)*j
: MAX_RTMP_BYTES
;
643 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
645 gbuf_freem(gbuf_cont(m
));
646 ioc_ack(ENOBUFS
, m
, gref
);
649 if (!mo
) { /* if first new one */
658 getRtmpTable((RT_entry
*)gbuf_rptr(mn
),i
,j
);
661 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
664 iocbp
->ioc_count
= 0;
665 ioc_ack(ENOBUFS
, m
, gref
);
670 *(int*)gbuf_rptr(gbuf_cont(m
)) = totalsize
; /* return table size */
671 gbuf_wset(gbuf_cont(m
),sizeof(int));
672 iocbp
->ioc_count
= sizeof(int);
675 atalk_putnext(gref
,mt
); /* send up table */
676 at_state
.flags
&= ~AT_ST_RT_CHANGED
;
679 case LAP_IOC_SNMP_GET_NBP
:
680 #ifdef APPLETALK_DEBUG
681 kprintf("LAP_IOC_SNMP_GET_NBP\n");
683 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
684 gbuf_freem(gbuf_cont(m
));
686 if (!(at_state
.flags
& AT_ST_STARTED
)) {
687 ioc_ack(ENOTREADY
, m
, gref
);
690 if (i
== UPDATE_IF_CHANGED
&&
691 !(at_state
.flags
& AT_ST_NBP_CHANGED
)) {
692 iocbp
->ioc_count
= 0;
694 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
695 ("elap_wput: nbp req denied, no change\n"));
700 tabsize
= getNbpTableSize();
702 /* retrieve table into multiple gbufs */
703 for (i
=0; i
<tabsize
; i
+=j
) {
705 MAX_NBP
? MAX_NBP
: tabsize
- i
;
706 size
= j
< MAX_NBP
? sizeof(snmpNbpEntry_t
)*j
: MAX_NBP_BYTES
;
708 size
+= SNMP_NBP_HEADER_SIZE
;
709 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
711 gbuf_freem(gbuf_cont(m
));
712 ioc_ack(ENOBUFS
, m
, gref
);
715 if (!mo
) { /* if first new one */
718 nbp
= (snmpNbpTable_t
*)gbuf_rptr(mn
);
719 nbp
->nbpt_entries
= tabsize
;
720 nbp
->nbpt_zone
= ifID_home
->ifZoneName
;
721 getNbpTable(nbp
->nbpt_table
,i
,j
);
726 getNbpTable((snmpNbpEntry_t
*)gbuf_rptr(mn
),i
,j
);
731 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
734 iocbp
->ioc_count
= 0;
735 ioc_ack(ENOBUFS
, m
, gref
);
740 *(int*)gbuf_rptr(gbuf_cont(m
)) = totalsize
; /* return table size */
741 gbuf_wset(gbuf_cont(m
),sizeof(int));
742 iocbp
->ioc_count
= sizeof(int);
745 atalk_putnext(gref
,mt
); /* send up table */
746 at_state
.flags
&= ~AT_ST_NBP_CHANGED
;
751 #ifdef APPLETALK_DEBUG
752 kprintf("unknown ioctl %d\n", iocbp
->ioc_cmd
);
754 ioc_ack(ENOTTY
, m
, gref
);
755 dPrintf(D_M_ELAP
, D_L_WARNING
,
756 ("elap_wput: unknown ioctl (%d)\n", iocbp
->ioc_cmd
));
759 elapp
->stats
.unknown_mblks
++;
774 /* Called directly by ddp/zip.
777 elap_dataput(m
, elapp
, addr_flag
, addr
)
779 register at_ifaddr_t
*elapp
;
785 struct etalk_addr dest_addr
;
786 struct atalk_addr dest_at_addr
;
788 /* flag to aarp to loopback (default) */
790 /* the incoming frame is of the form {flag, address, ddp...}
791 * where "flag" indicates whether the address is an 802.3
792 * (link) address, or an appletalk address. If it's an
793 * 802.3 address, the packet can just go out to the network
794 * through PAT, if it's an appletalk address, AT->802.3 address
795 * resolution needs to be done.
796 * If 802.3 address is known, strip off the flag and 802.3
797 * address, and prepend 802.2 and 802.3 headers.
801 addr_flag
= *(u_char
*)gbuf_rptr(m
);
806 case AT_ADDR_NO_LOOP
:
811 dest_at_addr
= *(struct atalk_addr
*)gbuf_rptr(m
);
812 gbuf_rinc(m
,sizeof(struct atalk_addr
));
814 dest_at_addr
= *(struct atalk_addr
*)addr
;
818 dest_addr
= *(struct etalk_addr
*)gbuf_rptr(m
);
819 gbuf_rinc(m
,sizeof(struct etalk_addr
));
821 dest_addr
= *(struct etalk_addr
*)addr
;
824 gbuf_freel(m
); /* unknown address type, chuck it */
830 /* At this point, rptr points to ddp header for sure */
831 if (elapp
->ifState
== LAP_OFFLINE
) {
836 if (elapp
->ifState
== LAP_ONLINE_FOR_ZIP
) {
837 /* see if this is a ZIP packet that we need
838 * to let through even though network is
841 if (zip_type_packet(m
) == 0) {
847 elapp
->stats
.xmit_packets
++;
848 size
= gbuf_msgsize(m
);
849 elapp
->stats
.xmit_bytes
+= size
;
850 snmpStats
.dd_outLong
++;
853 case AT_ADDR_NO_LOOP
:
856 * we don't want elap to be looking into ddp header, so
857 * it doesn't know net#, consequently can't do
858 * AMT_LOOKUP. That task left to aarp now.
860 error
= aarp_send_data(m
, elapp
, &dest_at_addr
, loop
);
863 error
= pat_output(elapp
, m
, (unsigned char *)&dest_addr
, 0);
869 /************************************************************************
872 ************************************************************************/
874 static int elap_online1(elapp
)
879 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online:%s elapp:0x%x\n",
880 (elapp
->ifName
) ? &elapp
->ifName
[0] : "NULL interface", (u_int
) elapp
));
881 if (elapp
->ifState
!= LAP_OFFLINE
|| elapp
->startup_inprogress
== TRUE
)
884 at_state
.flags
|= AT_ST_IF_CHANGED
;
886 if (elapp
->flags
& ELAP_CFG_HOME
) /* tell ddp_add_if if this is home */
887 elapp
->ifFlags
|= AT_IFF_DEFAULT
;
889 /* Get DDP started */
890 if ((errno
= ddp_add_if(elapp
)))
893 // check if we still have an interface - can be lost when
894 // ddp_add_if calls malloc
895 // need to make check here after ddp_add_if completes because
896 // lap_online will call ddp_rem_if if we fail here
897 if (elapp
->aa_ifp
== 0)
900 /* set up multicast address for cable-wide broadcasts */
901 (void)at_reg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
903 // need to check again if interface is present
904 // can be lost in at_reg_mcast
905 if (elapp
->aa_ifp
== 0)
908 elapp
->startup_inprogress
= TRUE
;
909 if (! (elapp
->startup_error
= re_aarp(elapp
))) {
910 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
911 (void)msleep(&elapp
->startup_inprogress
, atalk_mutex
, PSOCK
| PCATCH
,
915 /* then later, after some timeouts AARPwakeup() is called */
917 return(elapp
->startup_error
);
920 static int re_aarp(elapp
)
925 /* We now call aarp_init() to assign an appletalk node addr */
926 errno
= aarp_init1(elapp
);
927 /* aarp_init1() returns either -1 or ENOTREADY */
928 if (errno
== ENOTREADY
)
931 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
932 ("elap_online aarp_init for %s\n", elapp
->ifName
));
933 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
935 elapp
->ifState
= LAP_OFFLINE
;
936 return(EADDRNOTAVAIL
);
940 /* called from AARPwakeup */
941 static void elap_online2(elapp
)
944 if (MULTIPORT_MODE
) {
945 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
946 ("elap_online: re_aarp, we know it's a router...\n"));
948 if (elapp
->flags
& ELAP_CFG_SEED
) {
949 /* add route table entry (zones to be added later) */
950 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
951 ("elap_online: rt_insert Cable %d-%d port =%d as SEED\n",
952 elapp
->ifThisCableStart
, elapp
->ifThisCableEnd
, elapp
->ifPort
));
953 rt_insert(elapp
->ifThisCableEnd
,
954 elapp
->ifThisCableStart
,
957 RTE_STATE_PERMANENT
| RTE_STATE_ZKNOWN
| RTE_STATE_GOOD
959 /* LD 081694: set the RTR_SEED_PORT flag for seed ports */
960 elapp
->ifFlags
|= RTR_SEED_PORT
;
964 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
965 ("elap_online: it's a router, but non seed\n"));
969 if (elapp
->flags
& ELAP_CFG_ZONELESS
) {
970 /* ELAP_CFG_ZONELESS tells us that it is a router or in
971 multihome mode, so we don't want to do the GetNetInfo
972 exchange with the router. */
974 elapp
->ifState
= LAP_ONLINE_ZONELESS
;
975 elapp
->startup_inprogress
= FALSE
;
976 wakeup(&elapp
->startup_inprogress
);
977 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online: ack 3\n"));
981 /* if we don't already have a zone and a multicast address */
982 if (*(int *)&elapp
->ZoneMcastAddr
== 0 || elapp
->ifZoneName
.len
== 0) {
983 /* hzonehash is a global containing the nbp hash for the startup_zone */
986 /* Get ZIP rolling to get zone multicast address, etc. */
987 elapp
->ifState
= LAP_ONLINE_FOR_ZIP
;
988 (void)zip_control(elapp
, ZIP_ONLINE
);
989 /* zip_control (w. control == ZIP_ONLINE) always returns ENOTREADY */
991 /* later, after some timeouts ZIPwakeup() is called. */
993 /* otherwise, we have the zone and the multicast already,
994 so don't bother with another ZIP GetNetInfo request */
999 /* called from rtmp_router_start */
1000 int elap_online3(elapp
)
1003 elapp
->startup_inprogress
= TRUE
;
1005 /* just reset the net range */
1006 elapp
->initial_addr
.s_net
= 0;
1007 elapp
->initial_addr
.s_node
= 0;
1008 dPrintf(D_M_ELAP_LOW
, D_L_STARTUP_INFO
,
1009 ("elap_online: goto re_aarp port=%d\n", elapp
->ifPort
));
1011 if ((elapp
->startup_error
= re_aarp(elapp
)))
1012 return(elapp
->startup_error
);
1014 /* then later, after some timeouts AARPwakeup() is called */
1016 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
1017 (void)msleep(&elapp
->startup_inprogress
, atalk_mutex
, PSOCK
| PCATCH
,
1019 return(elapp
->startup_error
);
1020 } /* elap_online3 */
1022 /****************************************************************************
1025 ****************************************************************************/
1027 void elap_offline(elapp
)
1028 register at_ifaddr_t
*elapp
;
1031 dPrintf(D_M_ELAP
, D_L_SHUTDN_INFO
, ("elap_offline:%s\n", elapp
->ifName
));
1032 if (elapp
->ifState
!= LAP_OFFLINE
) {
1034 /* Since AppleTalk is going away, remove the cable
1035 * multicast address and turn the interface off so that all
1036 * AppleTalk packets are dropped in the driver itself.
1037 * Get rid of the zone multicast address prior to going Offline.
1039 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->ZoneMcastAddr
);
1040 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
1041 elapp
->ifState
= LAP_OFFLINE
;
1044 RT_DELETE(elapp
->ifThisCableEnd
,
1045 elapp
->ifThisCableStart
);
1047 /* make sure no zip timeouts are left running */
1048 elapp
->ifGNIScheduled
= 0;
1049 untimeout(zip_sched_getnetinfo
, elapp
);
1052 } /* elap_offline */
1055 static void add_route(rt
)
1058 /* support ioctl to manually add routes to table.
1059 this is really only for testing
1062 rt_insert( rt
->NetStop
, rt
->NetStart
, rt
->NextIRNet
,
1063 rt
->NextIRNode
, rt
->NetDist
, rt
->NetPort
,
1065 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("adding route: %ud:%ud dist:%ud\n",
1066 rt
->NetStart
, rt
->NetStop
,rt
->NetDist
));
1072 * Initialization that takes place each time AppleTalk is restarted.
1077 TAILQ_INIT(&at_ifQueueHd
);
1078 TAILQ_INIT(&name_registry
);
1079 bzero(at_interfaces
, sizeof(at_interfaces
));
1080 bzero(ifID_table
, sizeof(ifID_table
));
1081 bzero(&at_ddp_stats
, sizeof(at_ddp_stats_t
));
1082 rtmp_init(); /* initialize trackedrouters */
1084 add_ddp_handler(RTMP_SOCKET
, rtmp_input
);
1085 ifID_home
= (at_ifaddr_t
*)NULL
;
1089 int ddp_shutdown(count_only
)
1093 asp_scb_t
*scb
, *scb_next
;
1094 struct atp_state
*atp
, *atp_next
;
1097 int i
, active_skts
= 0; /* count of active pids for non-socketized
1098 AppleTalk protocols */
1100 /* Network is shutting down... send error messages up on each open
1102 *** For now, for ASP, ATP and ADSP, attempt to notify open
1103 sockets, but return EBUSY and don't complete shutdown. ***
1107 nbp_shutdown(); /* clear all known NVE */
1110 for (scb
= scb_used_list
; scb
; ) {
1111 scb_next
= scb
->next_scb
;
1114 dPrintf(D_M_ASP
, D_L_TRACE
, ("asp pid=%d\n", scb
->pid
));
1115 atalk_notify(scb
->gref
, ESHUTDOWN
);
1119 for (i
= 0; i
< 256 ; i
++) {
1120 if ((scb
= asp_scbQ
[i
]))
1122 scb_next
= scb
->next_scb
;
1125 dPrintf(D_M_ASP
, D_L_TRACE
,
1126 ("asp pid=%d\n", scb
->pid
));
1127 atalk_notify(scb
->gref
, ESHUTDOWN
);
1134 for (atp
= atp_used_list
; atp
; ) {
1135 atp_next
= atp
->atp_trans_waiting
;
1138 dPrintf(D_M_ATP
, D_L_TRACE
, ("atp pid=%d\n", atp
->atp_pid
));
1139 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1143 for (i
= 0; i
< 256; i
++) {
1144 if ((gref
= atp_inputQ
[i
]) && (gref
!= (gref_t
*)1)) {
1145 atp
= (struct atp_state
*)gref
->info
;
1149 dPrintf(D_M_ATP
, D_L_TRACE
,
1150 ("atp pid=%d\n", atp
->atp_pid
));
1151 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1158 for (sp
= ccb_used_list
; sp
; ) {
1159 sp_next
= sp
->otccbLink
;
1162 dPrintf(D_M_ADSP
, D_L_TRACE
, ("adsp pid=%d\n", sp
->pid
));
1163 atalk_notify(sp
->gref
, ESHUTDOWN
);
1167 for (i
= 0; i
< 256 ; i
++) {
1168 if ((sp
= adsp_inputQ
[i
]))
1170 sp_next
= sp
->otccbLink
;
1173 dPrintf(D_M_ADSP
, D_L_TRACE
,
1174 ("adsp pid=%d\n", sp
->pid
));
1175 atalk_notify(sp
->gref
, ESHUTDOWN
);
1182 for (gref
= ddp_head
.atpcb_next
; gref
!= &ddp_head
;
1183 gref
= gref
->atpcb_next
) {
1187 dPrintf(D_M_DDP
,D_L_TRACE
, ("ddp pid=%d\n", gref
->pid
));
1188 atalk_notify(gref
, ESHUTDOWN
);
1192 return(active_skts
);
1194 /* if there are no interfaces in the process of going online, continue shutting down DDP */
1195 for (i
= 0; i
< IF_TOTAL_MAX
; i
++) {
1196 if (at_interfaces
[i
].startup_inprogress
== TRUE
)
1199 if (MULTIPORT_MODE
) {
1201 /* free memory allocated for the rtmp/zip tables */
1203 FREE(ZT_table
, M_RTABLE
);
1204 ZT_table
= (ZT_entry
*)NULL
;
1207 FREE(RT_table
, M_RTABLE
);
1208 RT_table
= (RT_entry
*)NULL
;
1212 at_state
.flags
= 0; /* make sure inits are done on restart */
1214 wakeup(&ifID_home
->startup_inprogress
); /* if rtmp_router_start still starting up */
1216 /* from original ddp_shutdown() */
1226 dPrintf(D_M_DDP
, D_L_VERBOSE
, ("DDP shutdown completed"));
1229 * make sure we don't have a probe timeout hanging around
1230 * it's going to try and make use of an entry in at_interfaces
1231 * which is going to be zero'd out by the call to ddp_start a
1232 * little further down
1234 untimeout(aarp_sched_probe
, 0);
1236 /* *** after an SIOCSIFADDR and before an AIOCSIFADDR,
1237 this is the only place to find the ifID *** */
1238 for (i
= 0; i
< IF_TOTAL_MAX
; i
++) {
1239 ifID
= &at_interfaces
[i
];
1240 /* do LAP_IOC_OFFLINE processing */
1246 } /* ddp_shutdown */
1248 int routerStart(keP
)
1251 register at_ifaddr_t
*ifID
;
1259 * this will cause the ports to glean from the net the relevant
1260 * information before forwarding
1262 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1263 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1264 ("routerStart Port %d (%s) set to activating\n",
1265 ifID
->ifPort
, ifID
->ifName
));
1266 ifID
->ifRoutingState
= PORT_ACTIVATING
;
1267 ifID
->ifFlags
|= RTR_XNET_PORT
;
1271 * The next step is to check the information for each port before
1272 * declaring the ports up and forwarding
1274 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1275 ("router_start: waiting 20 sec before starting up\n"));
1277 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
1278 /* sleep for 20 seconds */
1280 /* the vaue of 10n terms of hz is 100ms */
1285 /* *** eventually this will be the ifID for the interface
1286 being brought up in router mode *** */
1287 msleep(&ifID_home
->startup_inprogress
, atalk_mutex
,
1288 PSOCK
| PCATCH
, "routerStart", &ts
))
1292 panic("routerStart: spurious interrupt");
1297 return(rtmp_router_start(keP
));
1298 /* was timeout(rtmp_router_start, 0, 20 * SYS_HZ); */
1301 void ZIPwakeup(elapp
, ZipError
)
1305 int error
= ZipError
;
1307 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
) {
1309 /* was ZIPContinue */
1310 /* was elapp_online() with jump to ZIP_sleep */
1312 /* instead of the goto ZIP_sleep ... */
1314 case 0 : /* success */
1315 elapp
->ifState
= LAP_ONLINE
;
1317 /* Send event with zone info. */
1318 atalk_post_msg(elapp
->aa_ifp
, KEV_ATALK_ZONEUPDATED
, 0, &(elapp
->ifZoneName
));
1322 /* instead of goto re_aarp; */
1323 /* We now call aarp_init() to assign an
1324 appletalk node addr */
1325 if ((elapp
->startup_error
= re_aarp(elapp
))) {
1326 elapp
->startup_inprogress
= FALSE
;
1327 wakeup(&elapp
->startup_inprogress
);
1328 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1329 ("elap_online: ack 2\n"));
1335 if (ZipError
!= ZIP_RE_AARP
) {
1336 elapp
->startup_error
= error
;
1337 elapp
->startup_inprogress
= FALSE
;
1338 wakeup(&elapp
->startup_inprogress
);
1339 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1340 ("elap_online: ifZipError=%d\n", error
));
1345 void AARPwakeup(probe_cb
)
1346 aarp_amt_t
*probe_cb
;
1351 elapp
= probe_cb
->elapp
;
1352 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
&& elapp
->aa_ifp
!= 0) {
1354 /* was AARPContinue */
1355 errno
= aarp_init2(elapp
);
1356 /* aarp_init2() returns either -1 or 0 */
1358 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
1359 ("elap_online aarp_init for %s\n",
1361 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->ZoneMcastAddr
);
1362 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
1363 elapp
->ifState
= LAP_OFFLINE
;
1365 elapp
->startup_error
= EADDRNOTAVAIL
;
1366 elapp
->startup_inprogress
= FALSE
;
1367 wakeup(&elapp
->startup_inprogress
);
1368 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online: ack 2\n"));
1370 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
1371 ("elap_online: aarp_init returns zero\n"));
1372 elap_online2(elapp
);
1377 void ddp_bit_reverse(addr
)
1378 unsigned char *addr
;
1380 static unsigned char reverse_data
[] = {
1381 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1382 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1383 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1384 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1385 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1386 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1387 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1388 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1389 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1390 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1391 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1392 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1393 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1394 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1395 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1396 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1397 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1398 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1399 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1400 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1401 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1402 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1403 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1404 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1405 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1406 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1407 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1408 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1409 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1410 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1411 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1412 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1417 for (k
=0; k
< 6; k
++)
1418 addr
[k
] = reverse_data
[addr
[k
]];
1421 static int elap_trackMcast(at_ifaddr_t
*, int, caddr_t
);
1423 static int elap_trackMcast(patp
, func
, addr
)
1430 switch(patp
->aa_ifp
->if_type
) {
1434 case IFT_IEEE8023ADLAG
: /* bonded ethernet */
1435 /* set addr to point to unique part of addr */
1438 /* first try to find match */
1439 /* *** save just one byte of the multicast address? *** */
1440 for (i
=0; i
< MAX_MCASTS
; i
++)
1441 if (c
== patp
->mcast
[i
]) {
1447 case MCAST_TRACK_DELETE
:
1449 patp
->mcast
[loc
] = 0;
1452 case MCAST_TRACK_ADD
:
1453 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add loc:%d\n", i
));
1455 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was there\n"));
1457 break; /* already there */
1459 for (i
=0; i
< MAX_MCASTS
; i
++)
1460 if (patp
->mcast
[i
] == 0) {
1464 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add1 loc:%d\n", i
));
1466 patp
->mcast
[loc
] = c
;
1467 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, adding(%x)\n",
1468 (*(int*)addr
)&0xffffff));
1471 /*errno = ENOMEM; */ /*LD 5/7/97 nobody is using that */
1475 case MCAST_TRACK_CHECK
:
1477 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:check, addr was there\n"));
1481 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was NOT there\n"));
1486 /*errno = EINVAL;*/ /*LD 5/7/97 nobody is using that */
1490 case IFT_ISO88025
: /* token ring */
1491 /* we would use the lowest byte of the addr argument as a value
1492 to shift left a 1 to form the mcast mask for TR. We'll do this
1502 static int getSnmpCfg(snmp
)
1509 snmp
->cfg_ifCnt
= 0;
1511 bzero(snmp
,sizeof(snmpCfg_t
));
1512 for (i
=0, elapp
=at_interfaces
,ifc
=snmp
->cfg_ifCfg
;
1513 i
<IF_TOTAL_MAX
; i
++, elapp
++, ifc
++) {
1514 if (elapp
->ifState
!= LAP_OFFLINE
) {
1516 strlcpy(ifc
->ifc_name
,elapp
->ifName
, sizeof(ifc
->ifc_name
));
1517 ifc
->ifc_aarpSize
= getAarpTableSize(i
);
1518 ifc
->ifc_addrSize
= getPhysAddrSize(i
);
1519 switch (elapp
->aa_ifp
->if_type
) {
1522 case IFT_IEEE8023ADLAG
: /* bonded ethernet */
1523 ifc
->ifc_type
= SNMP_TYPE_ETHER2
;
1525 case IFT_ISO88025
: /* token ring */
1526 ifc
->ifc_type
= SNMP_TYPE_TOKEN
;
1530 ifc
->ifc_type
= SNMP_TYPE_OTHER
;
1533 ifc
->ifc_start
= elapp
->ifThisCableStart
;
1534 ifc
->ifc_end
= elapp
->ifThisCableEnd
;
1535 ifc
->ifc_ddpAddr
= elapp
->ifThisNode
;
1536 ifc
->ifc_status
= elapp
->ifState
== LAP_ONLINE
? 1 : 2;
1537 ifc
->ifc_zoneName
.len
= 0;
1538 if (elapp
->ifZoneName
.len
!= 0) {
1539 ifc
->ifc_zoneName
= elapp
->ifZoneName
;
1541 else if (elapp
->ifDefZone
) {
1542 ifc
->ifc_zoneName
= ZT_table
[elapp
->ifDefZone
-1].Zone
;
1544 else /* temp, debug only */
1545 ifc
->ifc_zoneName
= ZT_table
[0].Zone
;
1547 if (elapp
->ifFlags
& RTR_SEED_PORT
) {
1548 ifc
->ifc_netCfg
= SNMP_CFG_CONFIGURED
;
1549 ifc
->ifc_zoneCfg
= SNMP_CFG_CONFIGURED
;
1552 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1553 ifc
->ifc_zoneCfg
= SNMP_CFG_GARNERED
;
1556 else { /* single-port mode */
1557 if (elapp
->ifRouterState
== ROUTER_AROUND
) {
1558 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1561 ifc
->ifc_netCfg
= SNMP_CFG_GUESSED
;
1562 ifc
->ifc_zoneCfg
= SNMP_CFG_UNCONFIG
;
1567 snmp
->cfg_flags
= at_state
.flags
;
1573 int at_reg_mcast(ifID
, data
)
1577 struct ifnet
*nddp
= ifID
->aa_ifp
;
1578 struct sockaddr_dl sdl
;
1582 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1586 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1589 /* this is for ether_output */
1590 bzero(&sdl
, sizeof(sdl
));
1591 sdl
.sdl_family
= AF_LINK
;
1592 sdl
.sdl_alen
= sizeof(struct etalk_addr
);
1593 sdl
.sdl_len
= offsetof(struct sockaddr_dl
, sdl_data
)
1594 + sizeof(struct etalk_addr
);
1595 bcopy(data
, sdl
.sdl_data
, sizeof(struct etalk_addr
));
1596 /* these next two lines should not really be needed XXX */
1597 sdl
.sdl_index
= nddp
->if_index
;
1598 sdl
.sdl_type
= IFT_ETHER
;
1600 dPrintf(D_M_PAT
, D_L_STARTUP
,
1601 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1602 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1605 if (if_addmulti_anon(nddp
, (struct sockaddr
*)&sdl
, NULL
))
1612 int at_unreg_mcast(ifID
, data
)
1616 struct ifnet
*nddp
= ifID
->aa_ifp
;
1617 struct sockaddr_dl sdl
;
1621 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1625 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1627 /* this is for ether_output */
1628 bzero(&sdl
, sizeof(sdl
));
1629 sdl
.sdl_family
= AF_LINK
;
1630 sdl
.sdl_alen
= sizeof(struct etalk_addr
);
1631 sdl
.sdl_len
= offsetof(struct sockaddr_dl
, sdl_data
)
1632 + sizeof(struct etalk_addr
);
1633 bcopy(data
, sdl
.sdl_data
, sizeof(struct etalk_addr
));
1634 /* these next two lines should not really be needed XXX */
1635 sdl
.sdl_index
= nddp
->if_index
;
1636 sdl
.sdl_type
= IFT_ETHER
;
1638 dPrintf(D_M_PAT
, D_L_STARTUP
,
1639 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1640 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1642 bzero(data
, sizeof(struct etalk_addr
));
1644 if (if_delmulti_anon(nddp
, (struct sockaddr
*)&sdl
))
1650 /* *** at_reg_mcast() and at_unreg_mcast() should be replaced as soon as the
1651 new code to allow an AF_LINK address family multicast to be (un)registered
1652 using the SIOCADDMULTI / SIOCDELMULTI ioctls has been completed.
1654 The issue is that the "struct sockaddr_dl" needed for the AF_LINK does not
1655 fit in the "struct ifreq" that is used for these ioctls, and we do not want
1656 Blue/Classic, which currently uses AF_UNSPEC, to use a different address
1657 family multicast address than Mac OS X uses.
1660 int at_reg_mcast(ifID
, data
)
1664 struct ifnet
*nddp
= ifID
->aa_ifp
;
1665 struct sockaddr_dl sdl
;
1669 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1672 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1675 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1676 sdl
.sdl_family
= AF_LINK
;
1678 sdl
.sdl_type
= nddp
->if_type
;
1679 sdl
.sdl_alen
= nddp
->if_addrlen
;
1681 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1682 nddp
->if_name
, nddp
->if_unit
);
1683 bcopy(data
, LLADDR(&sdl
), sdl
.sdl_alen
);
1685 dPrintf(D_M_PAT
, D_L_STARTUP
,
1686 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1687 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1690 if (if_addmulti_anon(nddp
, (struct sockaddr
*)&sdl
, NULL
))
1697 int at_unreg_mcast(ifID
, data
)
1701 struct ifnet
*nddp
= ifID
->aa_ifp
;
1702 struct sockaddr_dl sdl
;
1706 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1710 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1712 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1713 sdl
.sdl_family
= AF_LINK
;
1715 sdl
.sdl_type
= nddp
->if_type
;
1716 sdl
.sdl_alen
= nddp
->if_addrlen
;
1718 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1719 nddp
->if_name
, nddp
->if_unit
);
1721 dPrintf(D_M_PAT
, D_L_STARTUP
,
1722 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1723 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1725 bzero(data
, ETHERNET_ADDR_LEN
);
1727 if (if_delmulti_anon(nddp
, (struct sockaddr
*)&sdl
))