2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1988, 1989, 1993-1998 Apple Computer, Inc.
27 /* at_elap.c: 2.0, 1.29; 10/4/93; Apple Computer, Inc. */
29 /* This is the file which implements all the streams driver
30 * functionality required for EtherTalk.
35 03-14-94 jjs Changed all functions which assumed only one port would
36 ever be used. Added validate_msg_size, changed elap_online
37 to work with the h/w name only (e.g. 'et2').
39 Modified for MP, 1996 by Tuyen Nguyen
40 Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
44 #define RESOLVE_DBG /* for debug.h global resolution */
45 #include <sys/errno.h>
46 #include <sys/types.h>
47 #include <sys/param.h>
48 #include <machine/spl.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
52 #include <sys/filedesc.h>
53 #include <sys/fcntl.h>
55 #include <sys/ioctl.h>
56 #include <sys/socket.h>
57 #include <net/if_dl.h>
58 #include <sys/socketvar.h>
59 #include <sys/malloc.h>
60 #include <sys/domain.h>
61 #include <sys/sockio.h>
62 #include <vm/vm_kern.h> /* for kernel_map */
66 #include <net/if_types.h>
68 #include <netat/sysglue.h>
69 #include <netat/appletalk.h>
70 #include <netat/at_var.h>
71 #include <netat/ddp.h>
72 #include <netat/lap.h>
73 #include <netat/routing_tables.h> /* rtmp+zip table structs */
74 #include <netat/zip.h>
75 #include <netat/nbp.h>
76 #include <netat/at_snmp.h>
77 #include <netat/at_pcb.h>
78 #include <netat/at_aarp.h>
79 #include <netat/asp.h>
80 #include <netat/atp.h>
81 #include <netat/debug.h>
82 #include <netat/adsp.h>
83 #include <netat/adsp_internal.h>
85 #include <sys/kern_event.h>
89 at_ifaddr_t at_interfaces
[IF_TOTAL_MAX
];
90 /* index for at_interfaces is not important */
91 at_ifaddr_t
*ifID_table
[IF_TOTAL_MAX
];
92 /* the table of ifID structures, one per interface
94 * NOTE: for MH, entry 0 in this table is
95 * now defined to be the default I/F
97 at_ifaddr_t
*ifID_home
;
98 /* always ifID_table[IFID_HOME] for now, but will be used for
99 dynamic "home port" assignment, later */
101 at_state_t at_state
; /* global state of AT network */
102 snmpFlags_t snmpFlags
;
107 #define MAX_BUFSIZE 8192
108 #define MAX_RTMP (MAX_BUFSIZE/sizeof(RT_entry)-1)
110 ((MAX_BUFSIZE - SNMP_NBP_HEADER_SIZE)/sizeof(snmpNbpEntry_t)-1)
111 #define MAX_NBP_BYTES (MAX_NBP * sizeof(snmpNbpEntry_t))
112 #define MAX_ZIP (MAX_BUFSIZE/sizeof(ZT_entry)-1)
113 #define MAX_RTMP_BYTES (MAX_RTMP * sizeof(RT_entry))
114 #define MAX_ZIP_BYTES (MAX_ZIP * sizeof(ZT_entry))
117 extern TAILQ_HEAD(name_registry
, _nve_
) name_registry
;
118 extern snmpStats_t snmpStats
;
119 extern atlock_t ddpinp_lock
;
120 extern atlock_t arpinp_lock
;
121 extern short appletalk_inited
;
122 extern int adspInited
;
123 extern struct atpcb ddp_head
;
124 extern gref_t
*atp_inputQ
[];
125 extern struct atp_state
*atp_used_list
;
126 extern asp_scb_t
*asp_scbQ
[];
127 extern asp_scb_t
*scb_used_list
;
128 extern CCB
*adsp_inputQ
[];
129 extern CCB
*ccb_used_list
;
130 extern at_ddp_stats_t at_ddp_stats
;
131 extern lck_mtx_t
* atalk_mutex
;
134 extern snmpAarpEnt_t
* getAarp(int *);
135 extern void nbp_shutdown(), routershutdown(), ddp_brt_shutdown();
136 extern void ddp_brt_init(), rtmp_init(), rtmp_input();
137 extern rtmp_router_start(at_kern_err_t
*);
138 static void getIfNames(at_ifnames_t
*);
139 static void add_route();
140 static int set_zones();
142 static int elap_online1(), re_aarp();
143 int at_reg_mcast(), at_unreg_mcast();
144 void AARPwakeup(), ZIPwakeup();
145 static void elap_hangup();
148 at_ifaddr_t
*find_ifID(if_name
)
154 for (pat_id
=0; pat_id
< xpatcnt
; pat_id
++) {
155 if (!strcmp(at_interfaces
[pat_id
].ifName
, if_name
))
156 return(&at_interfaces
[pat_id
]);
159 return((at_ifaddr_t
*)NULL
);
162 static int validate_msg_size(m
, gref
, elapp
)
167 /* checks ioctl message type for minimum expected message size &
168 sends error back if size invalid
171 register ioc_t
*iocbp
;
172 register at_if_cfg_t
*cfgp
;
176 iocbp
= (ioc_t
*) gbuf_rptr(m
);
178 dPrintf(D_M_ELAP
, D_L_INFO
, ("validate_msg_size: ioc_cmd = %d\n",
180 switch (iocbp
->ioc_cmd
) {
181 case LAP_IOC_ADD_ROUTE
:
182 size
= sizeof(RT_entry
);
184 case LAP_IOC_GET_ROUTE
:
185 size
= sizeof(RT_entry
);
187 case LAP_IOC_GET_ZONE
:
188 size
= sizeof(ZT_entryno
);
190 case LAP_IOC_SNMP_GET_CFG
:
191 case LAP_IOC_SNMP_GET_AARP
:
192 case LAP_IOC_SNMP_GET_ZIP
:
193 case LAP_IOC_SNMP_GET_RTMP
:
194 case LAP_IOC_SNMP_GET_NBP
:
198 case ELAP_IOC_GET_STATS
:
199 case LAP_IOC_SNMP_GET_DDP
:
204 dPrintf(D_M_ELAP
, D_L_ERROR
, ("validate_msg_size: unknown ioctl\n"));
208 if (size
== 0) { /* a non-data ioctl */
212 if (gbuf_cont(m
) != NULL
)
213 i
= gbuf_len(gbuf_cont(m
));
214 if (iocbp
->ioc_count
< size
|| (gbuf_cont(m
) == NULL
) || i
< size
) {
215 dPrintf(D_M_ELAP
, D_L_ERROR
,
216 ("ioctl msg error:s:%d c:%d bcont:%c delta:%d\n",
217 size
, iocbp
->ioc_count
,
218 gbuf_cont(m
)? 'Y' : 'N', i
));
224 ioc_ack(EMSGSIZE
, m
, gref
);
226 } /* validate_msg_size */
228 int lap_online(elapp
, cfgp
)
234 if (elapp
->ifState
!= LAP_OFFLINE
) {
239 if (cfgp
->flags
& ELAP_CFG_HOME
) {
241 /* only 1 home allowed! */
244 dPrintf(D_M_ELAP
, D_L_STARTUP
,
245 ("elap_wput home I/F:%s\n", cfgp
->ifr_name
));
246 elapp
->flags
|= ELAP_CFG_HOME
;
249 if (MULTIPORT_MODE
) {
250 elapp
->flags
|= ELAP_CFG_ZONELESS
;
251 if (ROUTING_MODE
&& cfgp
->netStart
)
252 elapp
->flags
|= ELAP_CFG_SEED
;
255 if (!DEFAULT_ZONE(&cfgp
->zonename
) &&
256 (elapp
->flags
& ELAP_CFG_HOME
) || MULTIHOME_MODE
) {
257 elapp
->startup_zone
= cfgp
->zonename
;
260 if (elapp
->flags
& ELAP_CFG_SEED
) {
261 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
262 ("elap_wput: found to be seed\n"));
263 elapp
->ifThisCableStart
= cfgp
->netStart
;
264 elapp
->ifThisCableEnd
= cfgp
->netEnd
;
267 dPrintf(D_M_ELAP
,D_L_ERROR
,
268 ("elap_wput: we believe we're not seed\n"));
269 /* from ELAP_IOC_SET_CFG */
270 if (ATALK_VALUE(cfgp
->node
)) {
274 initial_node
= cfgp
->node
.s_node
;
275 initial_net
= cfgp
->node
.s_net
;
276 if ((initial_node
<0xfe) && (initial_node
>0) &&
277 !((initial_net
== 0) ||
278 ((initial_net
>= DDP_STARTUP_LOW
)&&
279 (initial_net
<= DDP_STARTUP_HIGH
)))) {
281 elapp
->initial_addr
= cfgp
->node
;
286 elapp
->startup_error
= 0;
287 elapp
->startup_inprogress
= FALSE
;
288 if ((error
= elap_online1(elapp
)))
291 if (!(MULTIPORT_MODE
) &&
292 elapp
->ifZoneName
.len
== 1 &&
293 elapp
->ifZoneName
.str
[0] == '*' &&
294 !DEFAULT_ZONE(&cfgp
->zonename
)) {
295 nbp_add_multicast(&cfgp
->zonename
, elapp
);
300 /***********************************************************************
303 **********************************************************************/
304 int elap_wput(gref
, m
)
309 register ioc_t
*iocbp
;
310 register at_if_cfg_t
*cfgp
;
311 at_elap_stats_t
*statsp
;
318 switch (gbuf_type(m
)) {
321 dPrintf(D_M_ELAP
,D_L_ERROR
,
322 ("Output data to control channel is ignored\n"));
326 iocbp
= (ioc_t
*) gbuf_rptr(m
);
328 if (validate_msg_size(m
, gref
, &elapp
))
332 cfgp
= (at_if_cfg_t
*) gbuf_rptr(gbuf_cont(m
));
334 if (LAP_IOC_MYIOCTL(iocbp
->ioc_cmd
) ||
335 ELAP_IOC_MYIOCTL(iocbp
->ioc_cmd
)) {
337 switch (iocbp
->ioc_cmd
) {
338 case ELAP_IOC_GET_STATS
:
339 #ifdef APPLETALK_DEBUG
340 kprintf("LAP_IOC_GET_STATS\n");
342 if ( (gbuf_cont(m
) == NULL
)
343 || (elapp
= find_ifID(gbuf_rptr(gbuf_cont(m
)))) == NULL
) {
344 ioc_ack(EINVAL
, m
, gref
);
347 gbuf_freem(gbuf_cont(m
));
348 if ((gbuf_cont(m
) =gbuf_alloc(sizeof(at_elap_stats_t
),
350 ioc_ack(ENOBUFS
, m
, gref
);
353 statsp
= ((at_elap_stats_t
*)gbuf_rptr(gbuf_cont(m
)));
354 *statsp
= elapp
->stats
;
355 gbuf_wset(gbuf_cont(m
),sizeof(at_elap_stats_t
));
356 iocbp
->ioc_count
= sizeof(at_elap_stats_t
);
360 case LAP_IOC_ADD_ROUTE
:
361 #ifdef APPLETALK_DEBUG
362 kprintf("LAP_IOC_ADD_ROUTE\n");
364 add_route((RT_entry
*)gbuf_rptr(gbuf_cont(m
)));
368 case LAP_IOC_GET_ZONE
:
369 #ifdef APPLETALK_DEBUG
370 kprintf("LAP_IOC_GET_ZONE\n");
372 /* return next ZT_entryno from ZT_table
373 a pointer to the struct ZT_entryno is passed down from
374 user space and the first byte is cast to a int, if
375 this int is non-zero, then the first ZT_entry is
376 returned and subsequent calls with a zero value
377 will return the next entry in the table. The next
378 read after the last valid entry will return EINVAL
383 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
384 gbuf_freem(gbuf_cont(m
));
387 pZTe
= zt_getNextZone(i
);
389 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(ZT_entryno
), PRI_MED
)) == NULL
) {
390 ioc_ack(ENOBUFS
, m
, gref
);
393 *(ZT_entryno
*)gbuf_rptr(gbuf_cont(m
)) = *pZTe
;
394 gbuf_wset(gbuf_cont(m
),sizeof(ZT_entryno
));
395 iocbp
->ioc_count
= sizeof(ZT_entryno
);
399 ioc_ack(EINVAL
, m
, gref
);
403 case LAP_IOC_GET_ROUTE
:
404 #ifdef APPLETALK_DEBUG
405 kprintf("LAP_IOC_GET_ROUTE\n");
407 /* return next RT_entry from RT_table
408 * a pointer to the struct RT_entry is
409 * passed down from user space and the first
410 * byte is cast to a int, if this int is
411 * non-zero, then the first RT_entry is
412 * returned and subsequent calls with a
413 * zero value will return the next entry in
414 * the table. The next read after the last
415 * valid entry will return EINVAL
420 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
421 gbuf_freem(gbuf_cont(m
));
424 pRT
= rt_getNextRoute(i
);
426 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(RT_entry
), PRI_MED
)) == NULL
) {
427 ioc_ack(ENOBUFS
, m
, gref
);
430 *(RT_entry
*)gbuf_rptr(gbuf_cont(m
)) = *pRT
;
431 gbuf_wset(gbuf_cont(m
),sizeof(RT_entry
));
432 iocbp
->ioc_count
= sizeof(RT_entry
);
436 ioc_ack(EINVAL
, m
, gref
);
440 case LAP_IOC_SNMP_GET_DDP
:
441 #ifdef APPLETALK_DEBUG
442 kprintf("LAP_IOC_SNMP_GET_DDP\n");
444 if (!(at_state
.flags
& AT_ST_STARTED
)) {
445 ioc_ack(ENOTREADY
, m
, gref
);
448 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(snmpStats_t
),
450 ioc_ack(ENOBUFS
, m
, gref
);
454 *(snmpStats_t
*)gbuf_rptr(gbuf_cont(m
)) = snmpStats
;
455 gbuf_wset(gbuf_cont(m
),sizeof(snmpStats
));
456 iocbp
->ioc_count
= sizeof(snmpStats
);
459 case LAP_IOC_SNMP_GET_CFG
:
460 #ifdef APPLETALK_DEBUG
461 kprintf("LAP_IOC_SNMP_GET_CFG\n");
467 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
468 gbuf_freem(gbuf_cont(m
));
470 if (!(at_state
.flags
& AT_ST_STARTED
)) {
472 iocbp
->ioc_count
= 0;
473 ioc_ack(ENOTREADY
, m
, gref
);
474 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
475 ("elap_wput: cfg req, stack down\n"));
478 if (i
== UPDATE_IF_CHANGED
&&
479 !(at_state
.flags
& AT_ST_IF_CHANGED
)) {
480 iocbp
->ioc_count
= 0;
482 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
483 ("elap_wput: cfg req, unchanged\n"));
486 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
487 ("elap_wput: cfg req, changed\n"));
489 if (getSnmpCfg(&snmp
)) {
490 dPrintf(D_M_ELAP
,D_L_ERROR
,
491 ("elap_wput:SNMP_GET_CFG error\n"));
492 ioc_ack(EOPNOTSUPP
, m
, gref
);
495 /* send up only used part of table */
496 size
= sizeof(snmp
) -
497 sizeof(snmpIfCfg_t
) * (MAX_IFS
- snmp
.cfg_ifCnt
);
499 if ((gbuf_cont(m
) = gbuf_alloc(size
, PRI_MED
)) == NULL
) {
500 ioc_ack(ENOBUFS
, m
, gref
);
503 bcopy(&snmp
,gbuf_rptr(gbuf_cont(m
)),size
);
504 gbuf_wset(gbuf_cont(m
),size
);
505 iocbp
->ioc_count
= size
;
506 at_state
.flags
&= ~AT_ST_IF_CHANGED
;
511 case LAP_IOC_SNMP_GET_AARP
:
513 snmpAarpEnt_t
*snmpp
;
515 #ifdef APPLETALK_DEBUG
516 kprintf("LAP_IOC_SNMP_GET_AARP\n");
518 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
519 gbuf_freem(gbuf_cont(m
));
521 dPrintf(D_M_ELAP
,D_L_INFO
,
522 ("elap_wput:calling getarp,i=%d\n", i
));
524 bytes
= i
* sizeof(snmpAarpEnt_t
);
525 dPrintf(D_M_ELAP
,D_L_INFO
,
526 ("elap_wput:getarp returned, i=%d,bytes=%d\n",
529 if ((gbuf_cont(m
) = gbuf_alloc(bytes
, PRI_MED
)) == NULL
) {
530 ioc_ack(ENOBUFS
, m
, gref
);
533 bcopy(snmpp
, gbuf_rptr(gbuf_cont(m
)), bytes
);
534 gbuf_wset(gbuf_cont(m
),bytes
);
535 iocbp
->ioc_count
= bytes
;
539 ioc_ack(EOPNOTSUPP
, m
, gref
);
543 case LAP_IOC_SNMP_GET_ZIP
:
544 #ifdef APPLETALK_DEBUG
545 kprintf("LAP_IOC_SNMP_GET_ZIP\n");
547 { /* matching brace NOT in this case */
549 register int size
, total
, tabsize
;
550 gbuf_t
*mn
; /* new gbuf */
551 gbuf_t
*mo
; /* old gbuf */
552 gbuf_t
*mt
; /* temp */
555 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
556 gbuf_freem(gbuf_cont(m
));
558 if (!(at_state
.flags
& AT_ST_STARTED
)) {
559 ioc_ack(ENOTREADY
, m
, gref
);
562 if (i
== UPDATE_IF_CHANGED
&&
563 !(at_state
.flags
& AT_ST_ZT_CHANGED
)) {
564 iocbp
->ioc_count
= 0;
569 tabsize
= getZipTableSize();
571 /* retrieve table into multiple gbufs */
572 for (i
=0; i
<tabsize
; i
+=j
) {
574 MAX_ZIP
? MAX_ZIP
: tabsize
- i
;
575 size
= j
< MAX_ZIP
? sizeof(ZT_entry
)*j
: MAX_ZIP_BYTES
;
576 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
578 gbuf_freem(gbuf_cont(m
));
579 ioc_ack(ENOBUFS
, m
, gref
);
582 if (!mo
) { /* if first new one */
591 getZipTable((ZT_entry
*)gbuf_rptr(mn
),i
,j
);
594 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
597 iocbp
->ioc_count
= 0;
598 ioc_ack(ENOBUFS
, m
, gref
);
602 dPrintf(D_M_ELAP
,D_L_WARNING
,
603 ("elap_wput:snmp: empty zip table\n"));
606 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
607 gbuf_wset(gbuf_cont(m
),sizeof(int));
608 iocbp
->ioc_count
= sizeof(int);
611 atalk_putnext(gref
,mt
); /* send up table */
612 at_state
.flags
&= ~AT_ST_ZT_CHANGED
;
615 case LAP_IOC_SNMP_GET_RTMP
:
616 #ifdef APPLETALK_DEBUG
617 kprintf("LAP_IOC_SNMP_GET_RTMP\n");
619 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
620 gbuf_freem(gbuf_cont(m
));
622 if (!(at_state
.flags
& AT_ST_STARTED
)) {
623 ioc_ack(ENOTREADY
, m
, gref
);
626 if (i
== UPDATE_IF_CHANGED
&&
627 !(at_state
.flags
& AT_ST_RT_CHANGED
)) {
628 iocbp
->ioc_count
= 0;
634 tabsize
= getRtmpTableSize();
636 /* retrieve table into multiple gbufs */
637 for (i
=0; i
<tabsize
; i
+=j
) {
639 MAX_RTMP
? MAX_RTMP
: tabsize
- i
;
640 size
= j
< MAX_RTMP
? sizeof(RT_entry
)*j
: MAX_RTMP_BYTES
;
641 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
643 gbuf_freem(gbuf_cont(m
));
644 ioc_ack(ENOBUFS
, m
, gref
);
647 if (!mo
) { /* if first new one */
656 getRtmpTable((RT_entry
*)gbuf_rptr(mn
),i
,j
);
659 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
662 iocbp
->ioc_count
= 0;
663 ioc_ack(ENOBUFS
, m
, gref
);
668 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
669 gbuf_wset(gbuf_cont(m
),sizeof(int));
670 iocbp
->ioc_count
= sizeof(int);
673 atalk_putnext(gref
,mt
); /* send up table */
674 at_state
.flags
&= ~AT_ST_RT_CHANGED
;
677 case LAP_IOC_SNMP_GET_NBP
:
678 #ifdef APPLETALK_DEBUG
679 kprintf("LAP_IOC_SNMP_GET_NBP\n");
681 i
= *(int *)gbuf_rptr(gbuf_cont(m
));
682 gbuf_freem(gbuf_cont(m
));
684 if (!(at_state
.flags
& AT_ST_STARTED
)) {
685 ioc_ack(ENOTREADY
, m
, gref
);
688 if (i
== UPDATE_IF_CHANGED
&&
689 !(at_state
.flags
& AT_ST_NBP_CHANGED
)) {
690 iocbp
->ioc_count
= 0;
692 dPrintf(D_M_ELAP_LOW
, D_L_INFO
,
693 ("elap_wput: nbp req denied, no change\n"));
698 tabsize
= getNbpTableSize();
700 /* retrieve table into multiple gbufs */
701 for (i
=0; i
<tabsize
; i
+=j
) {
703 MAX_NBP
? MAX_NBP
: tabsize
- i
;
704 size
= j
< MAX_NBP
? sizeof(snmpNbpEntry_t
)*j
: MAX_NBP_BYTES
;
706 size
+= SNMP_NBP_HEADER_SIZE
;
707 if ((mn
= gbuf_alloc(size
, PRI_MED
)) == NULL
) {
709 gbuf_freem(gbuf_cont(m
));
710 ioc_ack(ENOBUFS
, m
, gref
);
713 if (!mo
) { /* if first new one */
716 nbp
= (snmpNbpTable_t
*)gbuf_rptr(mn
);
717 nbp
->nbpt_entries
= tabsize
;
718 nbp
->nbpt_zone
= ifID_home
->ifZoneName
;
719 getNbpTable(nbp
->nbpt_table
,i
,j
);
724 getNbpTable((snmpNbpEntry_t
*)gbuf_rptr(mn
),i
,j
);
729 if ((gbuf_cont(m
) = gbuf_alloc(sizeof(int), PRI_MED
)) == NULL
) {
732 iocbp
->ioc_count
= 0;
733 ioc_ack(ENOBUFS
, m
, gref
);
738 *(int*)gbuf_rptr(gbuf_cont(m
)) = total
; /* return table size */
739 gbuf_wset(gbuf_cont(m
),sizeof(int));
740 iocbp
->ioc_count
= sizeof(int);
743 atalk_putnext(gref
,mt
); /* send up table */
744 at_state
.flags
&= ~AT_ST_NBP_CHANGED
;
749 #ifdef APPLETALK_DEBUG
750 kprintf("unknown ioctl %d\n", iocbp
->ioc_cmd
);
752 ioc_ack(ENOTTY
, m
, gref
);
753 dPrintf(D_M_ELAP
, D_L_WARNING
,
754 ("elap_wput: unknown ioctl (%d)\n", iocbp
->ioc_cmd
));
757 elapp
->stats
.unknown_mblks
++;
772 /* Called directly by ddp/zip.
774 elap_dataput(m
, elapp
, addr_flag
, addr
)
776 register at_ifaddr_t
*elapp
;
782 extern int zip_type_packet();
783 struct etalk_addr dest_addr
;
784 struct atalk_addr dest_at_addr
;
785 extern gbuf_t
*growmsg();
787 /* flag to aarp to loopback (default) */
789 /* the incoming frame is of the form {flag, address, ddp...}
790 * where "flag" indicates whether the address is an 802.3
791 * (link) address, or an appletalk address. If it's an
792 * 802.3 address, the packet can just go out to the network
793 * through PAT, if it's an appletalk address, AT->802.3 address
794 * resolution needs to be done.
795 * If 802.3 address is known, strip off the flag and 802.3
796 * address, and prepend 802.2 and 802.3 headers.
800 addr_flag
= *(u_char
*)gbuf_rptr(m
);
805 case AT_ADDR_NO_LOOP
:
810 dest_at_addr
= *(struct atalk_addr
*)gbuf_rptr(m
);
811 gbuf_rinc(m
,sizeof(struct atalk_addr
));
813 dest_at_addr
= *(struct atalk_addr
*)addr
;
817 dest_addr
= *(struct etalk_addr
*)gbuf_rptr(m
);
818 gbuf_rinc(m
,sizeof(struct etalk_addr
));
820 dest_addr
= *(struct etalk_addr
*)addr
;
823 gbuf_freel(m
); /* unknown address type, chuck it */
829 /* At this point, rptr points to ddp header for sure */
830 if (elapp
->ifState
== LAP_OFFLINE
) {
835 if (elapp
->ifState
== LAP_ONLINE_FOR_ZIP
) {
836 /* see if this is a ZIP packet that we need
837 * to let through even though network is
840 if (zip_type_packet(m
) == 0) {
846 elapp
->stats
.xmit_packets
++;
847 size
= gbuf_msgsize(m
);
848 elapp
->stats
.xmit_bytes
+= size
;
849 snmpStats
.dd_outLong
++;
852 case AT_ADDR_NO_LOOP
:
855 * we don't want elap to be looking into ddp header, so
856 * it doesn't know net#, consequently can't do
857 * AMT_LOOKUP. That task left to aarp now.
859 error
= aarp_send_data(m
,elapp
,&dest_at_addr
, loop
);
862 error
= pat_output(elapp
, m
, &dest_addr
, 0);
868 /************************************************************************
871 ************************************************************************/
873 static int elap_online1(elapp
)
878 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online:%s elapp:0x%x\n",
879 (elapp
->ifName
) ? &elapp
->ifName
[0] : "NULL interface", (u_int
) elapp
));
880 if (elapp
->ifState
!= LAP_OFFLINE
|| elapp
->startup_inprogress
== TRUE
)
883 at_state
.flags
|= AT_ST_IF_CHANGED
;
885 if (elapp
->flags
& ELAP_CFG_HOME
) /* tell ddp_add_if if this is home */
886 elapp
->ifFlags
|= AT_IFF_DEFAULT
;
888 /* Get DDP started */
889 if ((errno
= ddp_add_if(elapp
)))
892 // check if we still have an interface - can be lost when
893 // ddp_add_if calls malloc
894 // need to make check here after ddp_add_if completes because
895 // lap_online will call ddp_rem_if if we fail here
896 if (elapp
->aa_ifp
== 0)
899 /* set up multicast address for cable-wide broadcasts */
900 (void)at_reg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
902 // need to check again if interface is present
903 // can be lost in at_reg_mcast
904 if (elapp
->aa_ifp
== 0)
907 elapp
->startup_inprogress
= TRUE
;
908 if (! (elapp
->startup_error
= re_aarp(elapp
))) {
909 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
910 (void)msleep(&elapp
->startup_inprogress
, atalk_mutex
, PSOCK
| PCATCH
,
914 /* then later, after some timeouts AARPwakeup() is called */
916 return(elapp
->startup_error
);
919 static int re_aarp(elapp
)
924 /* We now call aarp_init() to assign an appletalk node addr */
925 errno
= aarp_init1(elapp
);
926 /* aarp_init1() returns either -1 or ENOTREADY */
927 if (errno
== ENOTREADY
)
930 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
931 ("elap_online aarp_init for %s\n", elapp
->ifName
));
932 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
934 elapp
->ifState
= LAP_OFFLINE
;
935 return(EADDRNOTAVAIL
);
939 /* called from AARPwakeup */
940 static void elap_online2(elapp
)
943 if (MULTIPORT_MODE
) {
944 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
945 ("elap_online: re_aarp, we know it's a router...\n"));
947 if (elapp
->flags
& ELAP_CFG_SEED
) {
948 /* add route table entry (zones to be added later) */
949 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
950 ("elap_online: rt_insert Cable %d-%d port =%d as SEED\n",
951 elapp
->ifThisCableStart
, elapp
->ifThisCableEnd
, elapp
->ifPort
));
952 rt_insert(elapp
->ifThisCableEnd
,
953 elapp
->ifThisCableStart
,
956 RTE_STATE_PERMANENT
| RTE_STATE_ZKNOWN
| RTE_STATE_GOOD
958 /* LD 081694: set the RTR_SEED_PORT flag for seed ports */
959 elapp
->ifFlags
|= RTR_SEED_PORT
;
962 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
963 ("elap_online: it's a router, but non seed\n"));
966 if (elapp
->flags
& ELAP_CFG_ZONELESS
) {
967 /* ELAP_CFG_ZONELESS tells us that it is a router or in
968 multihome mode, so we don't want to do the GetNetInfo
969 exchange with the router. */
971 elapp
->ifState
= LAP_ONLINE_ZONELESS
;
972 elapp
->startup_inprogress
= FALSE
;
973 wakeup(&elapp
->startup_inprogress
);
974 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online: ack 3\n"));
978 /* if we don't already have a zone and a multicast address */
979 if (*(int *)&elapp
->ZoneMcastAddr
== 0 || elapp
->ifZoneName
.len
== 0) {
980 /* hzonehash is a global containing the nbp hash for the startup_zone */
983 /* Get ZIP rolling to get zone multicast address, etc. */
984 elapp
->ifState
= LAP_ONLINE_FOR_ZIP
;
985 (void)zip_control(elapp
, ZIP_ONLINE
);
986 /* zip_control (w. control == ZIP_ONLINE) always returns ENOTREADY */
988 /* later, after some timeouts ZIPwakeup() is called. */
990 /* otherwise, we have the zone and the multicast already,
991 so don't bother with another ZIP GetNetInfo request */
996 /* called from rtmp_router_start */
997 int elap_online3(elapp
)
1000 elapp
->startup_inprogress
= TRUE
;
1002 /* just reset the net range */
1003 elapp
->initial_addr
.s_net
= 0;
1004 elapp
->initial_addr
.s_node
= 0;
1005 dPrintf(D_M_ELAP_LOW
, D_L_STARTUP_INFO
,
1006 ("elap_online: goto re_aarp port=%d\n", elapp
->ifPort
));
1008 if ((elapp
->startup_error
= re_aarp(elapp
)))
1009 return(elapp
->startup_error
);
1011 /* then later, after some timeouts AARPwakeup() is called */
1013 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
1014 (void)msleep(&elapp
->startup_inprogress
, atalk_mutex
, PSOCK
| PCATCH
,
1016 return(elapp
->startup_error
);
1017 } /* elap_online3 */
1019 /****************************************************************************
1022 ****************************************************************************/
1024 void elap_offline(elapp
)
1025 register at_ifaddr_t
*elapp
;
1028 void zip_sched_getnetinfo(); /* forward reference */
1032 dPrintf(D_M_ELAP
, D_L_SHUTDN_INFO
, ("elap_offline:%s\n", elapp
->ifName
));
1033 if (elapp
->ifState
!= LAP_OFFLINE
) {
1035 /* Since AppleTalk is going away, remove the cable
1036 * multicast address and turn the interface off so that all
1037 * AppleTalk packets are dropped in the driver itself.
1038 * Get rid of the zone multicast address prior to going Offline.
1040 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->ZoneMcastAddr
);
1041 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
1042 elapp
->ifState
= LAP_OFFLINE
;
1044 ATDISABLE(s
, ddpinp_lock
);
1046 RT_DELETE(elapp
->ifThisCableEnd
,
1047 elapp
->ifThisCableStart
);
1048 ATENABLE(s
, ddpinp_lock
);
1050 /* make sure no zip timeouts are left running */
1051 elapp
->ifGNIScheduled
= 0;
1052 untimeout(zip_sched_getnetinfo
, elapp
);
1055 } /* elap_offline */
1058 static void add_route(rt
)
1061 /* support ioctl to manually add routes to table.
1062 this is really only for testing
1065 rt_insert( rt
->NetStop
, rt
->NetStart
, rt
->NextIRNet
,
1066 rt
->NextIRNode
, rt
->NetDist
, rt
->NetPort
,
1068 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("adding route: %ud:%ud dist:%ud\n",
1069 rt
->NetStart
, rt
->NetStop
,rt
->NetDist
));
1075 * Initialization that takes place each time AppleTalk is restarted.
1080 TAILQ_INIT(&at_ifQueueHd
);
1081 TAILQ_INIT(&name_registry
);
1082 bzero(at_interfaces
, sizeof(at_interfaces
));
1083 bzero(ifID_table
, sizeof(ifID_table
));
1084 bzero(&at_ddp_stats
, sizeof(at_ddp_stats_t
));
1085 rtmp_init(); /* initialize trackedrouters */
1087 add_ddp_handler(RTMP_SOCKET
, rtmp_input
);
1088 ifID_home
= (at_ifaddr_t
*)NULL
;
1092 int ddp_shutdown(count_only
)
1096 asp_scb_t
*scb
, *scb_next
;
1097 struct atp_state
*atp
, *atp_next
;
1100 vm_offset_t temp_rcb_data
, temp_state_data
;
1101 int i
, s
, active_skts
= 0; /* count of active pids for non-socketized
1102 AppleTalk protocols */
1104 /* Network is shutting down... send error messages up on each open
1106 *** For now, for ASP, ATP and ADSP, attempt to notify open
1107 sockets, but return EBUSY and don't complete shutdown. ***
1110 s
= splimp(); /* *** previously contained mismatched locking
1111 that was ifdef'ed to splimp() *** */
1113 nbp_shutdown(); /* clear all known NVE */
1116 for (scb
= scb_used_list
; scb
; ) {
1117 scb_next
= scb
->next_scb
;
1120 dPrintf(D_M_ASP
, D_L_TRACE
, ("asp pid=%d\n", scb
->pid
));
1121 atalk_notify(scb
->gref
, ESHUTDOWN
);
1125 for (i
= 0; i
< 256 ; i
++) {
1126 if ((scb
= asp_scbQ
[i
]))
1128 scb_next
= scb
->next_scb
;
1131 dPrintf(D_M_ASP
, D_L_TRACE
,
1132 ("asp pid=%d\n", scb
->pid
));
1133 atalk_notify(scb
->gref
, ESHUTDOWN
);
1140 for (atp
= atp_used_list
; atp
; ) {
1141 atp_next
= atp
->atp_trans_waiting
;
1144 dPrintf(D_M_ATP
, D_L_TRACE
, ("atp pid=%d\n", atp
->atp_pid
));
1145 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1149 for (i
= 0; i
< 256; i
++) {
1150 if ((gref
= atp_inputQ
[i
]) && (gref
!= (gref_t
*)1)) {
1151 atp
= (struct atp_state
*)gref
->info
;
1155 dPrintf(D_M_ATP
, D_L_TRACE
,
1156 ("atp pid=%d\n", atp
->atp_pid
));
1157 atalk_notify(atp
->atp_gref
, ESHUTDOWN
);
1164 for (sp
= ccb_used_list
; sp
; ) {
1165 sp_next
= sp
->otccbLink
;
1168 dPrintf(D_M_ADSP
, D_L_TRACE
, ("adsp pid=%d\n", sp
->pid
));
1169 atalk_notify(sp
->gref
, ESHUTDOWN
);
1173 for (i
= 0; i
< 256 ; i
++) {
1174 if ((sp
= adsp_inputQ
[i
]))
1176 sp_next
= sp
->otccbLink
;
1179 dPrintf(D_M_ADSP
, D_L_TRACE
,
1180 ("adsp pid=%d\n", sp
->pid
));
1181 atalk_notify(sp
->gref
, ESHUTDOWN
);
1188 for (gref
= ddp_head
.atpcb_next
; gref
!= &ddp_head
;
1189 gref
= gref
->atpcb_next
) {
1193 dPrintf(D_M_DDP
,D_L_TRACE
, ("ddp pid=%d\n", gref
->pid
));
1194 atalk_notify(gref
, ESHUTDOWN
);
1197 if (count_only
|| active_skts
) {
1199 return(active_skts
);
1202 /* if there are no interfaces in the process of going online, continue shutting down DDP */
1203 for (i
= 0; i
< IF_TOTAL_MAX
; i
++) {
1204 if (at_interfaces
[i
].startup_inprogress
== TRUE
)
1207 if (MULTIPORT_MODE
) {
1209 /* free memory allocated for the rtmp/zip tables */
1211 FREE(ZT_table
, M_RTABLE
);
1212 ZT_table
= (ZT_entry
*)NULL
;
1215 FREE(RT_table
, M_RTABLE
);
1216 RT_table
= (RT_entry
*)NULL
;
1220 at_state
.flags
= 0; /* make sure inits are done on restart */
1222 wakeup(&ifID_home
->startup_inprogress
); /* if rtmp_router_start still starting up */
1224 /* from original ddp_shutdown() */
1234 dPrintf(D_M_DDP
, D_L_VERBOSE
, ("DDP shutdown completed"));
1237 * make sure we don't have a probe timeout hanging around
1238 * it's going to try and make use of an entry in at_interfaces
1239 * which is going to be zero'd out by the call to ddp_start a
1240 * little further down
1242 untimeout(aarp_sched_probe
, 0);
1244 /* *** after an SIOCSIFADDR and before an AIOCSIFADDR,
1245 this is the only place to find the ifID *** */
1246 for (i
= 0; i
< IF_TOTAL_MAX
; i
++) {
1247 ifID
= &at_interfaces
[i
];
1248 /* do LAP_IOC_OFFLINE processing */
1255 } /* ddp_shutdown */
1257 int routerStart(keP
)
1260 register at_ifaddr_t
*ifID
;
1268 * this will cause the ports to glean from the net the relevant
1269 * information before forwarding
1271 TAILQ_FOREACH(ifID
, &at_ifQueueHd
, aa_link
) {
1272 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1273 ("routerStart Port %d (%s) set to activating\n",
1274 ifID
->ifPort
, ifID
->ifName
));
1275 ifID
->ifRoutingState
= PORT_ACTIVATING
;
1276 ifID
->ifFlags
|= RTR_XNET_PORT
;
1280 * The next step is to check the information for each port before
1281 * declaring the ports up and forwarding
1283 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1284 ("router_start: waiting 20 sec before starting up\n"));
1286 lck_mtx_assert(atalk_mutex
, LCK_MTX_ASSERT_OWNED
);
1287 /* sleep for 20 seconds */
1289 /* the vaue of 10n terms of hz is 100ms */
1294 /* *** eventually this will be the ifID for the interface
1295 being brought up in router mode *** */
1296 msleep(&ifID_home
->startup_inprogress
, atalk_mutex
,
1297 PSOCK
| PCATCH
, "routerStart", &ts
))
1301 panic("routerStart: spurious interrupt");
1306 return(rtmp_router_start(keP
));
1307 /* was timeout(rtmp_router_start, 0, 20 * SYS_HZ); */
1310 void ZIPwakeup(elapp
, ZipError
)
1314 int s
, error
= ZipError
;
1316 ATDISABLE(s
, ddpinp_lock
);
1317 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
) {
1318 ATENABLE(s
, ddpinp_lock
);
1320 /* was ZIPContinue */
1321 /* was elapp_online() with jump to ZIP_sleep */
1323 /* instead of the goto ZIP_sleep ... */
1325 case 0 : /* success */
1326 elapp
->ifState
= LAP_ONLINE
;
1328 /* Send event with zone info. */
1329 atalk_post_msg(elapp
->aa_ifp
, KEV_ATALK_ZONEUPDATED
, 0, &(elapp
->ifZoneName
));
1333 /* instead of goto re_aarp; */
1334 /* We now call aarp_init() to assign an
1335 appletalk node addr */
1336 if ((elapp
->startup_error
= re_aarp(elapp
))) {
1337 elapp
->startup_inprogress
= FALSE
;
1338 wakeup(&elapp
->startup_inprogress
);
1339 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1340 ("elap_online: ack 2\n"));
1346 if (ZipError
!= ZIP_RE_AARP
) {
1347 elapp
->startup_error
= error
;
1348 elapp
->startup_inprogress
= FALSE
;
1349 wakeup(&elapp
->startup_inprogress
);
1350 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
,
1351 ("elap_online: ifZipError=%d\n", error
));
1354 ATENABLE(s
, ddpinp_lock
);
1357 void AARPwakeup(probe_cb
)
1358 aarp_amt_t
*probe_cb
;
1364 ATDISABLE(s
, arpinp_lock
);
1365 elapp
= probe_cb
->elapp
;
1366 if ( (elapp
!= NULL
) && elapp
->startup_inprogress
&& elapp
->aa_ifp
!= 0) {
1367 ATENABLE(s
, arpinp_lock
);
1369 /* was AARPContinue */
1370 errno
= aarp_init2(elapp
);
1371 /* aarp_init2() returns either -1 or 0 */
1373 dPrintf(D_M_ELAP
, D_L_STATE_CHG
,
1374 ("elap_online aarp_init for %s\n",
1376 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->ZoneMcastAddr
);
1377 (void)at_unreg_mcast(elapp
, (caddr_t
)&elapp
->cable_multicast_addr
);
1378 elapp
->ifState
= LAP_OFFLINE
;
1380 elapp
->startup_error
= EADDRNOTAVAIL
;
1381 elapp
->startup_inprogress
= FALSE
;
1382 wakeup(&elapp
->startup_inprogress
);
1383 dPrintf(D_M_ELAP
, D_L_STARTUP_INFO
, ("elap_online: ack 2\n"));
1385 dPrintf(D_M_ELAP
,D_L_STARTUP_INFO
,
1386 ("elap_online: aarp_init returns zero\n"));
1387 elap_online2(elapp
);
1390 ATENABLE(s
, arpinp_lock
);
1393 void ddp_bit_reverse(addr
)
1394 unsigned char *addr
;
1396 static unsigned char reverse_data
[] = {
1397 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1398 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1399 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1400 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1401 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1402 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1403 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1404 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1405 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1406 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1407 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1408 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1409 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1410 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1411 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1412 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1413 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1414 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1415 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1416 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1417 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1418 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1419 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1420 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1421 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1422 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1423 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1424 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1425 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1426 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1427 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1428 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1433 for (k
=0; k
< 6; k
++)
1434 addr
[k
] = reverse_data
[addr
[k
]];
1437 static int elap_trackMcast(patp
, func
, addr
)
1444 switch(patp
->aa_ifp
->if_type
) {
1448 case IFT_IEEE8023ADLAG
: /* bonded ethernet */
1449 /* set addr to point to unique part of addr */
1452 /* first try to find match */
1453 /* *** save just one byte of the multicast address? *** */
1454 for (i
=0; i
< MAX_MCASTS
; i
++)
1455 if (c
== patp
->mcast
[i
]) {
1461 case MCAST_TRACK_DELETE
:
1463 patp
->mcast
[loc
] = 0;
1466 case MCAST_TRACK_ADD
:
1467 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add loc:%d\n", i
));
1469 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was there\n"));
1471 break; /* already there */
1473 for (i
=0; i
< MAX_MCASTS
; i
++)
1474 if (patp
->mcast
[i
] == 0) {
1478 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add1 loc:%d\n", i
));
1480 patp
->mcast
[loc
] = c
;
1481 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, adding(%x)\n",
1482 (*(int*)addr
)&0xffffff));
1485 /*errno = ENOMEM; */ /*LD 5/7/97 nobody is using that */
1489 case MCAST_TRACK_CHECK
:
1491 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:check, addr was there\n"));
1495 dPrintf(D_M_PAT_LOW
, D_L_USR2
, ("mctrack:add, addr was NOT there\n"));
1500 /*errno = EINVAL;*/ /*LD 5/7/97 nobody is using that */
1504 case IFT_ISO88025
: /* token ring */
1505 /* we would use the lowest byte of the addr argument as a value
1506 to shift left a 1 to form the mcast mask for TR. We'll do this
1516 static getSnmpCfg(snmp
)
1523 snmp
->cfg_ifCnt
= 0;
1525 bzero(snmp
,sizeof(snmpCfg_t
));
1526 for (i
=0, elapp
=at_interfaces
,ifc
=snmp
->cfg_ifCfg
;
1527 i
<IF_TOTAL_MAX
; i
++, elapp
++, ifc
++) {
1528 if (elapp
->ifState
!= LAP_OFFLINE
) {
1530 strncpy(ifc
->ifc_name
,elapp
->ifName
, sizeof(ifc
->ifc_name
));
1531 ifc
->ifc_aarpSize
= getAarpTableSize(i
);
1532 ifc
->ifc_addrSize
= getPhysAddrSize(i
);
1533 switch (elapp
->aa_ifp
->if_type
) {
1536 case IFT_IEEE8023ADLAG
: /* bonded ethernet */
1537 ifc
->ifc_type
= SNMP_TYPE_ETHER2
;
1539 case IFT_ISO88025
: /* token ring */
1540 ifc
->ifc_type
= SNMP_TYPE_TOKEN
;
1544 ifc
->ifc_type
= SNMP_TYPE_OTHER
;
1547 ifc
->ifc_start
= elapp
->ifThisCableStart
;
1548 ifc
->ifc_end
= elapp
->ifThisCableEnd
;
1549 ifc
->ifc_ddpAddr
= elapp
->ifThisNode
;
1550 ifc
->ifc_status
= elapp
->ifState
== LAP_ONLINE
? 1 : 2;
1551 ifc
->ifc_zoneName
.len
= 0;
1552 if (elapp
->ifZoneName
.len
!= 0) {
1553 ifc
->ifc_zoneName
= elapp
->ifZoneName
;
1555 else if (elapp
->ifDefZone
) {
1556 ifc
->ifc_zoneName
= ZT_table
[elapp
->ifDefZone
-1].Zone
;
1558 else /* temp, debug only */
1559 ifc
->ifc_zoneName
= ZT_table
[0].Zone
;
1561 if (elapp
->ifFlags
& RTR_SEED_PORT
) {
1562 ifc
->ifc_netCfg
= SNMP_CFG_CONFIGURED
;
1563 ifc
->ifc_zoneCfg
= SNMP_CFG_CONFIGURED
;
1566 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1567 ifc
->ifc_zoneCfg
= SNMP_CFG_GARNERED
;
1570 else { /* single-port mode */
1571 if (elapp
->ifRouterState
== ROUTER_AROUND
) {
1572 ifc
->ifc_netCfg
= SNMP_CFG_GARNERED
;
1575 ifc
->ifc_netCfg
= SNMP_CFG_GUESSED
;
1576 ifc
->ifc_zoneCfg
= SNMP_CFG_UNCONFIG
;
1581 snmp
->cfg_flags
= at_state
.flags
;
1587 int at_reg_mcast(ifID
, data
)
1591 struct ifnet
*nddp
= ifID
->aa_ifp
;
1592 struct sockaddr_dl sdl
;
1596 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1600 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1603 /* this is for ether_output */
1604 bzero(&sdl
, sizeof(sdl
));
1605 sdl
.sdl_family
= AF_LINK
;
1606 sdl
.sdl_alen
= sizeof(struct etalk_addr
);
1607 sdl
.sdl_len
= offsetof(struct sockaddr_dl
, sdl_data
)
1608 + sizeof(struct etalk_addr
);
1609 bcopy(data
, sdl
.sdl_data
, sizeof(struct etalk_addr
));
1610 /* these next two lines should not really be needed XXX */
1611 sdl
.sdl_index
= nddp
->if_index
;
1612 sdl
.sdl_type
= IFT_ETHER
;
1614 dPrintf(D_M_PAT
, D_L_STARTUP
,
1615 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1616 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1619 if (if_addmulti(nddp
, &sdl
, 0))
1626 int at_unreg_mcast(ifID
, data
)
1630 struct ifnet
*nddp
= ifID
->aa_ifp
;
1631 struct sockaddr_dl sdl
;
1635 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1639 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1641 /* this is for ether_output */
1642 bzero(&sdl
, sizeof(sdl
));
1643 sdl
.sdl_family
= AF_LINK
;
1644 sdl
.sdl_alen
= sizeof(struct etalk_addr
);
1645 sdl
.sdl_len
= offsetof(struct sockaddr_dl
, sdl_data
)
1646 + sizeof(struct etalk_addr
);
1647 bcopy(data
, sdl
.sdl_data
, sizeof(struct etalk_addr
));
1648 /* these next two lines should not really be needed XXX */
1649 sdl
.sdl_index
= nddp
->if_index
;
1650 sdl
.sdl_type
= IFT_ETHER
;
1652 dPrintf(D_M_PAT
, D_L_STARTUP
,
1653 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1654 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1656 bzero(data
, sizeof(struct etalk_addr
));
1658 if (if_delmulti(nddp
, &sdl
))
1664 /* *** at_reg_mcast() and at_unreg_mcast() should be replaced as soon as the
1665 new code to allow an AF_LINK address family multicast to be (un)registered
1666 using the SIOCADDMULTI / SIOCDELMULTI ioctls has been completed.
1668 The issue is that the "struct sockaddr_dl" needed for the AF_LINK does not
1669 fit in the "struct ifreq" that is used for these ioctls, and we do not want
1670 Blue/Classic, which currently uses AF_UNSPEC, to use a different address
1671 family multicast address than Mac OS X uses.
1674 int at_reg_mcast(ifID
, data
)
1678 struct ifnet
*nddp
= ifID
->aa_ifp
;
1679 struct sockaddr_dl sdl
;
1683 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1686 if (elap_trackMcast(ifID
, MCAST_TRACK_ADD
, data
) == 1)
1689 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1690 sdl
.sdl_family
= AF_LINK
;
1692 sdl
.sdl_type
= nddp
->if_type
;
1693 sdl
.sdl_alen
= nddp
->if_addrlen
;
1695 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1696 nddp
->if_name
, nddp
->if_unit
);
1697 bcopy(data
, LLADDR(&sdl
), sdl
.sdl_alen
);
1699 dPrintf(D_M_PAT
, D_L_STARTUP
,
1700 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1701 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1704 if (if_addmulti(nddp
, (struct sockaddr
*)&sdl
, 0))
1711 int at_unreg_mcast(ifID
, data
)
1715 struct ifnet
*nddp
= ifID
->aa_ifp
;
1716 struct sockaddr_dl sdl
;
1720 dPrintf(D_M_PAT
, D_L_STARTUP
, ("pat_mcast: BAD ndpp\n"));
1724 elap_trackMcast(ifID
, MCAST_TRACK_DELETE
, data
);
1726 sdl
.sdl_len
= sizeof(struct sockaddr_dl
);
1727 sdl
.sdl_family
= AF_LINK
;
1729 sdl
.sdl_type
= nddp
->if_type
;
1730 sdl
.sdl_alen
= nddp
->if_addrlen
;
1732 sdl
.sdl_nlen
= sprintf(sdl
.sdl_data
, "%s%d",
1733 nddp
->if_name
, nddp
->if_unit
);
1735 dPrintf(D_M_PAT
, D_L_STARTUP
,
1736 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1737 *(unsigned*)data
, (*(unsigned *)(data
+2))&0x0000ffff,
1739 bzero(data
, ETHERNET_ADDR_LEN
);
1741 if (if_delmulti(nddp
, (struct sockaddr
*)&sdl
))