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 <net/if_dl.h>
57 #include <sys/socketvar.h>
58 #include <sys/malloc.h>
59 #include <sys/domain.h>
60 #include <sys/sockio.h>
61 #include <vm/vm_kern.h> /* for kernel_map */
65 #include <net/if_types.h>
67 #include <netat/sysglue.h>
68 #include <netat/appletalk.h>
69 #include <netat/at_var.h>
70 #include <netat/ddp.h>
71 #include <netat/lap.h>
72 #include <netat/routing_tables.h> /* rtmp+zip table structs */
73 #include <netat/zip.h>
74 #include <netat/nbp.h>
75 #include <netat/at_snmp.h>
76 #include <netat/at_pcb.h>
77 #include <netat/at_aarp.h>
78 #include <netat/asp.h>
79 #include <netat/atp.h>
80 #include <netat/debug.h>
81 #include <netat/adsp.h>
82 #include <netat/adsp_internal.h>
84 #include <sys/kern_event.h>
88 at_ifaddr_t at_interfaces
[IF_TOTAL_MAX
];
89 /* index for at_interfaces is not important */
90 at_ifaddr_t
*ifID_table
[IF_TOTAL_MAX
];
91 /* the table of ifID structures, one per interface
93 * NOTE: for MH, entry 0 in this table is
94 * now defined to be the default I/F
96 at_ifaddr_t
*ifID_home
;
97 /* always ifID_table[IFID_HOME] for now, but will be used for
98 dynamic "home port" assignment, later */
100 at_state_t at_state
; /* global state of AT network */
101 snmpFlags_t snmpFlags
;
106 #define MAX_BUFSIZE 8192
107 #define MAX_RTMP (MAX_BUFSIZE/sizeof(RT_entry)-1)
109 ((MAX_BUFSIZE - SNMP_NBP_HEADER_SIZE)/sizeof(snmpNbpEntry_t)-1)
110 #define MAX_NBP_BYTES (MAX_NBP * sizeof(snmpNbpEntry_t))
111 #define MAX_ZIP (MAX_BUFSIZE/sizeof(ZT_entry)-1)
112 #define MAX_RTMP_BYTES (MAX_RTMP * sizeof(RT_entry))
113 #define MAX_ZIP_BYTES (MAX_ZIP * sizeof(ZT_entry))
116 extern TAILQ_HEAD(name_registry
, _nve_
) name_registry
;
117 extern snmpStats_t snmpStats
;
118 extern atlock_t ddpinp_lock
;
119 extern atlock_t arpinp_lock
;
120 extern short appletalk_inited
;
121 extern int adspInited
;
122 extern struct atpcb ddp_head
;
123 extern gref_t
*atp_inputQ
[];
124 extern struct atp_state
*atp_used_list
;
125 extern asp_scb_t
*asp_scbQ
[];
126 extern asp_scb_t
*scb_used_list
;
127 extern CCB
*adsp_inputQ
[];
128 extern CCB
*ccb_used_list
;
129 extern at_ddp_stats_t at_ddp_stats
;
130 extern lck_mtx_t
* atalk_mutex
;
133 extern snmpAarpEnt_t
* getAarp(int *);
134 extern void nbp_shutdown(), routershutdown(), ddp_brt_shutdown();
135 extern void ddp_brt_init(), rtmp_init(), rtmp_input();
136 extern rtmp_router_start(at_kern_err_t
*);
137 static void getIfNames(at_ifnames_t
*);
138 static void add_route();
139 static int set_zones();
141 static int elap_online1(), re_aarp();
142 int at_reg_mcast(), at_unreg_mcast();
143 void AARPwakeup(), ZIPwakeup();
144 static void elap_hangup();
147 at_ifaddr_t
*find_ifID(if_name
)
153 for (pat_id
=0; pat_id
< xpatcnt
; pat_id
++) {
154 if (!strcmp(at_interfaces
[pat_id
].ifName
, if_name
))
155 return(&at_interfaces
[pat_id
]);
158 return((at_ifaddr_t
*)NULL
);
161 static int validate_msg_size(m
, gref
, elapp
)
166 /* checks ioctl message type for minimum expected message size &
167 sends error back if size invalid
170 register ioc_t
*iocbp
;
171 register at_if_cfg_t
*cfgp
;
175 iocbp
= (ioc_t
*) gbuf_rptr(m
);
177 dPrintf(D_M_ELAP
, D_L_INFO
, ("validate_msg_size: ioc_cmd = %d\n",
179 switch (iocbp
->ioc_cmd
) {
180 case LAP_IOC_ADD_ROUTE
:
181 size
= sizeof(RT_entry
);
183 case LAP_IOC_GET_ROUTE
:
184 size
= sizeof(RT_entry
);
186 case LAP_IOC_GET_ZONE
:
187 size
= sizeof(ZT_entryno
);
189 case LAP_IOC_SNMP_GET_CFG
:
190 case LAP_IOC_SNMP_GET_AARP
:
191 case LAP_IOC_SNMP_GET_ZIP
:
192 case LAP_IOC_SNMP_GET_RTMP
:
193 case LAP_IOC_SNMP_GET_NBP
:
197 case ELAP_IOC_GET_STATS
:
198 case LAP_IOC_SNMP_GET_DDP
:
203 dPrintf(D_M_ELAP
, D_L_ERROR
, ("validate_msg_size: unknown ioctl\n"));
207 if (size
== 0) { /* a non-data ioctl */
211 if (gbuf_cont(m
) != NULL
)
212 i
= gbuf_len(gbuf_cont(m
));
213 if (iocbp
->ioc_count
< size
|| (gbuf_cont(m
) == NULL
) || i
< size
) {
214 dPrintf(D_M_ELAP
, D_L_ERROR
,
215 ("ioctl msg error:s:%d c:%d bcont:%c delta:%d\n",
216 size
, iocbp
->ioc_count
,
217 gbuf_cont(m
)? 'Y' : 'N', i
));
223 ioc_ack(EMSGSIZE
, m
, gref
);
225 } /* validate_msg_size */
227 int lap_online(elapp
, cfgp
)
233 if (elapp
->ifState
!= LAP_OFFLINE
) {
238 if (cfgp
->flags
& ELAP_CFG_HOME
) {
240 /* only 1 home allowed! */
243 dPrintf(D_M_ELAP
, D_L_STARTUP
,
244 ("elap_wput home I/F:%s\n", cfgp
->ifr_name
));
245 elapp
->flags
|= ELAP_CFG_HOME
;
248 if (MULTIPORT_MODE
) {
249 elapp
->flags
|= ELAP_CFG_ZONELESS
;
250 if (ROUTING_MODE
&& cfgp
->netStart
)
251 elapp
->flags
|= ELAP_CFG_SEED
;
254 if (!DEFAULT_ZONE(&cfgp
->zonename
) &&
255 (elapp
->flags
& ELAP_CFG_HOME
) || MULTIHOME_MODE
) {
256 elapp
->startup_zone
= cfgp
->zonename
;
259 if (elapp
->flags
& ELAP_CFG_SEED
) {
260 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
261 ("elap_wput: found to be seed\n"));
262 elapp
->ifThisCableStart
= cfgp
->netStart
;
263 elapp
->ifThisCableEnd
= cfgp
->netEnd
;
266 dPrintf(D_M_ELAP
,D_L_ERROR
,
267 ("elap_wput: we believe we're not seed\n"));
268 /* from ELAP_IOC_SET_CFG */
269 if (ATALK_VALUE(cfgp
->node
)) {
273 initial_node
= cfgp
->node
.s_node
;
274 initial_net
= cfgp
->node
.s_net
;
275 if ((initial_node
<0xfe) && (initial_node
>0) &&
276 !((initial_net
== 0) ||
277 ((initial_net
>= DDP_STARTUP_LOW
)&&
278 (initial_net
<= DDP_STARTUP_HIGH
)))) {
280 elapp
->initial_addr
= cfgp
->node
;
285 elapp
->startup_error
= 0;
286 elapp
->startup_inprogress
= FALSE
;
287 if ((error
= elap_online1(elapp
)))
290 if (!(MULTIPORT_MODE
) &&
291 elapp
->ifZoneName
.len
== 1 &&
292 elapp
->ifZoneName
.str
[0] == '*' &&
293 !DEFAULT_ZONE(&cfgp
->zonename
)) {
294 nbp_add_multicast(&cfgp
->zonename
, elapp
);
299 /***********************************************************************
302 **********************************************************************/
303 int elap_wput(gref
, m
)
308 register ioc_t
*iocbp
;
309 register at_if_cfg_t
*cfgp
;
310 at_elap_stats_t
*statsp
;
317 switch (gbuf_type(m
)) {
320 dPrintf(D_M_ELAP
,D_L_ERROR
,
321 ("Output data to control channel is ignored\n"));
325 iocbp
= (ioc_t
*) gbuf_rptr(m
);
327 if (validate_msg_size(m
, gref
, &elapp
))
331 cfgp
= (at_if_cfg_t
*) gbuf_rptr(gbuf_cont(m
));
333 if (LAP_IOC_MYIOCTL(iocbp
->ioc_cmd
) ||
334 ELAP_IOC_MYIOCTL(iocbp
->ioc_cmd
)) {
336 switch (iocbp
->ioc_cmd
) {
337 case ELAP_IOC_GET_STATS
:
338 #ifdef APPLETALK_DEBUG
339 kprintf("LAP_IOC_GET_STATS\n");
341 if ( (gbuf_cont(m
) == NULL
)
342 || (elapp
= find_ifID(gbuf_rptr(gbuf_cont(m
)))) == NULL
) {
343 ioc_ack(EINVAL
, m
, gref
);
346 gbuf_freem(gbuf_cont(m
));
347 if ((gbuf_cont(m
) =gbuf_alloc(sizeof(at_elap_stats_t
),
349 ioc_ack(ENOBUFS
, m
, gref
);
352 statsp
= ((at_elap_stats_t
*)gbuf_rptr(gbuf_cont(m
)));
353 *statsp
= elapp
->stats
;
354 gbuf_wset(gbuf_cont(m
),sizeof(at_elap_stats_t
));
355 iocbp
->ioc_count
= sizeof(at_elap_stats_t
);
359 case LAP_IOC_ADD_ROUTE
:
360 #ifdef APPLETALK_DEBUG
361 kprintf("LAP_IOC_ADD_ROUTE\n");
363 add_route((RT_entry
*)gbuf_rptr(gbuf_cont(m
)));
367 case LAP_IOC_GET_ZONE
:
368 #ifdef APPLETALK_DEBUG
369 kprintf("LAP_IOC_GET_ZONE\n");
371 /* return next ZT_entryno from ZT_table
372 a pointer to the struct ZT_entryno is passed down from
373 user space and the first byte is cast to a int, if
374 this int is non-zero, then the first ZT_entry is
375 returned and subsequent calls with a zero value
376 will return the next entry in the table. The next
377 read after the last valid entry will return EINVAL
382 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
383 gbuf_freem(gbuf_cont(m
));
386 pZTe
= zt_getNextZone(i
);
388 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(ZT_entryno
), PRI_MED
)) == NULL
) {
389 ioc_ack(ENOBUFS
, m
, gref
);
392 *(ZT_entryno
*)gbuf_rptr(gbuf_cont(m
)) = *pZTe
;
393 gbuf_wset(gbuf_cont(m
),sizeof(ZT_entryno
));
394 iocbp
->ioc_count
= sizeof(ZT_entryno
);
398 ioc_ack(EINVAL
, m
, gref
);
402 case LAP_IOC_GET_ROUTE
:
403 #ifdef APPLETALK_DEBUG
404 kprintf("LAP_IOC_GET_ROUTE\n");
406 /* return next RT_entry from RT_table
407 * a pointer to the struct RT_entry is
408 * passed down from user space and the first
409 * byte is cast to a int, if this int is
410 * non-zero, then the first RT_entry is
411 * returned and subsequent calls with a
412 * zero value will return the next entry in
413 * the table. The next read after the last
414 * valid entry will return EINVAL
419 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
420 gbuf_freem(gbuf_cont(m
));
423 pRT
= rt_getNextRoute(i
);
425 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(RT_entry
), PRI_MED
)) == NULL
) {
426 ioc_ack(ENOBUFS
, m
, gref
);
429 *(RT_entry
*)gbuf_rptr(gbuf_cont(m
)) = *pRT
;
430 gbuf_wset(gbuf_cont(m
),sizeof(RT_entry
));
431 iocbp
->ioc_count
= sizeof(RT_entry
);
435 ioc_ack(EINVAL
, m
, gref
);
439 case LAP_IOC_SNMP_GET_DDP
:
440 #ifdef APPLETALK_DEBUG
441 kprintf("LAP_IOC_SNMP_GET_DDP\n");
443 if (!(at_state
.flags
& AT_ST_STARTED
)) {
444 ioc_ack(ENOTREADY
, m
, gref
);
447 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(snmpStats_t
),
449 ioc_ack(ENOBUFS
, m
, gref
);
453 *(snmpStats_t
*)gbuf_rptr(gbuf_cont(m
)) = snmpStats
;
454 gbuf_wset(gbuf_cont(m
),sizeof(snmpStats
));
455 iocbp
->ioc_count
= sizeof(snmpStats
);
458 case LAP_IOC_SNMP_GET_CFG
:
459 #ifdef APPLETALK_DEBUG
460 kprintf("LAP_IOC_SNMP_GET_CFG\n");
466 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
467 gbuf_freem(gbuf_cont(m
));
469 if (!(at_state
.flags
& AT_ST_STARTED
)) {
471 iocbp
->ioc_count
= 0;
472 ioc_ack(ENOTREADY
, m
, gref
);
473 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
474 ("elap_wput: cfg req, stack down\n"));
477 if (i
== UPDATE_IF_CHANGED
&&
478 !(at_state
.flags
& AT_ST_IF_CHANGED
)) {
479 iocbp
->ioc_count
= 0;
481 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
482 ("elap_wput: cfg req, unchanged\n"));
485 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
486 ("elap_wput: cfg req, changed\n"));
488 if (getSnmpCfg(&snmp
)) {
489 dPrintf(D_M_ELAP
,D_L_ERROR
,
490 ("elap_wput:SNMP_GET_CFG error\n"));
491 ioc_ack(EOPNOTSUPP
, m
, gref
);
494 /* send up only used part of table */
495 size
= sizeof(snmp
) -
496 sizeof(snmpIfCfg_t
) * (MAX_IFS
- snmp
.cfg_ifCnt
);
498 if ((gbuf_cont(m
) = gbuf_alloc(size
, PRI_MED
)) == NULL
) {
499 ioc_ack(ENOBUFS
, m
, gref
);
502 bcopy(&snmp
,gbuf_rptr(gbuf_cont(m
)),size
);
503 gbuf_wset(gbuf_cont(m
),size
);
504 iocbp
->ioc_count
= size
;
505 at_state
.flags
&= ~AT_ST_IF_CHANGED
;
510 case LAP_IOC_SNMP_GET_AARP
:
512 snmpAarpEnt_t
*snmpp
;
514 #ifdef APPLETALK_DEBUG
515 kprintf("LAP_IOC_SNMP_GET_AARP\n");
517 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
518 gbuf_freem(gbuf_cont(m
));
520 dPrintf(D_M_ELAP
,D_L_INFO
,
521 ("elap_wput:calling getarp,i=%d\n", i
));
523 bytes
= i
* sizeof(snmpAarpEnt_t
);
524 dPrintf(D_M_ELAP
,D_L_INFO
,
525 ("elap_wput:getarp returned, i=%d,bytes=%d\n",
528 if ((gbuf_cont(m
) = gbuf_alloc(bytes
, PRI_MED
)) == NULL
) {
529 ioc_ack(ENOBUFS
, m
, gref
);
532 bcopy(snmpp
, gbuf_rptr(gbuf_cont(m
)), bytes
);
533 gbuf_wset(gbuf_cont(m
),bytes
);
534 iocbp
->ioc_count
= bytes
;
538 ioc_ack(EOPNOTSUPP
, m
, gref
);
542 case LAP_IOC_SNMP_GET_ZIP
:
543 #ifdef APPLETALK_DEBUG
544 kprintf("LAP_IOC_SNMP_GET_ZIP\n");
546 { /* matching brace NOT in this case */
548 register int size
, total
, tabsize
;
549 gbuf_t
*mn
; /* new gbuf */
550 gbuf_t
*mo
; /* old gbuf */
551 gbuf_t
*mt
; /* temp */
554 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
555 gbuf_freem(gbuf_cont(m
));
557 if (!(at_state
.flags
& AT_ST_STARTED
)) {
558 ioc_ack(ENOTREADY
, m
, gref
);
561 if (i
== UPDATE_IF_CHANGED
&&
562 !(at_state
.flags
& AT_ST_ZT_CHANGED
)) {
563 iocbp
->ioc_count
= 0;
568 tabsize
= getZipTableSize();
570 /* retrieve table into multiple gbufs */
571 for (i
=0; i
<tabsize
; i
+=j
) {
573 MAX_ZIP
? MAX_ZIP
: tabsize
- i
;
574 size
= j
< MAX_ZIP
? sizeof(ZT_entry
)*j
: MAX_ZIP_BYTES
;
575 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
577 gbuf_freem(gbuf_cont(m
));
578 ioc_ack(ENOBUFS
, m
, gref
);
581 if (!mo
) { /* if first new one */
590 getZipTable((ZT_entry
*)gbuf_rptr(mn
),i
,j
);
593 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
596 iocbp
->ioc_count
= 0;
597 ioc_ack(ENOBUFS
, m
, gref
);
601 dPrintf(D_M_ELAP
,D_L_WARNING
,
602 ("elap_wput:snmp: empty zip table\n"));
605 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
606 gbuf_wset(gbuf_cont(m
),sizeof(int));
607 iocbp
->ioc_count
= sizeof(int);
610 atalk_putnext(gref
,mt
); /* send up table */
611 at_state
.flags
&= ~AT_ST_ZT_CHANGED
;
614 case LAP_IOC_SNMP_GET_RTMP
:
615 #ifdef APPLETALK_DEBUG
616 kprintf("LAP_IOC_SNMP_GET_RTMP\n");
618 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
619 gbuf_freem(gbuf_cont(m
));
621 if (!(at_state
.flags
& AT_ST_STARTED
)) {
622 ioc_ack(ENOTREADY
, m
, gref
);
625 if (i
== UPDATE_IF_CHANGED
&&
626 !(at_state
.flags
& AT_ST_RT_CHANGED
)) {
627 iocbp
->ioc_count
= 0;
633 tabsize
= getRtmpTableSize();
635 /* retrieve table into multiple gbufs */
636 for (i
=0; i
<tabsize
; i
+=j
) {
638 MAX_RTMP
? MAX_RTMP
: tabsize
- i
;
639 size
= j
< MAX_RTMP
? sizeof(RT_entry
)*j
: MAX_RTMP_BYTES
;
640 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
642 gbuf_freem(gbuf_cont(m
));
643 ioc_ack(ENOBUFS
, m
, gref
);
646 if (!mo
) { /* if first new one */
655 getRtmpTable((RT_entry
*)gbuf_rptr(mn
),i
,j
);
658 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
661 iocbp
->ioc_count
= 0;
662 ioc_ack(ENOBUFS
, m
, gref
);
667 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
668 gbuf_wset(gbuf_cont(m
),sizeof(int));
669 iocbp
->ioc_count
= sizeof(int);
672 atalk_putnext(gref
,mt
); /* send up table */
673 at_state
.flags
&= ~AT_ST_RT_CHANGED
;
676 case LAP_IOC_SNMP_GET_NBP
:
677 #ifdef APPLETALK_DEBUG
678 kprintf("LAP_IOC_SNMP_GET_NBP\n");
680 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
681 gbuf_freem(gbuf_cont(m
));
683 if (!(at_state
.flags
& AT_ST_STARTED
)) {
684 ioc_ack(ENOTREADY
, m
, gref
);
687 if (i
== UPDATE_IF_CHANGED
&&
688 !(at_state
.flags
& AT_ST_NBP_CHANGED
)) {
689 iocbp
->ioc_count
= 0;
691 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
692 ("elap_wput: nbp req denied, no change\n"));
697 tabsize
= getNbpTableSize();
699 /* retrieve table into multiple gbufs */
700 for (i
=0; i
<tabsize
; i
+=j
) {
702 MAX_NBP
? MAX_NBP
: tabsize
- i
;
703 size
= j
< MAX_NBP
? sizeof(snmpNbpEntry_t
)*j
: MAX_NBP_BYTES
;
705 size
+= SNMP_NBP_HEADER_SIZE
;
706 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
708 gbuf_freem(gbuf_cont(m
));
709 ioc_ack(ENOBUFS
, m
, gref
);
712 if (!mo
) { /* if first new one */
715 nbp
= (snmpNbpTable_t
*)gbuf_rptr(mn
);
716 nbp
->nbpt_entries
= tabsize
;
717 nbp
->nbpt_zone
= ifID_home
->ifZoneName
;
718 getNbpTable(nbp
->nbpt_table
,i
,j
);
723 getNbpTable((snmpNbpEntry_t
*)gbuf_rptr(mn
),i
,j
);
728 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
731 iocbp
->ioc_count
= 0;
732 ioc_ack(ENOBUFS
, m
, gref
);
737 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
738 gbuf_wset(gbuf_cont(m
),sizeof(int));
739 iocbp
->ioc_count
= sizeof(int);
742 atalk_putnext(gref
,mt
); /* send up table */
743 at_state
.flags
&= ~AT_ST_NBP_CHANGED
;
748 #ifdef APPLETALK_DEBUG
749 kprintf("unknown ioctl %d\n", iocbp
->ioc_cmd
);
751 ioc_ack(ENOTTY
, m
, gref
);
752 dPrintf(D_M_ELAP
, D_L_WARNING
,
753 ("elap_wput: unknown ioctl (%d)\n", iocbp
->ioc_cmd
));
756 elapp
->stats
.unknown_mblks
++;
771 /* Called directly by ddp/zip.
773 elap_dataput(m
, elapp
, addr_flag
, addr
)
775 register at_ifaddr_t
*elapp
;
781 extern int zip_type_packet();
782 struct etalk_addr dest_addr
;
783 struct atalk_addr dest_at_addr
;
784 extern gbuf_t
*growmsg();
786 /* flag to aarp to loopback (default) */
788 /* the incoming frame is of the form {flag, address, ddp...}
789 * where "flag" indicates whether the address is an 802.3
790 * (link) address, or an appletalk address. If it's an
791 * 802.3 address, the packet can just go out to the network
792 * through PAT, if it's an appletalk address, AT->802.3 address
793 * resolution needs to be done.
794 * If 802.3 address is known, strip off the flag and 802.3
795 * address, and prepend 802.2 and 802.3 headers.
799 addr_flag
= *(u_char
*)gbuf_rptr(m
);
804 case AT_ADDR_NO_LOOP
:
809 dest_at_addr
= *(struct atalk_addr
*)gbuf_rptr(m
);
810 gbuf_rinc(m
,sizeof(struct atalk_addr
));
812 dest_at_addr
= *(struct atalk_addr
*)addr
;
816 dest_addr
= *(struct etalk_addr
*)gbuf_rptr(m
);
817 gbuf_rinc(m
,sizeof(struct etalk_addr
));
819 dest_addr
= *(struct etalk_addr
*)addr
;
822 gbuf_freel(m
); /* unknown address type, chuck it */
828 /* At this point, rptr points to ddp header for sure */
829 if (elapp
->ifState
== LAP_OFFLINE
) {
834 if (elapp
->ifState
== LAP_ONLINE_FOR_ZIP
) {
835 /* see if this is a ZIP packet that we need
836 * to let through even though network is
839 if (zip_type_packet(m
) == 0) {
845 elapp
->stats
.xmit_packets
++;
846 size
= gbuf_msgsize(m
);
847 elapp
->stats
.xmit_bytes
+= size
;
848 snmpStats
.dd_outLong
++;
851 case AT_ADDR_NO_LOOP
:
854 * we don't want elap to be looking into ddp header, so
855 * it doesn't know net#, consequently can't do
856 * AMT_LOOKUP. That task left to aarp now.
858 error
= aarp_send_data(m
,elapp
,&dest_at_addr
, loop
);
861 error
= pat_output(elapp
, m
, &dest_addr
, 0);
867 /************************************************************************
870 ************************************************************************/
872 static int elap_online1(elapp
)
877 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online:%s elapp:0x%x\n",
878 (elapp
->ifName
) ? &elapp
->ifName
[0] : "NULL interface", (u_int
) elapp
));
879 if (elapp
->ifState
!= LAP_OFFLINE
|| elapp
->startup_inprogress
== TRUE
)
882 at_state
.flags
|= AT_ST_IF_CHANGED
;
884 if (elapp
->flags
& ELAP_CFG_HOME
) /* tell ddp_add_if if this is home */
885 elapp
->ifFlags
|= AT_IFF_DEFAULT
;
887 /* Get DDP started */
888 if ((errno
= ddp_add_if(elapp
)))
891 // check if we still have an interface - can be lost when
892 // ddp_add_if calls malloc
893 // need to make check here after ddp_add_if completes because
894 // lap_online will call ddp_rem_if if we fail here
895 if (elapp
->aa_ifp
== 0)
898 /* set up multicast address for cable-wide broadcasts */
899 (void)at_reg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
901 // need to check again if interface is present
902 // can be lost in at_reg_mcast
903 if (elapp
->aa_ifp
== 0)
906 elapp
->startup_inprogress
= TRUE
;
907 if (! (elapp
->startup_error
= re_aarp(elapp
))) {
908 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
909 (void)msleep(&elapp
->startup_inprogress
, atalk_mutex
, PSOCK
| PCATCH
,
913 /* then later, after some timeouts AARPwakeup() is called */
915 return(elapp
->startup_error
);
918 static int re_aarp(elapp
)
923 /* We now call aarp_init() to assign an appletalk node addr */
924 errno
= aarp_init1(elapp
);
925 /* aarp_init1() returns either -1 or ENOTREADY */
926 if (errno
== ENOTREADY
)
929 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
930 ("elap_online aarp_init for %s\n", elapp
->ifName
));
931 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
933 elapp
->ifState
= LAP_OFFLINE
;
934 return(EADDRNOTAVAIL
);
938 /* called from AARPwakeup */
939 static void elap_online2(elapp
)
942 if (MULTIPORT_MODE
) {
943 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
944 ("elap_online: re_aarp, we know it's a router...\n"));
946 if (elapp
->flags
& ELAP_CFG_SEED
) {
947 /* add route table entry (zones to be added later) */
948 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
949 ("elap_online: rt_insert Cable %d-%d port =%d as SEED\n",
950 elapp
->ifThisCableStart
, elapp
->ifThisCableEnd
, elapp
->ifPort
));
951 rt_insert(elapp
->ifThisCableEnd
,
952 elapp
->ifThisCableStart
,
955 RTE_STATE_PERMANENT
| RTE_STATE_ZKNOWN
| RTE_STATE_GOOD
957 /* LD 081694: set the RTR_SEED_PORT flag for seed ports */
958 elapp
->ifFlags
|= RTR_SEED_PORT
;
961 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
962 ("elap_online: it's a router, but non seed\n"));
965 if (elapp
->flags
& ELAP_CFG_ZONELESS
) {
966 /* ELAP_CFG_ZONELESS tells us that it is a router or in
967 multihome mode, so we don't want to do the GetNetInfo
968 exchange with the router. */
970 elapp
->ifState
= LAP_ONLINE_ZONELESS
;
971 elapp
->startup_inprogress
= FALSE
;
972 wakeup(&elapp
->startup_inprogress
);
973 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online: ack 3\n"));
977 /* if we don't already have a zone and a multicast address */
978 if (*(int *)&elapp
->ZoneMcastAddr
== 0 || elapp
->ifZoneName
.len
== 0) {
979 /* hzonehash is a global containing the nbp hash for the startup_zone */
982 /* Get ZIP rolling to get zone multicast address, etc. */
983 elapp
->ifState
= LAP_ONLINE_FOR_ZIP
;
984 (void)zip_control(elapp
, ZIP_ONLINE
);
985 /* zip_control (w. control == ZIP_ONLINE) always returns ENOTREADY */
987 /* later, after some timeouts ZIPwakeup() is called. */
989 /* otherwise, we have the zone and the multicast already,
990 so don't bother with another ZIP GetNetInfo request */
995 /* called from rtmp_router_start */
996 int elap_online3(elapp
)
999 elapp
->startup_inprogress
= TRUE
;
1001 /* just reset the net range */
1002 elapp
->initial_addr
.s_net
= 0;
1003 elapp
->initial_addr
.s_node
= 0;
1004 dPrintf(D_M_ELAP_LOW
, D_L_STARTUP_INFO
,
1005 ("elap_online: goto re_aarp port=%d\n", elapp
->ifPort
));
1007 if ((elapp
->startup_error
= re_aarp(elapp
)))
1008 return(elapp
->startup_error
);
1010 /* then later, after some timeouts AARPwakeup() is called */
1012 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
1013 (void)msleep(&elapp
->startup_inprogress
, atalk_mutex
, PSOCK
| PCATCH
,
1015 return(elapp
->startup_error
);
1016 } /* elap_online3 */
1018 /****************************************************************************
1021 ****************************************************************************/
1023 void elap_offline(elapp
)
1024 register at_ifaddr_t
*elapp
;
1027 void zip_sched_getnetinfo(); /* forward reference */
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
;
1043 ATDISABLE(s
, ddpinp_lock
);
1045 RT_DELETE(elapp
->ifThisCableEnd
,
1046 elapp
->ifThisCableStart
);
1047 ATENABLE(s
, ddpinp_lock
);
1049 /* make sure no zip timeouts are left running */
1050 elapp
->ifGNIScheduled
= 0;
1051 untimeout(zip_sched_getnetinfo
, elapp
);
1054 } /* elap_offline */
1057 static void add_route(rt
)
1060 /* support ioctl to manually add routes to table.
1061 this is really only for testing
1064 rt_insert( rt
->NetStop
, rt
->NetStart
, rt
->NextIRNet
,
1065 rt
->NextIRNode
, rt
->NetDist
, rt
->NetPort
,
1067 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("adding route: %ud:%ud dist:%ud\n",
1068 rt
->NetStart
, rt
->NetStop
,rt
->NetDist
));
1074 * Initialization that takes place each time AppleTalk is restarted.
1079 TAILQ_INIT(&at_ifQueueHd
);
1080 TAILQ_INIT(&name_registry
);
1081 bzero(at_interfaces
, sizeof(at_interfaces
));
1082 bzero(ifID_table
, sizeof(ifID_table
));
1083 bzero(&at_ddp_stats
, sizeof(at_ddp_stats_t
));
1084 rtmp_init(); /* initialize trackedrouters */
1086 add_ddp_handler(RTMP_SOCKET
, rtmp_input
);
1087 ifID_home
= (at_ifaddr_t
*)NULL
;
1091 int ddp_shutdown(count_only
)
1095 asp_scb_t
*scb
, *scb_next
;
1096 struct atp_state
*atp
, *atp_next
;
1099 vm_offset_t temp_rcb_data
, temp_state_data
;
1100 int i
, s
, active_skts
= 0; /* count of active pids for non-socketized
1101 AppleTalk protocols */
1103 /* Network is shutting down... send error messages up on each open
1105 *** For now, for ASP, ATP and ADSP, attempt to notify open
1106 sockets, but return EBUSY and don't complete shutdown. ***
1109 s
= splimp(); /* *** previously contained mismatched locking
1110 that was ifdef'ed to splimp() *** */
1112 nbp_shutdown(); /* clear all known NVE */
1115 for (scb
= scb_used_list
; scb
; ) {
1116 scb_next
= scb
->next_scb
;
1119 dPrintf(D_M_ASP
, D_L_TRACE
, ("asp pid=%d\n", scb
->pid
));
1120 atalk_notify(scb
->gref
, ESHUTDOWN
);
1124 for (i
= 0; i
< 256 ; i
++) {
1125 if ((scb
= asp_scbQ
[i
]))
1127 scb_next
= scb
->next_scb
;
1130 dPrintf(D_M_ASP
, D_L_TRACE
,
1131 ("asp pid=%d\n", scb
->pid
));
1132 atalk_notify(scb
->gref
, ESHUTDOWN
);
1139 for (atp
= atp_used_list
; atp
; ) {
1140 atp_next
= atp
->atp_trans_waiting
;
1143 dPrintf(D_M_ATP
, D_L_TRACE
, ("atp pid=%d\n", atp
->atp_pid
));
1144 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1148 for (i
= 0; i
< 256; i
++) {
1149 if ((gref
= atp_inputQ
[i
]) && (gref
!= (gref_t
*)1)) {
1150 atp
= (struct atp_state
*)gref
->info
;
1154 dPrintf(D_M_ATP
, D_L_TRACE
,
1155 ("atp pid=%d\n", atp
->atp_pid
));
1156 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1163 for (sp
= ccb_used_list
; sp
; ) {
1164 sp_next
= sp
->otccbLink
;
1167 dPrintf(D_M_ADSP
, D_L_TRACE
, ("adsp pid=%d\n", sp
->pid
));
1168 atalk_notify(sp
->gref
, ESHUTDOWN
);
1172 for (i
= 0; i
< 256 ; i
++) {
1173 if ((sp
= adsp_inputQ
[i
]))
1175 sp_next
= sp
->otccbLink
;
1178 dPrintf(D_M_ADSP
, D_L_TRACE
,
1179 ("adsp pid=%d\n", sp
->pid
));
1180 atalk_notify(sp
->gref
, ESHUTDOWN
);
1187 for (gref
= ddp_head
.atpcb_next
; gref
!= &ddp_head
;
1188 gref
= gref
->atpcb_next
) {
1192 dPrintf(D_M_DDP
,D_L_TRACE
, ("ddp pid=%d\n", gref
->pid
));
1193 atalk_notify(gref
, ESHUTDOWN
);
1198 return(active_skts
);
1201 /* if there are no interfaces in the process of going online, continue shutting down DDP */
1202 for (i
= 0; i
< IF_TOTAL_MAX
; i
++) {
1203 if (at_interfaces
[i
].startup_inprogress
== TRUE
)
1206 if (MULTIPORT_MODE
) {
1208 /* free memory allocated for the rtmp/zip tables */
1210 FREE(ZT_table
, M_RTABLE
);
1211 ZT_table
= (ZT_entry
*)NULL
;
1214 FREE(RT_table
, M_RTABLE
);
1215 RT_table
= (RT_entry
*)NULL
;
1219 at_state
.flags
= 0; /* make sure inits are done on restart */
1221 wakeup(&ifID_home
->startup_inprogress
); /* if rtmp_router_start still starting up */
1223 /* from original ddp_shutdown() */
1233 dPrintf(D_M_DDP
, D_L_VERBOSE
, ("DDP shutdown completed"));
1236 * make sure we don't have a probe timeout hanging around
1237 * it's going to try and make use of an entry in at_interfaces
1238 * which is going to be zero'd out by the call to ddp_start a
1239 * little further down
1241 untimeout(aarp_sched_probe
, 0);
1243 /* *** after an SIOCSIFADDR and before an AIOCSIFADDR,
1244 this is the only place to find the ifID *** */
1245 for (i
= 0; i
< IF_TOTAL_MAX
; i
++) {
1246 ifID
= &at_interfaces
[i
];
1247 /* do LAP_IOC_OFFLINE processing */
1254 } /* ddp_shutdown */
1256 int routerStart(keP
)
1259 register at_ifaddr_t
*ifID
;
1267 * this will cause the ports to glean from the net the relevant
1268 * information before forwarding
1270 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1271 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1272 ("routerStart Port %d (%s) set to activating\n",
1273 ifID
->ifPort
, ifID
->ifName
));
1274 ifID
->ifRoutingState
= PORT_ACTIVATING
;
1275 ifID
->ifFlags
|= RTR_XNET_PORT
;
1279 * The next step is to check the information for each port before
1280 * declaring the ports up and forwarding
1282 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1283 ("router_start: waiting 20 sec before starting up\n"));
1285 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
1286 /* sleep for 20 seconds */
1288 /* the vaue of 10n terms of hz is 100ms */
1293 /* *** eventually this will be the ifID for the interface
1294 being brought up in router mode *** */
1295 msleep(&ifID_home
->startup_inprogress
, atalk_mutex
,
1296 PSOCK
| PCATCH
, "routerStart", &ts
))
1300 panic("routerStart: spurious interrupt");
1305 return(rtmp_router_start(keP
));
1306 /* was timeout(rtmp_router_start, 0, 20 * SYS_HZ); */
1309 void ZIPwakeup(elapp
, ZipError
)
1313 int s
, error
= ZipError
;
1315 ATDISABLE(s
, ddpinp_lock
);
1316 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
) {
1317 ATENABLE(s
, ddpinp_lock
);
1319 /* was ZIPContinue */
1320 /* was elapp_online() with jump to ZIP_sleep */
1322 /* instead of the goto ZIP_sleep ... */
1324 case 0 : /* success */
1325 elapp
->ifState
= LAP_ONLINE
;
1327 /* Send event with zone info. */
1328 atalk_post_msg(elapp
->aa_ifp
, KEV_ATALK_ZONEUPDATED
, 0, &(elapp
->ifZoneName
));
1332 /* instead of goto re_aarp; */
1333 /* We now call aarp_init() to assign an
1334 appletalk node addr */
1335 if ((elapp
->startup_error
= re_aarp(elapp
))) {
1336 elapp
->startup_inprogress
= FALSE
;
1337 wakeup(&elapp
->startup_inprogress
);
1338 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1339 ("elap_online: ack 2\n"));
1345 if (ZipError
!= ZIP_RE_AARP
) {
1346 elapp
->startup_error
= error
;
1347 elapp
->startup_inprogress
= FALSE
;
1348 wakeup(&elapp
->startup_inprogress
);
1349 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1350 ("elap_online: ifZipError=%d\n", error
));
1353 ATENABLE(s
, ddpinp_lock
);
1356 void AARPwakeup(probe_cb
)
1357 aarp_amt_t
*probe_cb
;
1363 ATDISABLE(s
, arpinp_lock
);
1364 elapp
= probe_cb
->elapp
;
1365 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
&& elapp
->aa_ifp
!= 0) {
1366 ATENABLE(s
, arpinp_lock
);
1368 /* was AARPContinue */
1369 errno
= aarp_init2(elapp
);
1370 /* aarp_init2() returns either -1 or 0 */
1372 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
1373 ("elap_online aarp_init for %s\n",
1375 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->ZoneMcastAddr
);
1376 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
1377 elapp
->ifState
= LAP_OFFLINE
;
1379 elapp
->startup_error
= EADDRNOTAVAIL
;
1380 elapp
->startup_inprogress
= FALSE
;
1381 wakeup(&elapp
->startup_inprogress
);
1382 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online: ack 2\n"));
1384 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
1385 ("elap_online: aarp_init returns zero\n"));
1386 elap_online2(elapp
);
1389 ATENABLE(s
, arpinp_lock
);
1392 void ddp_bit_reverse(addr
)
1393 unsigned char *addr
;
1395 static unsigned char reverse_data
[] = {
1396 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1397 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1398 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1399 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1400 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1401 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1402 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1403 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1404 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1405 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1406 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1407 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1408 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1409 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1410 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1411 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1412 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1413 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1414 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1415 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1416 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1417 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1418 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1419 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1420 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1421 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1422 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1423 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1424 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1425 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1426 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1427 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1432 for (k
=0; k
< 6; k
++)
1433 addr
[k
] = reverse_data
[addr
[k
]];
1436 static int elap_trackMcast(patp
, func
, addr
)
1443 switch(patp
->aa_ifp
->if_type
) {
1447 case IFT_IEEE8023ADLAG
: /* bonded ethernet */
1448 /* set addr to point to unique part of addr */
1451 /* first try to find match */
1452 /* *** save just one byte of the multicast address? *** */
1453 for (i
=0; i
< MAX_MCASTS
; i
++)
1454 if (c
== patp
->mcast
[i
]) {
1460 case MCAST_TRACK_DELETE
:
1462 patp
->mcast
[loc
] = 0;
1465 case MCAST_TRACK_ADD
:
1466 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add loc:%d\n", i
));
1468 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was there\n"));
1470 break; /* already there */
1472 for (i
=0; i
< MAX_MCASTS
; i
++)
1473 if (patp
->mcast
[i
] == 0) {
1477 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add1 loc:%d\n", i
));
1479 patp
->mcast
[loc
] = c
;
1480 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, adding(%x)\n",
1481 (*(int*)addr
)&0xffffff));
1484 /*errno = ENOMEM; */ /*LD 5/7/97 nobody is using that */
1488 case MCAST_TRACK_CHECK
:
1490 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:check, addr was there\n"));
1494 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was NOT there\n"));
1499 /*errno = EINVAL;*/ /*LD 5/7/97 nobody is using that */
1503 case IFT_ISO88025
: /* token ring */
1504 /* we would use the lowest byte of the addr argument as a value
1505 to shift left a 1 to form the mcast mask for TR. We'll do this
1515 static getSnmpCfg(snmp
)
1522 snmp
->cfg_ifCnt
= 0;
1524 bzero(snmp
,sizeof(snmpCfg_t
));
1525 for (i
=0, elapp
=at_interfaces
,ifc
=snmp
->cfg_ifCfg
;
1526 i
<IF_TOTAL_MAX
; i
++, elapp
++, ifc
++) {
1527 if (elapp
->ifState
!= LAP_OFFLINE
) {
1529 strlcpy(ifc
->ifc_name
,elapp
->ifName
, sizeof(ifc
->ifc_name
));
1530 ifc
->ifc_aarpSize
= getAarpTableSize(i
);
1531 ifc
->ifc_addrSize
= getPhysAddrSize(i
);
1532 switch (elapp
->aa_ifp
->if_type
) {
1535 case IFT_IEEE8023ADLAG
: /* bonded ethernet */
1536 ifc
->ifc_type
= SNMP_TYPE_ETHER2
;
1538 case IFT_ISO88025
: /* token ring */
1539 ifc
->ifc_type
= SNMP_TYPE_TOKEN
;
1543 ifc
->ifc_type
= SNMP_TYPE_OTHER
;
1546 ifc
->ifc_start
= elapp
->ifThisCableStart
;
1547 ifc
->ifc_end
= elapp
->ifThisCableEnd
;
1548 ifc
->ifc_ddpAddr
= elapp
->ifThisNode
;
1549 ifc
->ifc_status
= elapp
->ifState
== LAP_ONLINE
? 1 : 2;
1550 ifc
->ifc_zoneName
.len
= 0;
1551 if (elapp
->ifZoneName
.len
!= 0) {
1552 ifc
->ifc_zoneName
= elapp
->ifZoneName
;
1554 else if (elapp
->ifDefZone
) {
1555 ifc
->ifc_zoneName
= ZT_table
[elapp
->ifDefZone
-1].Zone
;
1557 else /* temp, debug only */
1558 ifc
->ifc_zoneName
= ZT_table
[0].Zone
;
1560 if (elapp
->ifFlags
& RTR_SEED_PORT
) {
1561 ifc
->ifc_netCfg
= SNMP_CFG_CONFIGURED
;
1562 ifc
->ifc_zoneCfg
= SNMP_CFG_CONFIGURED
;
1565 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1566 ifc
->ifc_zoneCfg
= SNMP_CFG_GARNERED
;
1569 else { /* single-port mode */
1570 if (elapp
->ifRouterState
== ROUTER_AROUND
) {
1571 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1574 ifc
->ifc_netCfg
= SNMP_CFG_GUESSED
;
1575 ifc
->ifc_zoneCfg
= SNMP_CFG_UNCONFIG
;
1580 snmp
->cfg_flags
= at_state
.flags
;
1586 int at_reg_mcast(ifID
, data
)
1590 struct ifnet
*nddp
= ifID
->aa_ifp
;
1591 struct sockaddr_dl sdl
;
1595 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1599 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1602 /* this is for ether_output */
1603 bzero(&sdl
, sizeof(sdl
));
1604 sdl
.sdl_family
= AF_LINK
;
1605 sdl
.sdl_alen
= sizeof(struct etalk_addr
);
1606 sdl
.sdl_len
= offsetof(struct sockaddr_dl
, sdl_data
)
1607 + sizeof(struct etalk_addr
);
1608 bcopy(data
, sdl
.sdl_data
, sizeof(struct etalk_addr
));
1609 /* these next two lines should not really be needed XXX */
1610 sdl
.sdl_index
= nddp
->if_index
;
1611 sdl
.sdl_type
= IFT_ETHER
;
1613 dPrintf(D_M_PAT
, D_L_STARTUP
,
1614 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1615 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1618 if (if_addmulti(nddp
, &sdl
, 0))
1625 int at_unreg_mcast(ifID
, data
)
1629 struct ifnet
*nddp
= ifID
->aa_ifp
;
1630 struct sockaddr_dl sdl
;
1634 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1638 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1640 /* this is for ether_output */
1641 bzero(&sdl
, sizeof(sdl
));
1642 sdl
.sdl_family
= AF_LINK
;
1643 sdl
.sdl_alen
= sizeof(struct etalk_addr
);
1644 sdl
.sdl_len
= offsetof(struct sockaddr_dl
, sdl_data
)
1645 + sizeof(struct etalk_addr
);
1646 bcopy(data
, sdl
.sdl_data
, sizeof(struct etalk_addr
));
1647 /* these next two lines should not really be needed XXX */
1648 sdl
.sdl_index
= nddp
->if_index
;
1649 sdl
.sdl_type
= IFT_ETHER
;
1651 dPrintf(D_M_PAT
, D_L_STARTUP
,
1652 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1653 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1655 bzero(data
, sizeof(struct etalk_addr
));
1657 if (if_delmulti(nddp
, &sdl
))
1663 /* *** at_reg_mcast() and at_unreg_mcast() should be replaced as soon as the
1664 new code to allow an AF_LINK address family multicast to be (un)registered
1665 using the SIOCADDMULTI / SIOCDELMULTI ioctls has been completed.
1667 The issue is that the "struct sockaddr_dl" needed for the AF_LINK does not
1668 fit in the "struct ifreq" that is used for these ioctls, and we do not want
1669 Blue/Classic, which currently uses AF_UNSPEC, to use a different address
1670 family multicast address than Mac OS X uses.
1673 int at_reg_mcast(ifID
, data
)
1677 struct ifnet
*nddp
= ifID
->aa_ifp
;
1678 struct sockaddr_dl sdl
;
1682 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1685 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1688 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1689 sdl
.sdl_family
= AF_LINK
;
1691 sdl
.sdl_type
= nddp
->if_type
;
1692 sdl
.sdl_alen
= nddp
->if_addrlen
;
1694 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1695 nddp
->if_name
, nddp
->if_unit
);
1696 bcopy(data
, LLADDR(&sdl
), sdl
.sdl_alen
);
1698 dPrintf(D_M_PAT
, D_L_STARTUP
,
1699 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1700 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1703 if (if_addmulti(nddp
, (struct sockaddr
*)&sdl
, 0))
1710 int at_unreg_mcast(ifID
, data
)
1714 struct ifnet
*nddp
= ifID
->aa_ifp
;
1715 struct sockaddr_dl sdl
;
1719 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1723 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1725 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1726 sdl
.sdl_family
= AF_LINK
;
1728 sdl
.sdl_type
= nddp
->if_type
;
1729 sdl
.sdl_alen
= nddp
->if_addrlen
;
1731 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1732 nddp
->if_name
, nddp
->if_unit
);
1734 dPrintf(D_M_PAT
, D_L_STARTUP
,
1735 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1736 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1738 bzero(data
, ETHERNET_ADDR_LEN
);
1740 if (if_delmulti(nddp
, (struct sockaddr
*)&sdl
))