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 short appletalk_inited
;
119 extern int adspInited
;
120 extern struct atpcb ddp_head
;
121 extern gref_t
*atp_inputQ
[];
122 extern struct atp_state
*atp_used_list
;
123 extern asp_scb_t
*asp_scbQ
[];
124 extern asp_scb_t
*scb_used_list
;
125 extern CCB
*adsp_inputQ
[];
126 extern CCB
*ccb_used_list
;
127 extern at_ddp_stats_t at_ddp_stats
;
128 extern lck_mtx_t
* atalk_mutex
;
131 extern snmpAarpEnt_t
* getAarp(int *);
132 extern void nbp_shutdown(), routershutdown(), ddp_brt_shutdown();
133 extern void ddp_brt_init(), rtmp_init(), rtmp_input();
134 extern rtmp_router_start(at_kern_err_t
*);
135 static void getIfNames(at_ifnames_t
*);
136 static void add_route();
137 static int set_zones();
139 static int elap_online1(), re_aarp();
140 int at_reg_mcast(), at_unreg_mcast();
141 void AARPwakeup(), ZIPwakeup();
142 static void elap_hangup();
145 at_ifaddr_t
*find_ifID(if_name
)
151 for (pat_id
=0; pat_id
< xpatcnt
; pat_id
++) {
152 if (!strcmp(at_interfaces
[pat_id
].ifName
, if_name
))
153 return(&at_interfaces
[pat_id
]);
156 return((at_ifaddr_t
*)NULL
);
159 static int validate_msg_size(m
, gref
, elapp
)
164 /* checks ioctl message type for minimum expected message size &
165 sends error back if size invalid
168 register ioc_t
*iocbp
;
169 register at_if_cfg_t
*cfgp
;
173 iocbp
= (ioc_t
*) gbuf_rptr(m
);
175 dPrintf(D_M_ELAP
, D_L_INFO
, ("validate_msg_size: ioc_cmd = %d\n",
177 switch (iocbp
->ioc_cmd
) {
178 case LAP_IOC_ADD_ROUTE
:
179 size
= sizeof(RT_entry
);
181 case LAP_IOC_GET_ROUTE
:
182 size
= sizeof(RT_entry
);
184 case LAP_IOC_GET_ZONE
:
185 size
= sizeof(ZT_entryno
);
187 case LAP_IOC_SNMP_GET_CFG
:
188 case LAP_IOC_SNMP_GET_AARP
:
189 case LAP_IOC_SNMP_GET_ZIP
:
190 case LAP_IOC_SNMP_GET_RTMP
:
191 case LAP_IOC_SNMP_GET_NBP
:
195 case ELAP_IOC_GET_STATS
:
196 case LAP_IOC_SNMP_GET_DDP
:
201 dPrintf(D_M_ELAP
, D_L_ERROR
, ("validate_msg_size: unknown ioctl\n"));
205 if (size
== 0) { /* a non-data ioctl */
209 if (gbuf_cont(m
) != NULL
)
210 i
= gbuf_len(gbuf_cont(m
));
211 if (iocbp
->ioc_count
< size
|| (gbuf_cont(m
) == NULL
) || i
< size
) {
212 dPrintf(D_M_ELAP
, D_L_ERROR
,
213 ("ioctl msg error:s:%d c:%d bcont:%c delta:%d\n",
214 size
, iocbp
->ioc_count
,
215 gbuf_cont(m
)? 'Y' : 'N', i
));
221 ioc_ack(EMSGSIZE
, m
, gref
);
223 } /* validate_msg_size */
225 int lap_online(elapp
, cfgp
)
231 if (elapp
->ifState
!= LAP_OFFLINE
) {
236 if (cfgp
->flags
& ELAP_CFG_HOME
) {
238 /* only 1 home allowed! */
241 dPrintf(D_M_ELAP
, D_L_STARTUP
,
242 ("elap_wput home I/F:%s\n", cfgp
->ifr_name
));
243 elapp
->flags
|= ELAP_CFG_HOME
;
246 if (MULTIPORT_MODE
) {
247 elapp
->flags
|= ELAP_CFG_ZONELESS
;
248 if (ROUTING_MODE
&& cfgp
->netStart
)
249 elapp
->flags
|= ELAP_CFG_SEED
;
252 if (!DEFAULT_ZONE(&cfgp
->zonename
) &&
253 (elapp
->flags
& ELAP_CFG_HOME
) || MULTIHOME_MODE
) {
254 elapp
->startup_zone
= cfgp
->zonename
;
257 if (elapp
->flags
& ELAP_CFG_SEED
) {
258 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
259 ("elap_wput: found to be seed\n"));
260 elapp
->ifThisCableStart
= cfgp
->netStart
;
261 elapp
->ifThisCableEnd
= cfgp
->netEnd
;
264 dPrintf(D_M_ELAP
,D_L_ERROR
,
265 ("elap_wput: we believe we're not seed\n"));
266 /* from ELAP_IOC_SET_CFG */
267 if (ATALK_VALUE(cfgp
->node
)) {
271 initial_node
= cfgp
->node
.s_node
;
272 initial_net
= cfgp
->node
.s_net
;
273 if ((initial_node
<0xfe) && (initial_node
>0) &&
274 !((initial_net
== 0) ||
275 ((initial_net
>= DDP_STARTUP_LOW
)&&
276 (initial_net
<= DDP_STARTUP_HIGH
)))) {
278 elapp
->initial_addr
= cfgp
->node
;
283 elapp
->startup_error
= 0;
284 elapp
->startup_inprogress
= FALSE
;
285 if ((error
= elap_online1(elapp
)))
288 if (!(MULTIPORT_MODE
) &&
289 elapp
->ifZoneName
.len
== 1 &&
290 elapp
->ifZoneName
.str
[0] == '*' &&
291 !DEFAULT_ZONE(&cfgp
->zonename
)) {
292 nbp_add_multicast(&cfgp
->zonename
, elapp
);
297 /***********************************************************************
300 **********************************************************************/
301 int elap_wput(gref
, m
)
306 register ioc_t
*iocbp
;
307 register at_if_cfg_t
*cfgp
;
308 at_elap_stats_t
*statsp
;
315 switch (gbuf_type(m
)) {
318 dPrintf(D_M_ELAP
,D_L_ERROR
,
319 ("Output data to control channel is ignored\n"));
323 iocbp
= (ioc_t
*) gbuf_rptr(m
);
325 if (validate_msg_size(m
, gref
, &elapp
))
329 cfgp
= (at_if_cfg_t
*) gbuf_rptr(gbuf_cont(m
));
331 if (LAP_IOC_MYIOCTL(iocbp
->ioc_cmd
) ||
332 ELAP_IOC_MYIOCTL(iocbp
->ioc_cmd
)) {
334 switch (iocbp
->ioc_cmd
) {
335 case ELAP_IOC_GET_STATS
:
336 #ifdef APPLETALK_DEBUG
337 kprintf("LAP_IOC_GET_STATS\n");
339 if ( (gbuf_cont(m
) == NULL
)
340 || (elapp
= find_ifID(gbuf_rptr(gbuf_cont(m
)))) == NULL
) {
341 ioc_ack(EINVAL
, m
, gref
);
344 gbuf_freem(gbuf_cont(m
));
345 if ((gbuf_cont(m
) =gbuf_alloc(sizeof(at_elap_stats_t
),
347 ioc_ack(ENOBUFS
, m
, gref
);
350 statsp
= ((at_elap_stats_t
*)gbuf_rptr(gbuf_cont(m
)));
351 *statsp
= elapp
->stats
;
352 gbuf_wset(gbuf_cont(m
),sizeof(at_elap_stats_t
));
353 iocbp
->ioc_count
= sizeof(at_elap_stats_t
);
357 case LAP_IOC_ADD_ROUTE
:
358 #ifdef APPLETALK_DEBUG
359 kprintf("LAP_IOC_ADD_ROUTE\n");
361 add_route((RT_entry
*)gbuf_rptr(gbuf_cont(m
)));
365 case LAP_IOC_GET_ZONE
:
366 #ifdef APPLETALK_DEBUG
367 kprintf("LAP_IOC_GET_ZONE\n");
369 /* return next ZT_entryno from ZT_table
370 a pointer to the struct ZT_entryno is passed down from
371 user space and the first byte is cast to a int, if
372 this int is non-zero, then the first ZT_entry is
373 returned and subsequent calls with a zero value
374 will return the next entry in the table. The next
375 read after the last valid entry will return EINVAL
380 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
381 gbuf_freem(gbuf_cont(m
));
384 pZTe
= zt_getNextZone(i
);
386 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(ZT_entryno
), PRI_MED
)) == NULL
) {
387 ioc_ack(ENOBUFS
, m
, gref
);
390 *(ZT_entryno
*)gbuf_rptr(gbuf_cont(m
)) = *pZTe
;
391 gbuf_wset(gbuf_cont(m
),sizeof(ZT_entryno
));
392 iocbp
->ioc_count
= sizeof(ZT_entryno
);
396 ioc_ack(EINVAL
, m
, gref
);
400 case LAP_IOC_GET_ROUTE
:
401 #ifdef APPLETALK_DEBUG
402 kprintf("LAP_IOC_GET_ROUTE\n");
404 /* return next RT_entry from RT_table
405 * a pointer to the struct RT_entry is
406 * passed down from user space and the first
407 * byte is cast to a int, if this int is
408 * non-zero, then the first RT_entry is
409 * returned and subsequent calls with a
410 * zero value will return the next entry in
411 * the table. The next read after the last
412 * valid entry will return EINVAL
417 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
418 gbuf_freem(gbuf_cont(m
));
421 pRT
= rt_getNextRoute(i
);
423 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(RT_entry
), PRI_MED
)) == NULL
) {
424 ioc_ack(ENOBUFS
, m
, gref
);
427 *(RT_entry
*)gbuf_rptr(gbuf_cont(m
)) = *pRT
;
428 gbuf_wset(gbuf_cont(m
),sizeof(RT_entry
));
429 iocbp
->ioc_count
= sizeof(RT_entry
);
433 ioc_ack(EINVAL
, m
, gref
);
437 case LAP_IOC_SNMP_GET_DDP
:
438 #ifdef APPLETALK_DEBUG
439 kprintf("LAP_IOC_SNMP_GET_DDP\n");
441 if (!(at_state
.flags
& AT_ST_STARTED
)) {
442 ioc_ack(ENOTREADY
, m
, gref
);
445 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(snmpStats_t
),
447 ioc_ack(ENOBUFS
, m
, gref
);
451 *(snmpStats_t
*)gbuf_rptr(gbuf_cont(m
)) = snmpStats
;
452 gbuf_wset(gbuf_cont(m
),sizeof(snmpStats
));
453 iocbp
->ioc_count
= sizeof(snmpStats
);
456 case LAP_IOC_SNMP_GET_CFG
:
457 #ifdef APPLETALK_DEBUG
458 kprintf("LAP_IOC_SNMP_GET_CFG\n");
464 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
465 gbuf_freem(gbuf_cont(m
));
467 if (!(at_state
.flags
& AT_ST_STARTED
)) {
469 iocbp
->ioc_count
= 0;
470 ioc_ack(ENOTREADY
, m
, gref
);
471 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
472 ("elap_wput: cfg req, stack down\n"));
475 if (i
== UPDATE_IF_CHANGED
&&
476 !(at_state
.flags
& AT_ST_IF_CHANGED
)) {
477 iocbp
->ioc_count
= 0;
479 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
480 ("elap_wput: cfg req, unchanged\n"));
483 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
484 ("elap_wput: cfg req, changed\n"));
486 if (getSnmpCfg(&snmp
)) {
487 dPrintf(D_M_ELAP
,D_L_ERROR
,
488 ("elap_wput:SNMP_GET_CFG error\n"));
489 ioc_ack(EOPNOTSUPP
, m
, gref
);
492 /* send up only used part of table */
493 size
= sizeof(snmp
) -
494 sizeof(snmpIfCfg_t
) * (MAX_IFS
- snmp
.cfg_ifCnt
);
496 if ((gbuf_cont(m
) = gbuf_alloc(size
, PRI_MED
)) == NULL
) {
497 ioc_ack(ENOBUFS
, m
, gref
);
500 bcopy(&snmp
,gbuf_rptr(gbuf_cont(m
)),size
);
501 gbuf_wset(gbuf_cont(m
),size
);
502 iocbp
->ioc_count
= size
;
503 at_state
.flags
&= ~AT_ST_IF_CHANGED
;
508 case LAP_IOC_SNMP_GET_AARP
:
510 snmpAarpEnt_t
*snmpp
;
512 #ifdef APPLETALK_DEBUG
513 kprintf("LAP_IOC_SNMP_GET_AARP\n");
515 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
516 gbuf_freem(gbuf_cont(m
));
518 dPrintf(D_M_ELAP
,D_L_INFO
,
519 ("elap_wput:calling getarp,i=%d\n", i
));
521 bytes
= i
* sizeof(snmpAarpEnt_t
);
522 dPrintf(D_M_ELAP
,D_L_INFO
,
523 ("elap_wput:getarp returned, i=%d,bytes=%d\n",
526 if ((gbuf_cont(m
) = gbuf_alloc(bytes
, PRI_MED
)) == NULL
) {
527 ioc_ack(ENOBUFS
, m
, gref
);
530 bcopy(snmpp
, gbuf_rptr(gbuf_cont(m
)), bytes
);
531 gbuf_wset(gbuf_cont(m
),bytes
);
532 iocbp
->ioc_count
= bytes
;
536 ioc_ack(EOPNOTSUPP
, m
, gref
);
540 case LAP_IOC_SNMP_GET_ZIP
:
541 #ifdef APPLETALK_DEBUG
542 kprintf("LAP_IOC_SNMP_GET_ZIP\n");
544 { /* matching brace NOT in this case */
546 register int size
, total
, tabsize
;
547 gbuf_t
*mn
; /* new gbuf */
548 gbuf_t
*mo
; /* old gbuf */
549 gbuf_t
*mt
; /* temp */
552 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
553 gbuf_freem(gbuf_cont(m
));
555 if (!(at_state
.flags
& AT_ST_STARTED
)) {
556 ioc_ack(ENOTREADY
, m
, gref
);
559 if (i
== UPDATE_IF_CHANGED
&&
560 !(at_state
.flags
& AT_ST_ZT_CHANGED
)) {
561 iocbp
->ioc_count
= 0;
566 tabsize
= getZipTableSize();
568 /* retrieve table into multiple gbufs */
569 for (i
=0; i
<tabsize
; i
+=j
) {
571 MAX_ZIP
? MAX_ZIP
: tabsize
- i
;
572 size
= j
< MAX_ZIP
? sizeof(ZT_entry
)*j
: MAX_ZIP_BYTES
;
573 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
575 gbuf_freem(gbuf_cont(m
));
576 ioc_ack(ENOBUFS
, m
, gref
);
579 if (!mo
) { /* if first new one */
588 getZipTable((ZT_entry
*)gbuf_rptr(mn
),i
,j
);
591 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
594 iocbp
->ioc_count
= 0;
595 ioc_ack(ENOBUFS
, m
, gref
);
599 dPrintf(D_M_ELAP
,D_L_WARNING
,
600 ("elap_wput:snmp: empty zip table\n"));
603 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
604 gbuf_wset(gbuf_cont(m
),sizeof(int));
605 iocbp
->ioc_count
= sizeof(int);
608 atalk_putnext(gref
,mt
); /* send up table */
609 at_state
.flags
&= ~AT_ST_ZT_CHANGED
;
612 case LAP_IOC_SNMP_GET_RTMP
:
613 #ifdef APPLETALK_DEBUG
614 kprintf("LAP_IOC_SNMP_GET_RTMP\n");
616 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
617 gbuf_freem(gbuf_cont(m
));
619 if (!(at_state
.flags
& AT_ST_STARTED
)) {
620 ioc_ack(ENOTREADY
, m
, gref
);
623 if (i
== UPDATE_IF_CHANGED
&&
624 !(at_state
.flags
& AT_ST_RT_CHANGED
)) {
625 iocbp
->ioc_count
= 0;
631 tabsize
= getRtmpTableSize();
633 /* retrieve table into multiple gbufs */
634 for (i
=0; i
<tabsize
; i
+=j
) {
636 MAX_RTMP
? MAX_RTMP
: tabsize
- i
;
637 size
= j
< MAX_RTMP
? sizeof(RT_entry
)*j
: MAX_RTMP_BYTES
;
638 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
640 gbuf_freem(gbuf_cont(m
));
641 ioc_ack(ENOBUFS
, m
, gref
);
644 if (!mo
) { /* if first new one */
653 getRtmpTable((RT_entry
*)gbuf_rptr(mn
),i
,j
);
656 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
659 iocbp
->ioc_count
= 0;
660 ioc_ack(ENOBUFS
, m
, gref
);
665 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
666 gbuf_wset(gbuf_cont(m
),sizeof(int));
667 iocbp
->ioc_count
= sizeof(int);
670 atalk_putnext(gref
,mt
); /* send up table */
671 at_state
.flags
&= ~AT_ST_RT_CHANGED
;
674 case LAP_IOC_SNMP_GET_NBP
:
675 #ifdef APPLETALK_DEBUG
676 kprintf("LAP_IOC_SNMP_GET_NBP\n");
678 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
679 gbuf_freem(gbuf_cont(m
));
681 if (!(at_state
.flags
& AT_ST_STARTED
)) {
682 ioc_ack(ENOTREADY
, m
, gref
);
685 if (i
== UPDATE_IF_CHANGED
&&
686 !(at_state
.flags
& AT_ST_NBP_CHANGED
)) {
687 iocbp
->ioc_count
= 0;
689 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
690 ("elap_wput: nbp req denied, no change\n"));
695 tabsize
= getNbpTableSize();
697 /* retrieve table into multiple gbufs */
698 for (i
=0; i
<tabsize
; i
+=j
) {
700 MAX_NBP
? MAX_NBP
: tabsize
- i
;
701 size
= j
< MAX_NBP
? sizeof(snmpNbpEntry_t
)*j
: MAX_NBP_BYTES
;
703 size
+= SNMP_NBP_HEADER_SIZE
;
704 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
706 gbuf_freem(gbuf_cont(m
));
707 ioc_ack(ENOBUFS
, m
, gref
);
710 if (!mo
) { /* if first new one */
713 nbp
= (snmpNbpTable_t
*)gbuf_rptr(mn
);
714 nbp
->nbpt_entries
= tabsize
;
715 nbp
->nbpt_zone
= ifID_home
->ifZoneName
;
716 getNbpTable(nbp
->nbpt_table
,i
,j
);
721 getNbpTable((snmpNbpEntry_t
*)gbuf_rptr(mn
),i
,j
);
726 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
729 iocbp
->ioc_count
= 0;
730 ioc_ack(ENOBUFS
, m
, gref
);
735 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
736 gbuf_wset(gbuf_cont(m
),sizeof(int));
737 iocbp
->ioc_count
= sizeof(int);
740 atalk_putnext(gref
,mt
); /* send up table */
741 at_state
.flags
&= ~AT_ST_NBP_CHANGED
;
746 #ifdef APPLETALK_DEBUG
747 kprintf("unknown ioctl %d\n", iocbp
->ioc_cmd
);
749 ioc_ack(ENOTTY
, m
, gref
);
750 dPrintf(D_M_ELAP
, D_L_WARNING
,
751 ("elap_wput: unknown ioctl (%d)\n", iocbp
->ioc_cmd
));
754 elapp
->stats
.unknown_mblks
++;
769 /* Called directly by ddp/zip.
771 elap_dataput(m
, elapp
, addr_flag
, addr
)
773 register at_ifaddr_t
*elapp
;
779 extern int zip_type_packet();
780 struct etalk_addr dest_addr
;
781 struct atalk_addr dest_at_addr
;
782 extern gbuf_t
*growmsg();
784 /* flag to aarp to loopback (default) */
786 /* the incoming frame is of the form {flag, address, ddp...}
787 * where "flag" indicates whether the address is an 802.3
788 * (link) address, or an appletalk address. If it's an
789 * 802.3 address, the packet can just go out to the network
790 * through PAT, if it's an appletalk address, AT->802.3 address
791 * resolution needs to be done.
792 * If 802.3 address is known, strip off the flag and 802.3
793 * address, and prepend 802.2 and 802.3 headers.
797 addr_flag
= *(u_char
*)gbuf_rptr(m
);
802 case AT_ADDR_NO_LOOP
:
807 dest_at_addr
= *(struct atalk_addr
*)gbuf_rptr(m
);
808 gbuf_rinc(m
,sizeof(struct atalk_addr
));
810 dest_at_addr
= *(struct atalk_addr
*)addr
;
814 dest_addr
= *(struct etalk_addr
*)gbuf_rptr(m
);
815 gbuf_rinc(m
,sizeof(struct etalk_addr
));
817 dest_addr
= *(struct etalk_addr
*)addr
;
820 gbuf_freel(m
); /* unknown address type, chuck it */
826 /* At this point, rptr points to ddp header for sure */
827 if (elapp
->ifState
== LAP_OFFLINE
) {
832 if (elapp
->ifState
== LAP_ONLINE_FOR_ZIP
) {
833 /* see if this is a ZIP packet that we need
834 * to let through even though network is
837 if (zip_type_packet(m
) == 0) {
843 elapp
->stats
.xmit_packets
++;
844 size
= gbuf_msgsize(m
);
845 elapp
->stats
.xmit_bytes
+= size
;
846 snmpStats
.dd_outLong
++;
849 case AT_ADDR_NO_LOOP
:
852 * we don't want elap to be looking into ddp header, so
853 * it doesn't know net#, consequently can't do
854 * AMT_LOOKUP. That task left to aarp now.
856 error
= aarp_send_data(m
, elapp
, &dest_at_addr
, loop
);
859 error
= pat_output(elapp
, m
, &dest_addr
, 0);
865 /************************************************************************
868 ************************************************************************/
870 static int elap_online1(elapp
)
875 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online:%s elapp:0x%x\n",
876 (elapp
->ifName
) ? &elapp
->ifName
[0] : "NULL interface", (u_int
) elapp
));
877 if (elapp
->ifState
!= LAP_OFFLINE
|| elapp
->startup_inprogress
== TRUE
)
880 at_state
.flags
|= AT_ST_IF_CHANGED
;
882 if (elapp
->flags
& ELAP_CFG_HOME
) /* tell ddp_add_if if this is home */
883 elapp
->ifFlags
|= AT_IFF_DEFAULT
;
885 /* Get DDP started */
886 if ((errno
= ddp_add_if(elapp
)))
889 // check if we still have an interface - can be lost when
890 // ddp_add_if calls malloc
891 // need to make check here after ddp_add_if completes because
892 // lap_online will call ddp_rem_if if we fail here
893 if (elapp
->aa_ifp
== 0)
896 /* set up multicast address for cable-wide broadcasts */
897 (void)at_reg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
899 // need to check again if interface is present
900 // can be lost in at_reg_mcast
901 if (elapp
->aa_ifp
== 0)
904 elapp
->startup_inprogress
= TRUE
;
905 if (! (elapp
->startup_error
= re_aarp(elapp
))) {
906 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
907 (void)msleep(&elapp
->startup_inprogress
, atalk_mutex
, PSOCK
| PCATCH
,
911 /* then later, after some timeouts AARPwakeup() is called */
913 return(elapp
->startup_error
);
916 static int re_aarp(elapp
)
921 /* We now call aarp_init() to assign an appletalk node addr */
922 errno
= aarp_init1(elapp
);
923 /* aarp_init1() returns either -1 or ENOTREADY */
924 if (errno
== ENOTREADY
)
927 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
928 ("elap_online aarp_init for %s\n", elapp
->ifName
));
929 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
931 elapp
->ifState
= LAP_OFFLINE
;
932 return(EADDRNOTAVAIL
);
936 /* called from AARPwakeup */
937 static void elap_online2(elapp
)
940 if (MULTIPORT_MODE
) {
941 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
942 ("elap_online: re_aarp, we know it's a router...\n"));
944 if (elapp
->flags
& ELAP_CFG_SEED
) {
945 /* add route table entry (zones to be added later) */
946 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
947 ("elap_online: rt_insert Cable %d-%d port =%d as SEED\n",
948 elapp
->ifThisCableStart
, elapp
->ifThisCableEnd
, elapp
->ifPort
));
949 rt_insert(elapp
->ifThisCableEnd
,
950 elapp
->ifThisCableStart
,
953 RTE_STATE_PERMANENT
| RTE_STATE_ZKNOWN
| RTE_STATE_GOOD
955 /* LD 081694: set the RTR_SEED_PORT flag for seed ports */
956 elapp
->ifFlags
|= RTR_SEED_PORT
;
959 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
960 ("elap_online: it's a router, but non seed\n"));
963 if (elapp
->flags
& ELAP_CFG_ZONELESS
) {
964 /* ELAP_CFG_ZONELESS tells us that it is a router or in
965 multihome mode, so we don't want to do the GetNetInfo
966 exchange with the router. */
968 elapp
->ifState
= LAP_ONLINE_ZONELESS
;
969 elapp
->startup_inprogress
= FALSE
;
970 wakeup(&elapp
->startup_inprogress
);
971 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online: ack 3\n"));
975 /* if we don't already have a zone and a multicast address */
976 if (*(int *)&elapp
->ZoneMcastAddr
== 0 || elapp
->ifZoneName
.len
== 0) {
977 /* hzonehash is a global containing the nbp hash for the startup_zone */
980 /* Get ZIP rolling to get zone multicast address, etc. */
981 elapp
->ifState
= LAP_ONLINE_FOR_ZIP
;
982 (void)zip_control(elapp
, ZIP_ONLINE
);
983 /* zip_control (w. control == ZIP_ONLINE) always returns ENOTREADY */
985 /* later, after some timeouts ZIPwakeup() is called. */
987 /* otherwise, we have the zone and the multicast already,
988 so don't bother with another ZIP GetNetInfo request */
993 /* called from rtmp_router_start */
994 int elap_online3(elapp
)
997 elapp
->startup_inprogress
= TRUE
;
999 /* just reset the net range */
1000 elapp
->initial_addr
.s_net
= 0;
1001 elapp
->initial_addr
.s_node
= 0;
1002 dPrintf(D_M_ELAP_LOW
, D_L_STARTUP_INFO
,
1003 ("elap_online: goto re_aarp port=%d\n", elapp
->ifPort
));
1005 if ((elapp
->startup_error
= re_aarp(elapp
)))
1006 return(elapp
->startup_error
);
1008 /* then later, after some timeouts AARPwakeup() is called */
1010 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
1011 (void)msleep(&elapp
->startup_inprogress
, atalk_mutex
, PSOCK
| PCATCH
,
1013 return(elapp
->startup_error
);
1014 } /* elap_online3 */
1016 /****************************************************************************
1019 ****************************************************************************/
1021 void elap_offline(elapp
)
1022 register at_ifaddr_t
*elapp
;
1025 void zip_sched_getnetinfo(); /* forward reference */
1028 dPrintf(D_M_ELAP
, D_L_SHUTDN_INFO
, ("elap_offline:%s\n", elapp
->ifName
));
1029 if (elapp
->ifState
!= LAP_OFFLINE
) {
1031 /* Since AppleTalk is going away, remove the cable
1032 * multicast address and turn the interface off so that all
1033 * AppleTalk packets are dropped in the driver itself.
1034 * Get rid of the zone multicast address prior to going Offline.
1036 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->ZoneMcastAddr
);
1037 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
1038 elapp
->ifState
= LAP_OFFLINE
;
1041 RT_DELETE(elapp
->ifThisCableEnd
,
1042 elapp
->ifThisCableStart
);
1044 /* make sure no zip timeouts are left running */
1045 elapp
->ifGNIScheduled
= 0;
1046 untimeout(zip_sched_getnetinfo
, elapp
);
1049 } /* elap_offline */
1052 static void add_route(rt
)
1055 /* support ioctl to manually add routes to table.
1056 this is really only for testing
1059 rt_insert( rt
->NetStop
, rt
->NetStart
, rt
->NextIRNet
,
1060 rt
->NextIRNode
, rt
->NetDist
, rt
->NetPort
,
1062 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("adding route: %ud:%ud dist:%ud\n",
1063 rt
->NetStart
, rt
->NetStop
,rt
->NetDist
));
1069 * Initialization that takes place each time AppleTalk is restarted.
1074 TAILQ_INIT(&at_ifQueueHd
);
1075 TAILQ_INIT(&name_registry
);
1076 bzero(at_interfaces
, sizeof(at_interfaces
));
1077 bzero(ifID_table
, sizeof(ifID_table
));
1078 bzero(&at_ddp_stats
, sizeof(at_ddp_stats_t
));
1079 rtmp_init(); /* initialize trackedrouters */
1081 add_ddp_handler(RTMP_SOCKET
, rtmp_input
);
1082 ifID_home
= (at_ifaddr_t
*)NULL
;
1086 int ddp_shutdown(count_only
)
1090 asp_scb_t
*scb
, *scb_next
;
1091 struct atp_state
*atp
, *atp_next
;
1094 vm_offset_t temp_rcb_data
, temp_state_data
;
1095 int i
, active_skts
= 0; /* count of active pids for non-socketized
1096 AppleTalk protocols */
1098 /* Network is shutting down... send error messages up on each open
1100 *** For now, for ASP, ATP and ADSP, attempt to notify open
1101 sockets, but return EBUSY and don't complete shutdown. ***
1105 nbp_shutdown(); /* clear all known NVE */
1108 for (scb
= scb_used_list
; scb
; ) {
1109 scb_next
= scb
->next_scb
;
1112 dPrintf(D_M_ASP
, D_L_TRACE
, ("asp pid=%d\n", scb
->pid
));
1113 atalk_notify(scb
->gref
, ESHUTDOWN
);
1117 for (i
= 0; i
< 256 ; i
++) {
1118 if ((scb
= asp_scbQ
[i
]))
1120 scb_next
= scb
->next_scb
;
1123 dPrintf(D_M_ASP
, D_L_TRACE
,
1124 ("asp pid=%d\n", scb
->pid
));
1125 atalk_notify(scb
->gref
, ESHUTDOWN
);
1132 for (atp
= atp_used_list
; atp
; ) {
1133 atp_next
= atp
->atp_trans_waiting
;
1136 dPrintf(D_M_ATP
, D_L_TRACE
, ("atp pid=%d\n", atp
->atp_pid
));
1137 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1141 for (i
= 0; i
< 256; i
++) {
1142 if ((gref
= atp_inputQ
[i
]) && (gref
!= (gref_t
*)1)) {
1143 atp
= (struct atp_state
*)gref
->info
;
1147 dPrintf(D_M_ATP
, D_L_TRACE
,
1148 ("atp pid=%d\n", atp
->atp_pid
));
1149 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1156 for (sp
= ccb_used_list
; sp
; ) {
1157 sp_next
= sp
->otccbLink
;
1160 dPrintf(D_M_ADSP
, D_L_TRACE
, ("adsp pid=%d\n", sp
->pid
));
1161 atalk_notify(sp
->gref
, ESHUTDOWN
);
1165 for (i
= 0; i
< 256 ; i
++) {
1166 if ((sp
= adsp_inputQ
[i
]))
1168 sp_next
= sp
->otccbLink
;
1171 dPrintf(D_M_ADSP
, D_L_TRACE
,
1172 ("adsp pid=%d\n", sp
->pid
));
1173 atalk_notify(sp
->gref
, ESHUTDOWN
);
1180 for (gref
= ddp_head
.atpcb_next
; gref
!= &ddp_head
;
1181 gref
= gref
->atpcb_next
) {
1185 dPrintf(D_M_DDP
,D_L_TRACE
, ("ddp pid=%d\n", gref
->pid
));
1186 atalk_notify(gref
, ESHUTDOWN
);
1190 return(active_skts
);
1192 /* if there are no interfaces in the process of going online, continue shutting down DDP */
1193 for (i
= 0; i
< IF_TOTAL_MAX
; i
++) {
1194 if (at_interfaces
[i
].startup_inprogress
== TRUE
)
1197 if (MULTIPORT_MODE
) {
1199 /* free memory allocated for the rtmp/zip tables */
1201 FREE(ZT_table
, M_RTABLE
);
1202 ZT_table
= (ZT_entry
*)NULL
;
1205 FREE(RT_table
, M_RTABLE
);
1206 RT_table
= (RT_entry
*)NULL
;
1210 at_state
.flags
= 0; /* make sure inits are done on restart */
1212 wakeup(&ifID_home
->startup_inprogress
); /* if rtmp_router_start still starting up */
1214 /* from original ddp_shutdown() */
1224 dPrintf(D_M_DDP
, D_L_VERBOSE
, ("DDP shutdown completed"));
1227 * make sure we don't have a probe timeout hanging around
1228 * it's going to try and make use of an entry in at_interfaces
1229 * which is going to be zero'd out by the call to ddp_start a
1230 * little further down
1232 untimeout(aarp_sched_probe
, 0);
1234 /* *** after an SIOCSIFADDR and before an AIOCSIFADDR,
1235 this is the only place to find the ifID *** */
1236 for (i
= 0; i
< IF_TOTAL_MAX
; i
++) {
1237 ifID
= &at_interfaces
[i
];
1238 /* do LAP_IOC_OFFLINE processing */
1244 } /* ddp_shutdown */
1246 int routerStart(keP
)
1249 register at_ifaddr_t
*ifID
;
1257 * this will cause the ports to glean from the net the relevant
1258 * information before forwarding
1260 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1261 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1262 ("routerStart Port %d (%s) set to activating\n",
1263 ifID
->ifPort
, ifID
->ifName
));
1264 ifID
->ifRoutingState
= PORT_ACTIVATING
;
1265 ifID
->ifFlags
|= RTR_XNET_PORT
;
1269 * The next step is to check the information for each port before
1270 * declaring the ports up and forwarding
1272 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1273 ("router_start: waiting 20 sec before starting up\n"));
1275 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
1276 /* sleep for 20 seconds */
1278 /* the vaue of 10n terms of hz is 100ms */
1283 /* *** eventually this will be the ifID for the interface
1284 being brought up in router mode *** */
1285 msleep(&ifID_home
->startup_inprogress
, atalk_mutex
,
1286 PSOCK
| PCATCH
, "routerStart", &ts
))
1290 panic("routerStart: spurious interrupt");
1295 return(rtmp_router_start(keP
));
1296 /* was timeout(rtmp_router_start, 0, 20 * SYS_HZ); */
1299 void ZIPwakeup(elapp
, ZipError
)
1303 int error
= ZipError
;
1305 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
) {
1307 /* was ZIPContinue */
1308 /* was elapp_online() with jump to ZIP_sleep */
1310 /* instead of the goto ZIP_sleep ... */
1312 case 0 : /* success */
1313 elapp
->ifState
= LAP_ONLINE
;
1315 /* Send event with zone info. */
1316 atalk_post_msg(elapp
->aa_ifp
, KEV_ATALK_ZONEUPDATED
, 0, &(elapp
->ifZoneName
));
1320 /* instead of goto re_aarp; */
1321 /* We now call aarp_init() to assign an
1322 appletalk node addr */
1323 if ((elapp
->startup_error
= re_aarp(elapp
))) {
1324 elapp
->startup_inprogress
= FALSE
;
1325 wakeup(&elapp
->startup_inprogress
);
1326 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1327 ("elap_online: ack 2\n"));
1333 if (ZipError
!= ZIP_RE_AARP
) {
1334 elapp
->startup_error
= error
;
1335 elapp
->startup_inprogress
= FALSE
;
1336 wakeup(&elapp
->startup_inprogress
);
1337 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1338 ("elap_online: ifZipError=%d\n", error
));
1343 void AARPwakeup(probe_cb
)
1344 aarp_amt_t
*probe_cb
;
1349 elapp
= probe_cb
->elapp
;
1350 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
&& elapp
->aa_ifp
!= 0) {
1352 /* was AARPContinue */
1353 errno
= aarp_init2(elapp
);
1354 /* aarp_init2() returns either -1 or 0 */
1356 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
1357 ("elap_online aarp_init for %s\n",
1359 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->ZoneMcastAddr
);
1360 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
1361 elapp
->ifState
= LAP_OFFLINE
;
1363 elapp
->startup_error
= EADDRNOTAVAIL
;
1364 elapp
->startup_inprogress
= FALSE
;
1365 wakeup(&elapp
->startup_inprogress
);
1366 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online: ack 2\n"));
1368 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
1369 ("elap_online: aarp_init returns zero\n"));
1370 elap_online2(elapp
);
1375 void ddp_bit_reverse(addr
)
1376 unsigned char *addr
;
1378 static unsigned char reverse_data
[] = {
1379 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1380 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1381 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1382 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1383 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1384 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1385 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1386 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1387 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1388 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1389 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1390 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1391 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1392 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1393 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1394 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1395 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1396 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1397 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1398 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1399 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1400 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1401 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1402 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1403 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1404 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1405 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1406 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1407 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1408 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1409 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1410 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1415 for (k
=0; k
< 6; k
++)
1416 addr
[k
] = reverse_data
[addr
[k
]];
1419 static int elap_trackMcast(patp
, func
, addr
)
1426 switch(patp
->aa_ifp
->if_type
) {
1430 case IFT_IEEE8023ADLAG
: /* bonded ethernet */
1431 /* set addr to point to unique part of addr */
1434 /* first try to find match */
1435 /* *** save just one byte of the multicast address? *** */
1436 for (i
=0; i
< MAX_MCASTS
; i
++)
1437 if (c
== patp
->mcast
[i
]) {
1443 case MCAST_TRACK_DELETE
:
1445 patp
->mcast
[loc
] = 0;
1448 case MCAST_TRACK_ADD
:
1449 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add loc:%d\n", i
));
1451 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was there\n"));
1453 break; /* already there */
1455 for (i
=0; i
< MAX_MCASTS
; i
++)
1456 if (patp
->mcast
[i
] == 0) {
1460 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add1 loc:%d\n", i
));
1462 patp
->mcast
[loc
] = c
;
1463 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, adding(%x)\n",
1464 (*(int*)addr
)&0xffffff));
1467 /*errno = ENOMEM; */ /*LD 5/7/97 nobody is using that */
1471 case MCAST_TRACK_CHECK
:
1473 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:check, addr was there\n"));
1477 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was NOT there\n"));
1482 /*errno = EINVAL;*/ /*LD 5/7/97 nobody is using that */
1486 case IFT_ISO88025
: /* token ring */
1487 /* we would use the lowest byte of the addr argument as a value
1488 to shift left a 1 to form the mcast mask for TR. We'll do this
1498 static getSnmpCfg(snmp
)
1505 snmp
->cfg_ifCnt
= 0;
1507 bzero(snmp
,sizeof(snmpCfg_t
));
1508 for (i
=0, elapp
=at_interfaces
,ifc
=snmp
->cfg_ifCfg
;
1509 i
<IF_TOTAL_MAX
; i
++, elapp
++, ifc
++) {
1510 if (elapp
->ifState
!= LAP_OFFLINE
) {
1512 strncpy(ifc
->ifc_name
,elapp
->ifName
, sizeof(ifc
->ifc_name
));
1513 ifc
->ifc_aarpSize
= getAarpTableSize(i
);
1514 ifc
->ifc_addrSize
= getPhysAddrSize(i
);
1515 switch (elapp
->aa_ifp
->if_type
) {
1518 case IFT_IEEE8023ADLAG
: /* bonded ethernet */
1519 ifc
->ifc_type
= SNMP_TYPE_ETHER2
;
1521 case IFT_ISO88025
: /* token ring */
1522 ifc
->ifc_type
= SNMP_TYPE_TOKEN
;
1526 ifc
->ifc_type
= SNMP_TYPE_OTHER
;
1529 ifc
->ifc_start
= elapp
->ifThisCableStart
;
1530 ifc
->ifc_end
= elapp
->ifThisCableEnd
;
1531 ifc
->ifc_ddpAddr
= elapp
->ifThisNode
;
1532 ifc
->ifc_status
= elapp
->ifState
== LAP_ONLINE
? 1 : 2;
1533 ifc
->ifc_zoneName
.len
= 0;
1534 if (elapp
->ifZoneName
.len
!= 0) {
1535 ifc
->ifc_zoneName
= elapp
->ifZoneName
;
1537 else if (elapp
->ifDefZone
) {
1538 ifc
->ifc_zoneName
= ZT_table
[elapp
->ifDefZone
-1].Zone
;
1540 else /* temp, debug only */
1541 ifc
->ifc_zoneName
= ZT_table
[0].Zone
;
1543 if (elapp
->ifFlags
& RTR_SEED_PORT
) {
1544 ifc
->ifc_netCfg
= SNMP_CFG_CONFIGURED
;
1545 ifc
->ifc_zoneCfg
= SNMP_CFG_CONFIGURED
;
1548 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1549 ifc
->ifc_zoneCfg
= SNMP_CFG_GARNERED
;
1552 else { /* single-port mode */
1553 if (elapp
->ifRouterState
== ROUTER_AROUND
) {
1554 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1557 ifc
->ifc_netCfg
= SNMP_CFG_GUESSED
;
1558 ifc
->ifc_zoneCfg
= SNMP_CFG_UNCONFIG
;
1563 snmp
->cfg_flags
= at_state
.flags
;
1569 int at_reg_mcast(ifID
, data
)
1573 struct ifnet
*nddp
= ifID
->aa_ifp
;
1574 struct sockaddr_dl sdl
;
1578 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1582 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1585 /* this is for ether_output */
1586 bzero(&sdl
, sizeof(sdl
));
1587 sdl
.sdl_family
= AF_LINK
;
1588 sdl
.sdl_alen
= sizeof(struct etalk_addr
);
1589 sdl
.sdl_len
= offsetof(struct sockaddr_dl
, sdl_data
)
1590 + sizeof(struct etalk_addr
);
1591 bcopy(data
, sdl
.sdl_data
, sizeof(struct etalk_addr
));
1592 /* these next two lines should not really be needed XXX */
1593 sdl
.sdl_index
= nddp
->if_index
;
1594 sdl
.sdl_type
= IFT_ETHER
;
1596 dPrintf(D_M_PAT
, D_L_STARTUP
,
1597 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1598 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1601 if (if_addmulti(nddp
, &sdl
, 0))
1608 int at_unreg_mcast(ifID
, data
)
1612 struct ifnet
*nddp
= ifID
->aa_ifp
;
1613 struct sockaddr_dl sdl
;
1617 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1621 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1623 /* this is for ether_output */
1624 bzero(&sdl
, sizeof(sdl
));
1625 sdl
.sdl_family
= AF_LINK
;
1626 sdl
.sdl_alen
= sizeof(struct etalk_addr
);
1627 sdl
.sdl_len
= offsetof(struct sockaddr_dl
, sdl_data
)
1628 + sizeof(struct etalk_addr
);
1629 bcopy(data
, sdl
.sdl_data
, sizeof(struct etalk_addr
));
1630 /* these next two lines should not really be needed XXX */
1631 sdl
.sdl_index
= nddp
->if_index
;
1632 sdl
.sdl_type
= IFT_ETHER
;
1634 dPrintf(D_M_PAT
, D_L_STARTUP
,
1635 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1636 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1638 bzero(data
, sizeof(struct etalk_addr
));
1640 if (if_delmulti(nddp
, &sdl
))
1646 /* *** at_reg_mcast() and at_unreg_mcast() should be replaced as soon as the
1647 new code to allow an AF_LINK address family multicast to be (un)registered
1648 using the SIOCADDMULTI / SIOCDELMULTI ioctls has been completed.
1650 The issue is that the "struct sockaddr_dl" needed for the AF_LINK does not
1651 fit in the "struct ifreq" that is used for these ioctls, and we do not want
1652 Blue/Classic, which currently uses AF_UNSPEC, to use a different address
1653 family multicast address than Mac OS X uses.
1656 int at_reg_mcast(ifID
, data
)
1660 struct ifnet
*nddp
= ifID
->aa_ifp
;
1661 struct sockaddr_dl sdl
;
1665 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1668 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1671 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1672 sdl
.sdl_family
= AF_LINK
;
1674 sdl
.sdl_type
= nddp
->if_type
;
1675 sdl
.sdl_alen
= nddp
->if_addrlen
;
1677 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1678 nddp
->if_name
, nddp
->if_unit
);
1679 bcopy(data
, LLADDR(&sdl
), sdl
.sdl_alen
);
1681 dPrintf(D_M_PAT
, D_L_STARTUP
,
1682 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1683 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1686 if (if_addmulti(nddp
, (struct sockaddr
*)&sdl
, 0))
1693 int at_unreg_mcast(ifID
, data
)
1697 struct ifnet
*nddp
= ifID
->aa_ifp
;
1698 struct sockaddr_dl sdl
;
1702 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1706 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1708 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1709 sdl
.sdl_family
= AF_LINK
;
1711 sdl
.sdl_type
= nddp
->if_type
;
1712 sdl
.sdl_alen
= nddp
->if_addrlen
;
1714 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1715 nddp
->if_name
, nddp
->if_unit
);
1717 dPrintf(D_M_PAT
, D_L_STARTUP
,
1718 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1719 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1721 bzero(data
, ETHERNET_ADDR_LEN
);
1723 if (if_delmulti(nddp
, (struct sockaddr
*)&sdl
))