]> git.saurik.com Git - apple/xnu.git/blame - bsd/netat/ddp_lap.c
xnu-1228.5.18.tar.gz
[apple/xnu.git] / bsd / netat / ddp_lap.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * Copyright (c) 1988, 1989, 1993-1998 Apple Computer, Inc.
30 */
31
32/* at_elap.c: 2.0, 1.29; 10/4/93; Apple Computer, Inc. */
33
34/* This is the file which implements all the streams driver
35 * functionality required for EtherTalk.
36 */
37
38/* revision history
39
40 03-14-94 jjs Changed all functions which assumed only one port would
41 ever be used. Added validate_msg_size, changed elap_online
42 to work with the h/w name only (e.g. 'et2').
43
44 Modified for MP, 1996 by Tuyen Nguyen
45 Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
46
47*/
48
49#define RESOLVE_DBG /* for debug.h global resolution */
50#include <sys/errno.h>
51#include <sys/types.h>
52#include <sys/param.h>
53#include <machine/spl.h>
54#include <sys/systm.h>
55#include <sys/kernel.h>
56#include <sys/proc.h>
57#include <sys/filedesc.h>
58#include <sys/fcntl.h>
59#include <sys/mbuf.h>
60#include <sys/ioctl.h>
61#include <sys/socket.h>
91447636 62#include <net/if_dl.h>
1c79356b
A
63#include <sys/socketvar.h>
64#include <sys/malloc.h>
91447636 65#include <sys/domain.h>
1c79356b 66#include <sys/sockio.h>
9bccf70c
A
67#include <vm/vm_kern.h> /* for kernel_map */
68
1c79356b
A
69
70#include <net/if.h>
71#include <net/if_types.h>
72
73#include <netat/sysglue.h>
74#include <netat/appletalk.h>
2d21ac55 75#include <netat/at_pcb.h>
1c79356b
A
76#include <netat/at_var.h>
77#include <netat/ddp.h>
78#include <netat/lap.h>
79#include <netat/routing_tables.h> /* rtmp+zip table structs */
80#include <netat/zip.h>
81#include <netat/nbp.h>
82#include <netat/at_snmp.h>
1c79356b
A
83#include <netat/at_aarp.h>
84#include <netat/asp.h>
85#include <netat/atp.h>
86#include <netat/debug.h>
87#include <netat/adsp.h>
88#include <netat/adsp_internal.h>
2d21ac55
A
89#include <netat/at_pat.h>
90#include <netat/rtmp.h>
1c79356b 91
9bccf70c
A
92#include <sys/kern_event.h>
93
1c79356b
A
94/* globals */
95
96at_ifaddr_t at_interfaces[IF_TOTAL_MAX];
97 /* index for at_interfaces is not important */
98at_ifaddr_t *ifID_table[IF_TOTAL_MAX];
99 /* the table of ifID structures, one per interface
100 (not just ethernet),
101 * NOTE: for MH, entry 0 in this table is
102 * now defined to be the default I/F
103 */
104at_ifaddr_t *ifID_home;
105 /* always ifID_table[IFID_HOME] for now, but will be used for
106 dynamic "home port" assignment, later */
107
108at_state_t at_state; /* global state of AT network */
109snmpFlags_t snmpFlags;
110
111int xpatcnt = 0;
112
113/* snmp defines */
114#define MAX_BUFSIZE 8192
115#define MAX_RTMP (MAX_BUFSIZE/sizeof(RT_entry)-1)
116#define MAX_NBP \
117 ((MAX_BUFSIZE - SNMP_NBP_HEADER_SIZE)/sizeof(snmpNbpEntry_t)-1)
118#define MAX_NBP_BYTES (MAX_NBP * sizeof(snmpNbpEntry_t))
119#define MAX_ZIP (MAX_BUFSIZE/sizeof(ZT_entry)-1)
120#define MAX_RTMP_BYTES (MAX_RTMP * sizeof(RT_entry))
121#define MAX_ZIP_BYTES (MAX_ZIP * sizeof(ZT_entry))
122
123/* externs */
124extern TAILQ_HEAD(name_registry, _nve_) name_registry;
125extern snmpStats_t snmpStats;
1c79356b
A
126extern short appletalk_inited;
127extern int adspInited;
128extern struct atpcb ddp_head;
129extern gref_t *atp_inputQ[];
130extern struct atp_state *atp_used_list;
131extern asp_scb_t *asp_scbQ[];
132extern asp_scb_t *scb_used_list;
133extern CCB *adsp_inputQ[];
134extern CCB *ccb_used_list;
135extern at_ddp_stats_t at_ddp_stats;
91447636 136extern lck_mtx_t * atalk_mutex;
1c79356b
A
137
138/* protos */
2d21ac55
A
139int rtmp_router_start(at_kern_err_t *);
140static void add_route(RT_entry *);
141void elap_offline(at_ifaddr_t *);
142static int elap_online1(at_ifaddr_t *);
143static void elap_online2(at_ifaddr_t *);
144 int elap_online3(at_ifaddr_t *);
145static int re_aarp(at_ifaddr_t *);
146static int getSnmpCfg(snmpCfg_t *);
147
148int routerStart(at_kern_err_t *);
149
150static int validate_msg_size(gbuf_t *, gref_t *, at_ifaddr_t **);
151at_ifaddr_t *find_ifID(char *);
152int lap_online( at_ifaddr_t *, at_if_cfg_t *cfgp);
153
1c79356b
A
154
155at_ifaddr_t *find_ifID(if_name)
156 char *if_name;
157{
158 int pat_id;
159
160 if (strlen(if_name))
161 for (pat_id=0; pat_id < xpatcnt; pat_id++) {
162 if (!strcmp(at_interfaces[pat_id].ifName, if_name))
163 return(&at_interfaces[pat_id]);
164 }
165
166 return((at_ifaddr_t *)NULL);
167}
168
169static int validate_msg_size(m, gref, elapp)
170 register gbuf_t *m;
171 gref_t *gref;
172 at_ifaddr_t **elapp;
173
174/* checks ioctl message type for minimum expected message size &
175 sends error back if size invalid
176*/
177{
178 register ioc_t *iocbp;
1c79356b
A
179 int i = 0, size = 1;
180
181 *elapp = NULL;
182 iocbp = (ioc_t *) gbuf_rptr(m);
183
184 dPrintf(D_M_ELAP, D_L_INFO, ("validate_msg_size: ioc_cmd = %d\n",
185 iocbp->ioc_cmd));
186 switch (iocbp->ioc_cmd) {
187 case LAP_IOC_ADD_ROUTE:
188 size = sizeof(RT_entry);
189 break;
190 case LAP_IOC_GET_ROUTE:
191 size = sizeof(RT_entry);
192 break;
193 case LAP_IOC_GET_ZONE:
194 size = sizeof(ZT_entryno);
195 break;
196 case LAP_IOC_SNMP_GET_CFG:
197 case LAP_IOC_SNMP_GET_AARP:
198 case LAP_IOC_SNMP_GET_ZIP:
199 case LAP_IOC_SNMP_GET_RTMP:
200 case LAP_IOC_SNMP_GET_NBP:
201 size = sizeof(int);
202 break;
203
204 case ELAP_IOC_GET_STATS:
205 case LAP_IOC_SNMP_GET_DDP:
206 size = 0;
207 break;
208
209 default:
210 dPrintf(D_M_ELAP, D_L_ERROR, ("validate_msg_size: unknown ioctl\n"));
211 goto error;
212 }
213
214 if (size == 0) { /* a non-data ioctl */
215 return(0);
216 }
217
218 if (gbuf_cont(m) != NULL)
219 i = gbuf_len(gbuf_cont(m));
220 if (iocbp->ioc_count < size || (gbuf_cont(m) == NULL) || i < size) {
221 dPrintf(D_M_ELAP, D_L_ERROR,
222 ("ioctl msg error:s:%d c:%d bcont:%c delta:%d\n",
223 size, iocbp->ioc_count,
224 gbuf_cont(m)? 'Y' : 'N', i));
225 goto error;
226 }
227 else
228 return(0);
229error:
230 ioc_ack(EMSGSIZE, m, gref);
231 return (EMSGSIZE);
232} /* validate_msg_size */
233
234int lap_online(elapp, cfgp)
235 at_ifaddr_t *elapp;
236 at_if_cfg_t *cfgp;
237{
238 int error;
239
240 if (elapp->ifState != LAP_OFFLINE) {
241 return(EALREADY);
242 }
243
244 elapp->flags = 0;
245 if (cfgp->flags & ELAP_CFG_HOME) {
246 if (ifID_home) {
247 /* only 1 home allowed! */
248 return(EEXIST);
249 }
250 dPrintf(D_M_ELAP, D_L_STARTUP,
251 ("elap_wput home I/F:%s\n", cfgp->ifr_name));
252 elapp->flags |= ELAP_CFG_HOME;
253 }
254
255 if (MULTIPORT_MODE) {
256 elapp->flags |= ELAP_CFG_ZONELESS;
257 if (ROUTING_MODE && cfgp->netStart)
258 elapp->flags |= ELAP_CFG_SEED;
259 }
260
2d21ac55
A
261 /* (VL) !? */
262 if ((!DEFAULT_ZONE(&cfgp->zonename) &&
263 (elapp->flags & ELAP_CFG_HOME)) || MULTIHOME_MODE) {
1c79356b
A
264 elapp->startup_zone = cfgp->zonename;
265 }
266
267 if (elapp->flags & ELAP_CFG_SEED) {
268 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
269 ("elap_wput: found to be seed\n"));
270 elapp->ifThisCableStart = cfgp->netStart;
271 elapp->ifThisCableEnd = cfgp->netEnd;
272 }
273 else {
274 dPrintf(D_M_ELAP,D_L_ERROR,
275 ("elap_wput: we believe we're not seed\n"));
276 /* from ELAP_IOC_SET_CFG */
277 if (ATALK_VALUE(cfgp->node)) {
278 u_short initial_net;
279 u_char initial_node;
280
281 initial_node = cfgp->node.s_node;
282 initial_net = cfgp->node.s_net;
283 if ((initial_node<0xfe) && (initial_node>0) &&
284 !((initial_net == 0) ||
285 ((initial_net >= DDP_STARTUP_LOW)&&
286 (initial_net <= DDP_STARTUP_HIGH)))) {
287
288 elapp->initial_addr = cfgp->node;
289 }
290 }
291 }
292
293 elapp->startup_error = 0;
294 elapp->startup_inprogress = FALSE;
295 if ((error = elap_online1(elapp)))
296 ddp_rem_if(elapp);
297 else
298 if (!(MULTIPORT_MODE) &&
299 elapp->ifZoneName.len == 1 &&
300 elapp->ifZoneName.str[0] == '*' &&
301 !DEFAULT_ZONE(&cfgp->zonename)) {
302 nbp_add_multicast(&cfgp->zonename, elapp);
303 }
304 return(error);
305} /* lap_online */
306
307/***********************************************************************
308 * elap_wput()
309 *
310 **********************************************************************/
311int elap_wput(gref, m)
312 gref_t *gref;
313 register gbuf_t *m;
314{
315 at_ifaddr_t *elapp;
316 register ioc_t *iocbp;
317 register at_if_cfg_t *cfgp;
318 at_elap_stats_t *statsp;
2d21ac55
A
319 int i,j;
320 int size, totalsize = 0, tabsize;
321 gbuf_t *mn; /* new gbuf */
322 gbuf_t *mo; /* old gbuf */
323 gbuf_t *mt = NULL; /* temp */
324 snmpNbpTable_t *nbp;
1c79356b
A
325
326
327 switch (gbuf_type(m)) {
328 case MSG_DATA:
329 gbuf_freem(m);
330 dPrintf(D_M_ELAP,D_L_ERROR,
331 ("Output data to control channel is ignored\n"));
332 break;
333
334 case MSG_IOCTL:
335 iocbp = (ioc_t *) gbuf_rptr(m);
336
337 if (validate_msg_size(m, gref, &elapp))
338 break;
339
340 if (elapp)
341 cfgp = (at_if_cfg_t*) gbuf_rptr(gbuf_cont(m));
342
343 if (LAP_IOC_MYIOCTL(iocbp->ioc_cmd) ||
344 ELAP_IOC_MYIOCTL(iocbp->ioc_cmd)) {
345
346 switch (iocbp->ioc_cmd) {
347 case ELAP_IOC_GET_STATS:
348#ifdef APPLETALK_DEBUG
349 kprintf("LAP_IOC_GET_STATS\n");
350#endif
351 if ( (gbuf_cont(m) == NULL)
352 || (elapp = find_ifID(gbuf_rptr(gbuf_cont(m)))) == NULL) {
353 ioc_ack(EINVAL, m, gref);
354 break;
355 }
356 gbuf_freem(gbuf_cont(m));
357 if ((gbuf_cont(m) =gbuf_alloc(sizeof(at_elap_stats_t),
358 PRI_MED)) == NULL) {
359 ioc_ack(ENOBUFS, m, gref);
360 break;
361 }
362 statsp = ((at_elap_stats_t *)gbuf_rptr(gbuf_cont(m)));
363 *statsp = elapp->stats;
364 gbuf_wset(gbuf_cont(m),sizeof(at_elap_stats_t));
365 iocbp->ioc_count = sizeof(at_elap_stats_t);
366 ioc_ack(0, m, gref);
367 break;
368
369 case LAP_IOC_ADD_ROUTE:
370#ifdef APPLETALK_DEBUG
371 kprintf("LAP_IOC_ADD_ROUTE\n");
372#endif
373 add_route((RT_entry *)gbuf_rptr(gbuf_cont(m)));
374 ioc_ack(0, m, gref);
375 break;
376
377 case LAP_IOC_GET_ZONE:
378#ifdef APPLETALK_DEBUG
379 kprintf("LAP_IOC_GET_ZONE\n");
380#endif
381 /* return next ZT_entryno from ZT_table
382 a pointer to the struct ZT_entryno is passed down from
383 user space and the first byte is cast to a int, if
384 this int is non-zero, then the first ZT_entry is
385 returned and subsequent calls with a zero value
386 will return the next entry in the table. The next
387 read after the last valid entry will return EINVAL
388 */
389 {
390 ZT_entryno *pZTe;
391
392 i = *(int *)gbuf_rptr(gbuf_cont(m));
393 gbuf_freem(gbuf_cont(m));
394 gbuf_cont(m) = NULL;
395
396 pZTe = zt_getNextZone(i);
397 if (pZTe) {
398 if ((gbuf_cont(m) = gbuf_alloc(sizeof(ZT_entryno), PRI_MED)) == NULL) {
399 ioc_ack(ENOBUFS, m, gref);
400 break;
401 }
402 *(ZT_entryno *)gbuf_rptr(gbuf_cont(m)) = *pZTe;
403 gbuf_wset(gbuf_cont(m),sizeof(ZT_entryno));
404 iocbp->ioc_count = sizeof(ZT_entryno);
405 ioc_ack(0, m, gref);
406 }
407 else
408 ioc_ack(EINVAL, m, gref);
409 }
410 break;
411
412 case LAP_IOC_GET_ROUTE:
413#ifdef APPLETALK_DEBUG
414 kprintf("LAP_IOC_GET_ROUTE\n");
415#endif
416 /* return next RT_entry from RT_table
417 * a pointer to the struct RT_entry is
418 * passed down from user space and the first
419 * byte is cast to a int, if this int is
420 * non-zero, then the first RT_entry is
421 * returned and subsequent calls with a
422 * zero value will return the next entry in
423 * the table. The next read after the last
424 * valid entry will return EINVAL
425 */
426 {
427 RT_entry *pRT;
428
429 i = *(int *)gbuf_rptr(gbuf_cont(m));
430 gbuf_freem(gbuf_cont(m));
431 gbuf_cont(m) = NULL;
432
433 pRT = rt_getNextRoute(i);
434 if (pRT) {
435 if ((gbuf_cont(m) = gbuf_alloc(sizeof(RT_entry), PRI_MED)) == NULL) {
436 ioc_ack(ENOBUFS, m, gref);
437 break;
438 }
439 *(RT_entry *)gbuf_rptr(gbuf_cont(m)) = *pRT;
440 gbuf_wset(gbuf_cont(m),sizeof(RT_entry));
441 iocbp->ioc_count = sizeof(RT_entry);
442 ioc_ack(0, m, gref);
443 }
444 else
445 ioc_ack(EINVAL, m, gref);
446 }
447 break;
448
449 case LAP_IOC_SNMP_GET_DDP:
450#ifdef APPLETALK_DEBUG
451 kprintf("LAP_IOC_SNMP_GET_DDP\n");
452#endif
453 if (!(at_state.flags & AT_ST_STARTED)) {
454 ioc_ack(ENOTREADY, m, gref);
455 break;
456 }
457 if ((gbuf_cont(m) = gbuf_alloc(sizeof(snmpStats_t),
458 PRI_MED)) == NULL) {
459 ioc_ack(ENOBUFS, m, gref);
460 break;
461 }
462
463 *(snmpStats_t *)gbuf_rptr(gbuf_cont(m)) = snmpStats;
464 gbuf_wset(gbuf_cont(m),sizeof(snmpStats));
465 iocbp->ioc_count = sizeof(snmpStats);
466 ioc_ack(0, m, gref);
467 break;
468 case LAP_IOC_SNMP_GET_CFG:
469#ifdef APPLETALK_DEBUG
470 kprintf("LAP_IOC_SNMP_GET_CFG\n");
471#endif
472 {
1c79356b
A
473 snmpCfg_t snmp;
474
475 i = *(int *)gbuf_rptr(gbuf_cont(m));
476 gbuf_freem(gbuf_cont(m));
477 gbuf_cont(m) = NULL;
478 if (!(at_state.flags & AT_ST_STARTED)) {
479 /* if stack down */
480 iocbp->ioc_count = 0;
481 ioc_ack(ENOTREADY, m, gref);
482 dPrintf(D_M_ELAP_LOW, D_L_INFO,
483 ("elap_wput: cfg req, stack down\n"));
484 break;
485 }
486 if (i == UPDATE_IF_CHANGED &&
487 !(at_state.flags & AT_ST_IF_CHANGED)) {
488 iocbp->ioc_count = 0;
489 ioc_ack(0, m, gref);
490 dPrintf(D_M_ELAP_LOW, D_L_INFO,
491 ("elap_wput: cfg req, unchanged\n"));
492 break;
493 }
494 dPrintf(D_M_ELAP_LOW, D_L_INFO,
495 ("elap_wput: cfg req, changed\n"));
496
497 if (getSnmpCfg(&snmp)) {
498 dPrintf(D_M_ELAP,D_L_ERROR,
499 ("elap_wput:SNMP_GET_CFG error\n"));
500 ioc_ack(EOPNOTSUPP, m, gref);
501 break;
502 }
503 /* send up only used part of table */
504 size = sizeof(snmp) -
505 sizeof(snmpIfCfg_t) * (MAX_IFS - snmp.cfg_ifCnt);
506
507 if ((gbuf_cont(m) = gbuf_alloc(size, PRI_MED)) == NULL) {
508 ioc_ack(ENOBUFS, m, gref);
509 break;
510 }
511 bcopy(&snmp,gbuf_rptr(gbuf_cont(m)),size);
512 gbuf_wset(gbuf_cont(m),size);
513 iocbp->ioc_count = size;
514 at_state.flags &= ~AT_ST_IF_CHANGED;
515 ioc_ack(0, m, gref);
516 }
517 break;
518
519 case LAP_IOC_SNMP_GET_AARP:
520 {
521 snmpAarpEnt_t *snmpp;
522 int bytes;
523#ifdef APPLETALK_DEBUG
524 kprintf("LAP_IOC_SNMP_GET_AARP\n");
525#endif
526 i = *(int *)gbuf_rptr(gbuf_cont(m));
527 gbuf_freem(gbuf_cont(m));
528 gbuf_cont(m) = NULL;
529 dPrintf(D_M_ELAP,D_L_INFO,
530 ("elap_wput:calling getarp,i=%d\n", i));
531 snmpp = getAarp(&i);
532 bytes = i * sizeof(snmpAarpEnt_t);
533 dPrintf(D_M_ELAP,D_L_INFO,
534 ("elap_wput:getarp returned, i=%d,bytes=%d\n",
535 i, bytes));
536 if (snmpp) {
537 if ((gbuf_cont(m) = gbuf_alloc(bytes, PRI_MED)) == NULL) {
538 ioc_ack(ENOBUFS, m, gref);
539 break;
540 }
541 bcopy(snmpp, gbuf_rptr(gbuf_cont(m)), bytes);
542 gbuf_wset(gbuf_cont(m),bytes);
543 iocbp->ioc_count = bytes;
544 ioc_ack(0, m, gref);
545 }
546 else
547 ioc_ack(EOPNOTSUPP, m, gref);
548 }
549 break;
550
551 case LAP_IOC_SNMP_GET_ZIP:
552#ifdef APPLETALK_DEBUG
553 kprintf("LAP_IOC_SNMP_GET_ZIP\n");
554#endif
555 { /* matching brace NOT in this case */
1c79356b
A
556
557 i = *(int *)gbuf_rptr(gbuf_cont(m));
558 gbuf_freem(gbuf_cont(m));
559 gbuf_cont(m) = NULL;
560 if (!(at_state.flags & AT_ST_STARTED)) {
561 ioc_ack(ENOTREADY, m, gref);
562 break;
563 }
564 if (i == UPDATE_IF_CHANGED &&
565 !(at_state.flags & AT_ST_ZT_CHANGED)) {
566 iocbp->ioc_count = 0;
567 ioc_ack(0, m, gref);
568 break;
569 }
570 mo=(gbuf_t*)NULL;
571 tabsize = getZipTableSize();
572
573 /* retrieve table into multiple gbufs */
574 for (i =0; i<tabsize; i+=j) {
575 j = tabsize - i >
576 MAX_ZIP ? MAX_ZIP : tabsize - i;
577 size = j < MAX_ZIP ? sizeof(ZT_entry)*j : MAX_ZIP_BYTES;
578 if ((mn = gbuf_alloc(size, PRI_MED)) == NULL) {
579 if (gbuf_cont(m))
580 gbuf_freem(gbuf_cont(m));
581 ioc_ack(ENOBUFS, m, gref);
582 break;
583 }
584 if (!mo) { /* if first new one */
585 mt = mn;
2d21ac55 586 totalsize = size;
1c79356b
A
587 }
588 else {
589 gbuf_cont(mo) = mn;
2d21ac55 590 totalsize += size;
1c79356b
A
591 }
592 mo = mn;
593 getZipTable((ZT_entry*)gbuf_rptr(mn),i,j);
594 gbuf_wset(mn,size);
595 }
596 if ((gbuf_cont(m) = gbuf_alloc(sizeof(int), PRI_MED)) == NULL) {
597 if (mt)
598 gbuf_freem(mt);
599 iocbp->ioc_count = 0;
600 ioc_ack(ENOBUFS, m, gref);
601 break;
602 }
603 if (!tabsize) {
604 dPrintf(D_M_ELAP,D_L_WARNING,
605 ("elap_wput:snmp: empty zip table\n"));
2d21ac55 606 totalsize = 0;
1c79356b 607 }
2d21ac55 608 *(int*)gbuf_rptr(gbuf_cont(m)) = totalsize; /* return table size */
1c79356b
A
609 gbuf_wset(gbuf_cont(m),sizeof(int));
610 iocbp->ioc_count = sizeof(int);
611 ioc_ack(0, m, gref);
612 if (tabsize)
613 atalk_putnext(gref,mt); /* send up table */
614 at_state.flags &= ~AT_ST_ZT_CHANGED;
615 break;
616
617 case LAP_IOC_SNMP_GET_RTMP:
618#ifdef APPLETALK_DEBUG
619 kprintf("LAP_IOC_SNMP_GET_RTMP\n");
620#endif
621 i = *(int *)gbuf_rptr(gbuf_cont(m));
622 gbuf_freem(gbuf_cont(m));
623 gbuf_cont(m) = NULL;
624 if (!(at_state.flags & AT_ST_STARTED)) {
625 ioc_ack(ENOTREADY, m, gref);
626 break;
627 }
628 if (i == UPDATE_IF_CHANGED &&
629 !(at_state.flags & AT_ST_RT_CHANGED)) {
630 iocbp->ioc_count = 0;
631 ioc_ack(0, m, gref);
632 break;
633 }
634
635 mo=(gbuf_t*)NULL;
636 tabsize = getRtmpTableSize();
637
638 /* retrieve table into multiple gbufs */
639 for (i =0; i<tabsize; i+=j) {
640 j = tabsize - i >
641 MAX_RTMP ? MAX_RTMP : tabsize - i;
642 size = j < MAX_RTMP ? sizeof(RT_entry)*j : MAX_RTMP_BYTES;
643 if ((mn = gbuf_alloc(size, PRI_MED)) == NULL) {
644 if (gbuf_cont(m))
645 gbuf_freem(gbuf_cont(m));
646 ioc_ack(ENOBUFS, m, gref);
647 break;
648 }
649 if (!mo) { /* if first new one */
650 mt = mn;
2d21ac55 651 totalsize = size;
1c79356b
A
652 }
653 else {
654 gbuf_cont(mo) = mn;
2d21ac55 655 totalsize += size;
1c79356b
A
656 }
657 mo = mn;
658 getRtmpTable((RT_entry*)gbuf_rptr(mn),i,j);
659 gbuf_wset(mn,size);
660 }
661 if ((gbuf_cont(m) = gbuf_alloc(sizeof(int), PRI_MED)) == NULL) {
662 if (mt)
663 gbuf_freem(mt);
664 iocbp->ioc_count = 0;
665 ioc_ack(ENOBUFS, m, gref);
666 break;
667 }
668 if (!tabsize)
2d21ac55
A
669 totalsize = 0;
670 *(int*)gbuf_rptr(gbuf_cont(m)) = totalsize; /* return table size */
1c79356b
A
671 gbuf_wset(gbuf_cont(m),sizeof(int));
672 iocbp->ioc_count = sizeof(int);
673 ioc_ack(0, m, gref);
674 if (tabsize)
675 atalk_putnext(gref,mt); /* send up table */
676 at_state.flags &= ~AT_ST_RT_CHANGED;
677 break;
678
679 case LAP_IOC_SNMP_GET_NBP:
680#ifdef APPLETALK_DEBUG
681 kprintf("LAP_IOC_SNMP_GET_NBP\n");
682#endif
683 i = *(int *)gbuf_rptr(gbuf_cont(m));
684 gbuf_freem(gbuf_cont(m));
685 gbuf_cont(m) = NULL;
686 if (!(at_state.flags & AT_ST_STARTED)) {
687 ioc_ack(ENOTREADY, m, gref);
688 break;
689 }
690 if (i == UPDATE_IF_CHANGED &&
691 !(at_state.flags & AT_ST_NBP_CHANGED)) {
692 iocbp->ioc_count = 0;
693 ioc_ack(0, m, gref);
694 dPrintf(D_M_ELAP_LOW, D_L_INFO,
695 ("elap_wput: nbp req denied, no change\n"));
696 break;
697 }
698
699 mo=(gbuf_t*)NULL;
700 tabsize = getNbpTableSize();
701
702 /* retrieve table into multiple gbufs */
703 for (i =0; i<tabsize; i+=j) {
704 j = tabsize - i >
705 MAX_NBP ? MAX_NBP : tabsize - i;
706 size = j < MAX_NBP ? sizeof(snmpNbpEntry_t)*j : MAX_NBP_BYTES;
707 if (!i)
708 size += SNMP_NBP_HEADER_SIZE;
709 if ((mn = gbuf_alloc(size, PRI_MED)) == NULL) {
710 if (gbuf_cont(m))
711 gbuf_freem(gbuf_cont(m));
712 ioc_ack(ENOBUFS, m, gref);
713 break;
714 }
715 if (!mo) { /* if first new one */
716 mt = mn;
2d21ac55 717 totalsize = size;
1c79356b
A
718 nbp = (snmpNbpTable_t*)gbuf_rptr(mn);
719 nbp->nbpt_entries = tabsize;
720 nbp->nbpt_zone = ifID_home->ifZoneName;
721 getNbpTable(nbp->nbpt_table,i,j);
722 }
723 else {
724 gbuf_cont(mo) = mn;
2d21ac55 725 totalsize += size;
1c79356b
A
726 getNbpTable((snmpNbpEntry_t *)gbuf_rptr(mn),i,j);
727 }
728 mo = mn;
729 gbuf_wset(mn,size);
730 }
731 if ((gbuf_cont(m) = gbuf_alloc(sizeof(int), PRI_MED)) == NULL) {
732 if (mt)
733 gbuf_freem(mt);
734 iocbp->ioc_count = 0;
735 ioc_ack(ENOBUFS, m, gref);
736 break;
737 }
738 if (!tabsize)
2d21ac55
A
739 totalsize = 0;
740 *(int*)gbuf_rptr(gbuf_cont(m)) = totalsize; /* return table size */
1c79356b
A
741 gbuf_wset(gbuf_cont(m),sizeof(int));
742 iocbp->ioc_count = sizeof(int);
743 ioc_ack(0, m, gref);
744 if (tabsize)
745 atalk_putnext(gref,mt); /* send up table */
746 at_state.flags &= ~AT_ST_NBP_CHANGED;
747 break;
748 }
749
750 default:
751#ifdef APPLETALK_DEBUG
752 kprintf("unknown ioctl %d\n", iocbp->ioc_cmd);
753#endif
754 ioc_ack(ENOTTY, m, gref);
755 dPrintf(D_M_ELAP, D_L_WARNING,
756 ("elap_wput: unknown ioctl (%d)\n", iocbp->ioc_cmd));
757
758 if (elapp)
759 elapp->stats.unknown_mblks++;
760 break;
761 }
762 }
763 break;
764
765 default:
766 gbuf_freem(m);
767 break;
768 }
769
770 return 0;
771} /* elap_wput */
772
773
774/* Called directly by ddp/zip.
775 */
2d21ac55 776int
1c79356b
A
777elap_dataput(m, elapp, addr_flag, addr)
778 register gbuf_t *m;
779 register at_ifaddr_t *elapp;
780 u_char addr_flag;
781 char *addr;
782{
783 register int size;
91447636 784 int error = 0;
1c79356b
A
785 struct etalk_addr dest_addr;
786 struct atalk_addr dest_at_addr;
1c79356b
A
787 int loop = TRUE;
788 /* flag to aarp to loopback (default) */
789
790 /* the incoming frame is of the form {flag, address, ddp...}
791 * where "flag" indicates whether the address is an 802.3
792 * (link) address, or an appletalk address. If it's an
793 * 802.3 address, the packet can just go out to the network
794 * through PAT, if it's an appletalk address, AT->802.3 address
795 * resolution needs to be done.
796 * If 802.3 address is known, strip off the flag and 802.3
797 * address, and prepend 802.2 and 802.3 headers.
798 */
799
800 if (addr == NULL) {
801 addr_flag = *(u_char *)gbuf_rptr(m);
802 gbuf_rinc(m,1);
803 }
804
805 switch (addr_flag) {
806 case AT_ADDR_NO_LOOP :
807 loop = FALSE;
808 /* pass thru */
809 case AT_ADDR :
810 if (addr == NULL) {
811 dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m);
812 gbuf_rinc(m,sizeof(struct atalk_addr));
813 } else
814 dest_at_addr = *(struct atalk_addr *)addr;
815 break;
816 case ET_ADDR :
817 if (addr == NULL) {
818 dest_addr = *(struct etalk_addr *)gbuf_rptr(m);
819 gbuf_rinc(m,sizeof(struct etalk_addr));
820 } else
821 dest_addr = *(struct etalk_addr *)addr;
822 break;
823 default :
824 gbuf_freel(m); /* unknown address type, chuck it */
825 return(EINVAL);
826 }
827
828 m = gbuf_strip(m);
829
830 /* At this point, rptr points to ddp header for sure */
831 if (elapp->ifState == LAP_OFFLINE) {
832 gbuf_freel(m);
833 return(ENETDOWN);
834 }
835
836 if (elapp->ifState == LAP_ONLINE_FOR_ZIP) {
837 /* see if this is a ZIP packet that we need
838 * to let through even though network is
839 * not yet alive!!
840 */
841 if (zip_type_packet(m) == 0) {
842 gbuf_freel(m);
843 return(ENETDOWN);
844 }
845 }
846
847 elapp->stats.xmit_packets++;
848 size = gbuf_msgsize(m);
849 elapp->stats.xmit_bytes += size;
850 snmpStats.dd_outLong++;
851
852 switch (addr_flag) {
853 case AT_ADDR_NO_LOOP :
854 case AT_ADDR :
855 /*
856 * we don't want elap to be looking into ddp header, so
857 * it doesn't know net#, consequently can't do
858 * AMT_LOOKUP. That task left to aarp now.
859 */
0c530ab8 860 error = aarp_send_data(m, elapp, &dest_at_addr, loop);
1c79356b
A
861 break;
862 case ET_ADDR :
2d21ac55 863 error = pat_output(elapp, m, (unsigned char *)&dest_addr, 0);
1c79356b
A
864 break;
865 }
866 return (error);
867} /* elap_dataput */
868
869/************************************************************************
870 * elap_online()
871 *
872 ************************************************************************/
873
874static int elap_online1(elapp)
875 at_ifaddr_t *elapp;
876{
877 int errno;
878
879 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online:%s elapp:0x%x\n",
880 (elapp->ifName) ? &elapp->ifName[0] : "NULL interface", (u_int) elapp));
881 if (elapp->ifState != LAP_OFFLINE || elapp->startup_inprogress == TRUE)
882 return (EALREADY);
883
884 at_state.flags |= AT_ST_IF_CHANGED;
885
886 if (elapp->flags & ELAP_CFG_HOME) /* tell ddp_add_if if this is home */
887 elapp->ifFlags |= AT_IFF_DEFAULT;
888
889 /* Get DDP started */
890 if ((errno = ddp_add_if(elapp)))
891 return(errno);
55e303ae
A
892
893 // check if we still have an interface - can be lost when
894 // ddp_add_if calls malloc
895 // need to make check here after ddp_add_if completes because
896 // lap_online will call ddp_rem_if if we fail here
897 if (elapp->aa_ifp == 0)
898 return ENOENT;
899
1c79356b
A
900 /* set up multicast address for cable-wide broadcasts */
901 (void)at_reg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
902
55e303ae
A
903 // need to check again if interface is present
904 // can be lost in at_reg_mcast
905 if (elapp->aa_ifp == 0)
906 return ENOENT;
907
1c79356b 908 elapp->startup_inprogress = TRUE;
91447636
A
909 if (! (elapp->startup_error = re_aarp(elapp))) {
910 lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED);
911 (void)msleep(&elapp->startup_inprogress, atalk_mutex, PSOCK | PCATCH,
1c79356b 912 "elap_online1", 0);
91447636 913 }
1c79356b
A
914
915 /* then later, after some timeouts AARPwakeup() is called */
916
917 return(elapp->startup_error);
918} /* elap_online1 */
919
920static int re_aarp(elapp)
921 at_ifaddr_t *elapp;
922{
923 int errno;
924
925 /* We now call aarp_init() to assign an appletalk node addr */
926 errno = aarp_init1(elapp);
927 /* aarp_init1() returns either -1 or ENOTREADY */
928 if (errno == ENOTREADY)
929 return(0);
930 else {
931 dPrintf(D_M_ELAP, D_L_STATE_CHG,
932 ("elap_online aarp_init for %s\n", elapp->ifName));
933 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
934 ddp_rem_if(elapp);
935 elapp->ifState = LAP_OFFLINE;
936 return(EADDRNOTAVAIL);
937 }
938}
939
940/* called from AARPwakeup */
941static void elap_online2(elapp)
942 at_ifaddr_t *elapp;
943{
944 if (MULTIPORT_MODE) {
945 dPrintf(D_M_ELAP,D_L_STARTUP_INFO,
946 ("elap_online: re_aarp, we know it's a router...\n"));
947
948 if (elapp->flags & ELAP_CFG_SEED) {
949 /* add route table entry (zones to be added later) */
950 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
951 ("elap_online: rt_insert Cable %d-%d port =%d as SEED\n",
952 elapp->ifThisCableStart, elapp->ifThisCableEnd, elapp->ifPort));
953 rt_insert(elapp->ifThisCableEnd,
954 elapp->ifThisCableStart,
955 0,0,0,
956 elapp->ifPort,
957 RTE_STATE_PERMANENT | RTE_STATE_ZKNOWN | RTE_STATE_GOOD
958 );
959 /* LD 081694: set the RTR_SEED_PORT flag for seed ports */
960 elapp->ifFlags |= RTR_SEED_PORT;
961 }
2d21ac55 962#if DEBUG
1c79356b
A
963 else
964 dPrintf(D_M_ELAP,D_L_STARTUP_INFO,
965 ("elap_online: it's a router, but non seed\n"));
2d21ac55 966#endif
1c79356b
A
967 }
968
969 if (elapp->flags & ELAP_CFG_ZONELESS) {
970 /* ELAP_CFG_ZONELESS tells us that it is a router or in
971 multihome mode, so we don't want to do the GetNetInfo
972 exchange with the router. */
973
974 elapp->ifState = LAP_ONLINE_ZONELESS;
975 elapp->startup_inprogress = FALSE;
9bccf70c 976 wakeup(&elapp->startup_inprogress);
1c79356b
A
977 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online: ack 3\n"));
978 return;
979 }
980
981 /* if we don't already have a zone and a multicast address */
982 if (*(int *)&elapp->ZoneMcastAddr == 0 || elapp->ifZoneName.len == 0) {
983 /* hzonehash is a global containing the nbp hash for the startup_zone */
984 sethzonehash(elapp);
985
986 /* Get ZIP rolling to get zone multicast address, etc. */
987 elapp->ifState = LAP_ONLINE_FOR_ZIP;
988 (void)zip_control(elapp, ZIP_ONLINE);
989 /* zip_control (w. control == ZIP_ONLINE) always returns ENOTREADY */
990
991 /* later, after some timeouts ZIPwakeup() is called. */
992 } else {
993 /* otherwise, we have the zone and the multicast already,
994 so don't bother with another ZIP GetNetInfo request */
995 ZIPwakeup(elapp, 0);
996 }
997} /* elap_online2 */
998
999/* called from rtmp_router_start */
1000int elap_online3(elapp)
1001 at_ifaddr_t *elapp;
1002{
1003 elapp->startup_inprogress = TRUE;
1004
1005 /* just reset the net range */
1006 elapp->initial_addr.s_net = 0;
1007 elapp->initial_addr.s_node = 0;
1008 dPrintf(D_M_ELAP_LOW, D_L_STARTUP_INFO,
1009 ("elap_online: goto re_aarp port=%d\n", elapp->ifPort));
1010
1011 if ((elapp->startup_error = re_aarp(elapp)))
1012 return(elapp->startup_error);
1013
1014 /* then later, after some timeouts AARPwakeup() is called */
1015
91447636
A
1016 lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED);
1017 (void)msleep(&elapp->startup_inprogress, atalk_mutex, PSOCK | PCATCH,
1c79356b
A
1018 "elap_online3", 0);
1019 return(elapp->startup_error);
1020} /* elap_online3 */
1021
1022/****************************************************************************
1023 * elap_offline()
1024 *
1025 ****************************************************************************/
1026
1027void elap_offline(elapp)
1028 register at_ifaddr_t *elapp;
1029
1030{
1c79356b
A
1031 dPrintf(D_M_ELAP, D_L_SHUTDN_INFO, ("elap_offline:%s\n", elapp->ifName));
1032 if (elapp->ifState != LAP_OFFLINE) {
1033
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.
1038 */
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;
1042
1c79356b
A
1043 if (MULTIPORT_MODE)
1044 RT_DELETE(elapp->ifThisCableEnd,
1045 elapp->ifThisCableStart);
1c79356b
A
1046
1047 /* make sure no zip timeouts are left running */
91447636 1048 elapp->ifGNIScheduled = 0;
1c79356b
A
1049 untimeout(zip_sched_getnetinfo, elapp);
1050 }
1051 ddp_rem_if(elapp);
1052} /* elap_offline */
1053
1054
1055static void add_route(rt)
1056RT_entry *rt;
1057
1058/* support ioctl to manually add routes to table.
1059 this is really only for testing
1060*/
1061{
1062 rt_insert( rt->NetStop, rt->NetStart, rt->NextIRNet,
1063 rt->NextIRNode, rt->NetDist, rt->NetPort,
1064 rt->EntryState);
1065 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("adding route: %ud:%ud dist:%ud\n",
1066 rt->NetStart, rt->NetStop,rt->NetDist));
1067}
1068
1069/*
1070 * ddp_start()
1071 *
1072 * Initialization that takes place each time AppleTalk is restarted.
1073 *
1074 */
1075void ddp_start()
1076{
1077 TAILQ_INIT(&at_ifQueueHd);
1078 TAILQ_INIT(&name_registry);
1079 bzero(at_interfaces, sizeof(at_interfaces));
1080 bzero(ifID_table, sizeof(ifID_table));
1081 bzero(&at_ddp_stats, sizeof(at_ddp_stats_t));
1082 rtmp_init(); /* initialize trackedrouters */
1083
1084 add_ddp_handler(RTMP_SOCKET, rtmp_input);
1085 ifID_home = (at_ifaddr_t *)NULL;
1086 xpatcnt = 0;
1087}
1088
1089int ddp_shutdown(count_only)
1090 int count_only;
1091{
1092 at_ifaddr_t *ifID;
1093 asp_scb_t *scb, *scb_next;
1094 struct atp_state *atp, *atp_next;
1095 CCB *sp, *sp_next;
1096 gref_t *gref;
0c530ab8 1097 int i, active_skts = 0; /* count of active pids for non-socketized
1c79356b 1098 AppleTalk protocols */
1c79356b
A
1099
1100 /* Network is shutting down... send error messages up on each open
1101 * socket.
1102 *** For now, for ASP, ATP and ADSP, attempt to notify open
1103 sockets, but return EBUSY and don't complete shutdown. ***
1104 */
1105
1c79356b
A
1106 if (!count_only)
1107 nbp_shutdown(); /* clear all known NVE */
1108
1109 /* ASP */
1110 for (scb = scb_used_list; scb; ) {
1111 scb_next = scb->next_scb;
1112 active_skts++;
1113 if (!count_only) {
1114 dPrintf(D_M_ASP, D_L_TRACE, ("asp pid=%d\n", scb->pid));
1115 atalk_notify(scb->gref, ESHUTDOWN);
1116 }
1117 scb = scb_next;
1118 }
1119 for (i = 0; i < 256 ; i++) {
1120 if ((scb = asp_scbQ[i]))
1121 do {
1122 scb_next = scb->next_scb;
1123 active_skts++;
1124 if (!count_only) {
1125 dPrintf(D_M_ASP, D_L_TRACE,
1126 ("asp pid=%d\n", scb->pid));
1127 atalk_notify(scb->gref, ESHUTDOWN);
1128 }
1129 scb = scb_next;
1130 } while (scb);
1131 }
1132
1133 /* ATP */
1134 for (atp = atp_used_list; atp; ) {
1135 atp_next = atp->atp_trans_waiting;
1136 active_skts++;
1137 if (!count_only) {
1138 dPrintf(D_M_ATP, D_L_TRACE, ("atp pid=%d\n", atp->atp_pid));
1139 atalk_notify(atp->atp_gref, ESHUTDOWN);
1140 }
1141 atp = atp_next;
1142 }
1143 for (i = 0; i < 256; i++) {
1144 if ((gref = atp_inputQ[i]) && (gref != (gref_t *)1)) {
1145 atp = (struct atp_state *)gref->info;
1146 if (!atp->dflag) {
1147 active_skts++;
1148 if (!count_only) {
1149 dPrintf(D_M_ATP, D_L_TRACE,
1150 ("atp pid=%d\n", atp->atp_pid));
1151 atalk_notify(atp->atp_gref, ESHUTDOWN);
1152 }
1153 }
1154 }
1155 }
0b4e3aa0 1156
1c79356b
A
1157 /* ADSP */
1158 for (sp = ccb_used_list; sp ; ) {
1159 sp_next = sp->otccbLink;
1160 active_skts++;
1161 if (!count_only) {
1162 dPrintf(D_M_ADSP, D_L_TRACE, ("adsp pid=%d\n", sp->pid));
1163 atalk_notify(sp->gref, ESHUTDOWN);
1164 }
1165 sp = sp_next;
1166 }
1167 for (i = 0; i < 256 ; i++) {
1168 if ((sp = adsp_inputQ[i]))
1169 do {
1170 sp_next = sp->otccbLink;
1171 active_skts++;
1172 if (!count_only) {
1173 dPrintf(D_M_ADSP, D_L_TRACE,
1174 ("adsp pid=%d\n", sp->pid));
1175 atalk_notify(sp->gref, ESHUTDOWN);
1176 }
1177 sp = sp_next;
1178 } while (sp);
1179 }
1180
1181 /* DDP */
1182 for (gref = ddp_head.atpcb_next; gref != &ddp_head;
1183 gref = gref->atpcb_next) {
1184 if (count_only) {
1185 active_skts++;
1186 } else {
1187 dPrintf(D_M_DDP,D_L_TRACE, ("ddp pid=%d\n", gref->pid));
1188 atalk_notify(gref, ESHUTDOWN);
1189 }
1190 }
0c530ab8 1191 if (count_only)
1c79356b
A
1192 return(active_skts);
1193
1c79356b
A
1194 /* if there are no interfaces in the process of going online, continue shutting down DDP */
1195 for (i = 0; i < IF_TOTAL_MAX; i++) {
1196 if (at_interfaces[i].startup_inprogress == TRUE)
1197 return(1);
1198 }
1199 if (MULTIPORT_MODE) {
1200 rtmp_shutdown();
1201 /* free memory allocated for the rtmp/zip tables */
1202 if (ZT_table) {
1203 FREE(ZT_table, M_RTABLE);
1204 ZT_table = (ZT_entry *)NULL;
1205 }
1206 if (RT_table) {
1207 FREE(RT_table, M_RTABLE);
1208 RT_table = (RT_entry *)NULL;
1209 }
1210 }
1211
1212 at_state.flags = 0; /* make sure inits are done on restart */
9bccf70c
A
1213
1214 wakeup(&ifID_home->startup_inprogress); /* if rtmp_router_start still starting up */
1c79356b
A
1215
1216 /* from original ddp_shutdown() */
1217 routershutdown();
1218 ddp_brt_shutdown();
1219
1220 if (adspInited) {
1221 CleanupGlobals();
1222 adspInited = 0;
1223 }
9bccf70c
A
1224
1225
1c79356b
A
1226 dPrintf(D_M_DDP, D_L_VERBOSE, ("DDP shutdown completed"));
1227
1228 /*
1229 * make sure we don't have a probe timeout hanging around
1230 * it's going to try and make use of an entry in at_interfaces
1231 * which is going to be zero'd out by the call to ddp_start a
1232 * little further down
1233 */
1234 untimeout(aarp_sched_probe, 0);
1235
1236 /* *** after an SIOCSIFADDR and before an AIOCSIFADDR,
1237 this is the only place to find the ifID *** */
1238 for (i = 0; i < IF_TOTAL_MAX; i++) {
1239 ifID = &at_interfaces[i];
1240 /* do LAP_IOC_OFFLINE processing */
1241 elap_offline(ifID);
1242 }
1243 ddp_start();
9bccf70c 1244
1c79356b
A
1245 return(0);
1246} /* ddp_shutdown */
1247
1248int routerStart(keP)
1249 at_kern_err_t *keP;
1250{
1251 register at_ifaddr_t *ifID;
1252 int error;
91447636 1253 struct timespec ts;
1c79356b
A
1254
1255 if (! ifID_home)
1256 return(EINVAL);
1257
1258 /*
1259 * this will cause the ports to glean from the net the relevant
1260 * information before forwarding
1261 */
1262 TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
1263 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
1264 ("routerStart Port %d (%s) set to activating\n",
1265 ifID->ifPort, ifID->ifName));
1266 ifID->ifRoutingState = PORT_ACTIVATING;
1267 ifID->ifFlags |= RTR_XNET_PORT;
1268 }
1269
1270 /*
1271 * The next step is to check the information for each port before
1272 * declaring the ports up and forwarding
1273 */
1274 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
1275 ("router_start: waiting 20 sec before starting up\n"));
1276
91447636 1277 lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED);
1c79356b 1278 /* sleep for 20 seconds */
91447636
A
1279
1280 /* the vaue of 10n terms of hz is 100ms */
1281 ts.tv_sec = 20;
1282 ts.tv_nsec = 0;
1283
1c79356b
A
1284 if ((error =
1285 /* *** eventually this will be the ifID for the interface
1286 being brought up in router mode *** */
91447636
A
1287 msleep(&ifID_home->startup_inprogress, atalk_mutex,
1288 PSOCK | PCATCH, "routerStart", &ts))
1c79356b
A
1289 != EWOULDBLOCK) {
1290/*
1291 if (!error)
1292 panic("routerStart: spurious interrupt");
1293*/
1294 return(error);
1295 }
1296
1297 return(rtmp_router_start(keP));
1298 /* was timeout(rtmp_router_start, 0, 20 * SYS_HZ); */
1299} /* routerStart */
1300
1301void ZIPwakeup(elapp, ZipError)
1302 at_ifaddr_t *elapp;
1303 int ZipError;
1304{
0c530ab8 1305 int error = ZipError;
1c79356b 1306
1c79356b 1307 if ( (elapp != NULL) && elapp->startup_inprogress) {
1c79356b
A
1308
1309 /* was ZIPContinue */
1310 /* was elapp_online() with jump to ZIP_sleep */
1311
1312 /* instead of the goto ZIP_sleep ... */
1313 switch (ZipError) {
1314 case 0 : /* success */
1315 elapp->ifState = LAP_ONLINE;
9bccf70c
A
1316
1317 /* Send event with zone info. */
1318 atalk_post_msg(elapp->aa_ifp, KEV_ATALK_ZONEUPDATED, 0, &(elapp->ifZoneName));
1319
1c79356b
A
1320 break;
1321 case ZIP_RE_AARP :
1322 /* instead of goto re_aarp; */
1323 /* We now call aarp_init() to assign an
1324 appletalk node addr */
1325 if ((elapp->startup_error = re_aarp(elapp))) {
1326 elapp->startup_inprogress = FALSE;
9bccf70c 1327 wakeup(&elapp->startup_inprogress);
1c79356b
A
1328 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
1329 ("elap_online: ack 2\n"));
1330 }
1331 break;
1332 default :
1333 break;
1334 }
1335 if (ZipError != ZIP_RE_AARP) {
1336 elapp->startup_error = error;
1337 elapp->startup_inprogress = FALSE;
9bccf70c 1338 wakeup(&elapp->startup_inprogress);
1c79356b
A
1339 dPrintf(D_M_ELAP, D_L_STARTUP_INFO,
1340 ("elap_online: ifZipError=%d\n", error));
1341 }
0c530ab8 1342 }
1c79356b
A
1343} /* ZIPwakeup */
1344
1345void AARPwakeup(probe_cb)
1346 aarp_amt_t *probe_cb;
1347{
1c79356b
A
1348 int errno;
1349 at_ifaddr_t *elapp;
1350
1c79356b 1351 elapp = probe_cb->elapp;
55e303ae 1352 if ( (elapp != NULL) && elapp->startup_inprogress && elapp->aa_ifp != 0) {
1c79356b
A
1353
1354 /* was AARPContinue */
1355 errno = aarp_init2(elapp);
1356 /* aarp_init2() returns either -1 or 0 */
1357 if (errno != 0) {
1358 dPrintf(D_M_ELAP, D_L_STATE_CHG,
1359 ("elap_online aarp_init for %s\n",
1360 elapp->ifName));
1361 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->ZoneMcastAddr);
1362 (void)at_unreg_mcast(elapp, (caddr_t)&elapp->cable_multicast_addr);
1363 elapp->ifState = LAP_OFFLINE;
1364 ddp_rem_if(elapp);
1365 elapp->startup_error = EADDRNOTAVAIL;
1366 elapp->startup_inprogress = FALSE;
9bccf70c 1367 wakeup(&elapp->startup_inprogress);
1c79356b
A
1368 dPrintf(D_M_ELAP, D_L_STARTUP_INFO, ("elap_online: ack 2\n"));
1369 } else {
1370 dPrintf(D_M_ELAP,D_L_STARTUP_INFO,
1371 ("elap_online: aarp_init returns zero\n"));
1372 elap_online2(elapp);
1373 }
0c530ab8 1374 }
1c79356b
A
1375} /* AARPwakeup */
1376
1377void ddp_bit_reverse(addr)
1378 unsigned char *addr;
1379{
1380static unsigned char reverse_data[] = {
1381 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1382 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1383 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1384 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1385 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1386 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1387 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1388 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1389 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1390 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1391 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1392 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1393 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1394 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1395 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1396 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1397 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1398 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1399 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1400 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1401 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1402 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1403 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1404 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1405 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1406 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1407 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1408 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1409 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1410 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1411 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1412 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1413 };
1414
1415 unsigned char k;
1416
1417 for (k=0; k < 6; k++)
1418 addr[k] = reverse_data[addr[k]];
1419}
1420
2d21ac55
A
1421static int elap_trackMcast(at_ifaddr_t *, int, caddr_t);
1422
1c79356b
A
1423static int elap_trackMcast(patp, func, addr)
1424 at_ifaddr_t *patp;
1425 int func;
1426 caddr_t addr;
1427{
1428 int i, loc=-1;
1429 u_char c;
1430 switch(patp->aa_ifp->if_type) {
1431 case IFT_ETHER:
91447636
A
1432 case IFT_FDDI:
1433 case IFT_L2VLAN:
1434 case IFT_IEEE8023ADLAG: /* bonded ethernet */
1c79356b
A
1435 /* set addr to point to unique part of addr */
1436 c = addr[5];
1437
1438 /* first try to find match */
1439 /* *** save just one byte of the multicast address? *** */
1440 for (i=0; i< MAX_MCASTS; i++)
1441 if (c == patp->mcast[i]) {
1442 loc = i;
1443 break;
1444 }
1445
1446 switch (func) {
1447 case MCAST_TRACK_DELETE:
1448 if (loc >= 0)
1449 patp->mcast[loc] = 0;
1450
1451 break;
1452 case MCAST_TRACK_ADD:
1453 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add loc:%d\n", i));
1454 if (loc >= 0) {
1455 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, addr was there\n"));
1456 return(1);
1457 break; /* already there */
1458 }
1459 for (i=0; i< MAX_MCASTS; i++)
1460 if (patp->mcast[i] == 0) {
1461 loc = i;
1462 break;
1463 }
1464 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add1 loc:%d\n", i));
1465 if (loc >= 0) {
1466 patp->mcast[loc] = c;
1467 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, adding(%x)\n",
1468 (*(int*)addr)&0xffffff));
1469 }
1470 else {
1471 /*errno = ENOMEM; */ /*LD 5/7/97 nobody is using that */
1472 return(-1);
1473 }
1474 break;
1475 case MCAST_TRACK_CHECK:
1476 if (loc >= 0) {
1477 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:check, addr was there\n"));
1478 return(0);
1479 }
1480 else {
1481 dPrintf(D_M_PAT_LOW, D_L_USR2, ("mctrack:add, addr was NOT there\n"));
1482 return(-1);
1483 }
1484
1485 default:
1486 /*errno = EINVAL;*/ /*LD 5/7/97 nobody is using that */
1487 return(-1);
1488 }
1489
1490 case IFT_ISO88025: /* token ring */
1491 /* we would use the lowest byte of the addr argument as a value
1492 to shift left a 1 to form the mcast mask for TR. We'll do this
1493 when the time comes
1494 */
1495 default:
1496 ;
1497 }
1498 return(0);
1499}
1500
1501
2d21ac55 1502static int getSnmpCfg(snmp)
1c79356b
A
1503 snmpCfg_t *snmp;
1504{
1505 int i;
1506 at_ifaddr_t *elapp;
1507 snmpIfCfg_t *ifc;
1508
1509 snmp->cfg_ifCnt = 0;
1510
1511 bzero(snmp,sizeof(snmpCfg_t));
1512 for (i=0, elapp=at_interfaces,ifc=snmp->cfg_ifCfg;
1513 i<IF_TOTAL_MAX; i++, elapp++, ifc++) {
1514 if (elapp->ifState != LAP_OFFLINE) {
1515 snmp->cfg_ifCnt++;
8f6c56a5 1516 strlcpy(ifc->ifc_name,elapp->ifName, sizeof(ifc->ifc_name));
1c79356b
A
1517 ifc->ifc_aarpSize = getAarpTableSize(i);
1518 ifc->ifc_addrSize = getPhysAddrSize(i);
1519 switch (elapp->aa_ifp->if_type) {
1520 case IFT_ETHER:
91447636
A
1521 case IFT_L2VLAN:
1522 case IFT_IEEE8023ADLAG: /* bonded ethernet */
1c79356b
A
1523 ifc->ifc_type = SNMP_TYPE_ETHER2;
1524 break;
1525 case IFT_ISO88025: /* token ring */
1526 ifc->ifc_type = SNMP_TYPE_TOKEN;
1527 break;
1528 case IFT_FDDI:
1529 default:
1530 ifc->ifc_type = SNMP_TYPE_OTHER;
1531 break;
1532 }
1533 ifc->ifc_start = elapp->ifThisCableStart;
1534 ifc->ifc_end = elapp->ifThisCableEnd;
1535 ifc->ifc_ddpAddr= elapp->ifThisNode;
1536 ifc->ifc_status = elapp->ifState == LAP_ONLINE ? 1 : 2;
1537 ifc->ifc_zoneName.len = 0;
1538 if (elapp->ifZoneName.len != 0) {
1539 ifc->ifc_zoneName = elapp->ifZoneName;
1540 }
1541 else if (elapp->ifDefZone) {
1542 ifc->ifc_zoneName = ZT_table[elapp->ifDefZone-1].Zone;
1543 }
1544 else /* temp, debug only */
1545 ifc->ifc_zoneName = ZT_table[0].Zone;
1546 if (ROUTING_MODE) {
1547 if (elapp->ifFlags & RTR_SEED_PORT) {
1548 ifc->ifc_netCfg = SNMP_CFG_CONFIGURED;
1549 ifc->ifc_zoneCfg = SNMP_CFG_CONFIGURED;
1550 }
1551 else {
1552 ifc->ifc_netCfg = SNMP_CFG_GARNERED;
1553 ifc->ifc_zoneCfg = SNMP_CFG_GARNERED;
1554 }
1555 }
1556 else { /* single-port mode */
1557 if (elapp->ifRouterState == ROUTER_AROUND) {
1558 ifc->ifc_netCfg = SNMP_CFG_GARNERED;
1559 }
1560 else {
1561 ifc->ifc_netCfg = SNMP_CFG_GUESSED;
1562 ifc->ifc_zoneCfg = SNMP_CFG_UNCONFIG;
1563 }
1564 }
1565 }
1566 }
1567 snmp->cfg_flags = at_state.flags;
1568
1569
1570 return(0);
1571}
1572
1573int at_reg_mcast(ifID, data)
1574 at_ifaddr_t *ifID;
1575 caddr_t data;
1576{
1577 struct ifnet *nddp = ifID->aa_ifp;
91447636 1578 struct sockaddr_dl sdl;
1c79356b
A
1579
1580 if (*(int *)data) {
1581 if (!nddp) {
1582 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
1583 return(-1);
1584 }
1585
1586 if (elap_trackMcast(ifID, MCAST_TRACK_ADD, data) == 1)
1587 return(0);
1588
1589 /* this is for ether_output */
91447636
A
1590 bzero(&sdl, sizeof(sdl));
1591 sdl.sdl_family = AF_LINK;
1592 sdl.sdl_alen = sizeof(struct etalk_addr);
1593 sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data)
1594 + sizeof(struct etalk_addr);
1595 bcopy(data, sdl.sdl_data, sizeof(struct etalk_addr));
1596 /* these next two lines should not really be needed XXX */
1597 sdl.sdl_index = nddp->if_index;
1598 sdl.sdl_type = IFT_ETHER;
1c79356b
A
1599
1600 dPrintf(D_M_PAT, D_L_STARTUP,
1601 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1602 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff,
1603 (unsigned)ifID));
1604
2d21ac55 1605 if (if_addmulti(nddp, (struct sockaddr *)&sdl, 0))
1c79356b
A
1606 return -1;
1607 }
1608 return 0;
1609
1610}
1611
1612int at_unreg_mcast(ifID, data)
1613 at_ifaddr_t *ifID;
1614 caddr_t data;
1615{
1616 struct ifnet *nddp = ifID->aa_ifp;
91447636 1617 struct sockaddr_dl sdl;
1c79356b
A
1618
1619 if (*(int *)data) {
1620 if (!nddp) {
1621 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
1622 return(-1);
1623 }
1624
1625 elap_trackMcast(ifID, MCAST_TRACK_DELETE, data);
1626
1627 /* this is for ether_output */
91447636
A
1628 bzero(&sdl, sizeof(sdl));
1629 sdl.sdl_family = AF_LINK;
1630 sdl.sdl_alen = sizeof(struct etalk_addr);
1631 sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data)
1632 + sizeof(struct etalk_addr);
1633 bcopy(data, sdl.sdl_data, sizeof(struct etalk_addr));
1634 /* these next two lines should not really be needed XXX */
1635 sdl.sdl_index = nddp->if_index;
1636 sdl.sdl_type = IFT_ETHER;
1c79356b
A
1637
1638 dPrintf(D_M_PAT, D_L_STARTUP,
1639 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1640 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff,
1641 (unsigned)ifID));
1642 bzero(data, sizeof(struct etalk_addr));
1643
2d21ac55 1644 if (if_delmulti(nddp, (struct sockaddr *)&sdl))
1c79356b
A
1645 return -1;
1646 }
1647 return 0;
1648}
1649#ifdef NOT_YET
1650/* *** at_reg_mcast() and at_unreg_mcast() should be replaced as soon as the
1651 new code to allow an AF_LINK address family multicast to be (un)registered
1652 using the SIOCADDMULTI / SIOCDELMULTI ioctls has been completed.
1653
1654 The issue is that the "struct sockaddr_dl" needed for the AF_LINK does not
1655 fit in the "struct ifreq" that is used for these ioctls, and we do not want
1656 Blue/Classic, which currently uses AF_UNSPEC, to use a different address
1657 family multicast address than Mac OS X uses.
1658 *** */
1659
1660int at_reg_mcast(ifID, data)
1661 at_ifaddr_t *ifID;
1662 caddr_t data;
1663{
1664 struct ifnet *nddp = ifID->aa_ifp;
1665 struct sockaddr_dl sdl;
1666
1667 if (*(int *)data) {
1668 if (!nddp) {
1669 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
1670 return(-1);
1671 }
1672 if (elap_trackMcast(ifID, MCAST_TRACK_ADD, data) == 1)
1673 return(0);
1674
1675 sdl.sdl_len = sizeof(struct sockaddr_dl);
1676 sdl.sdl_family = AF_LINK;
1677 sdl.sdl_index = 0;
1678 sdl.sdl_type = nddp->if_type;
1679 sdl.sdl_alen = nddp->if_addrlen;
1680 sdl.sdl_slen = 0;
1681 sdl.sdl_nlen = sprintf(sdl.sdl_data, "%s%d",
1682 nddp->if_name , nddp->if_unit);
1683 bcopy(data, LLADDR(&sdl), sdl.sdl_alen);
1684
1685 dPrintf(D_M_PAT, D_L_STARTUP,
1686 ("pat_mcast: adding multicast %08x%04x ifID:0x%x\n",
1687 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff,
1688 (unsigned)ifID));
1689
1690 if (if_addmulti(nddp, (struct sockaddr *)&sdl, 0))
1691 return -1;
1692 }
1693
1694 return 0;
1695}
1696
1697int at_unreg_mcast(ifID, data)
1698 at_ifaddr_t *ifID;
1699 caddr_t data;
1700{
1701 struct ifnet *nddp = ifID->aa_ifp;
1702 struct sockaddr_dl sdl;
1703
1704 if (*(int *)data) {
1705 if (!nddp) {
1706 dPrintf(D_M_PAT, D_L_STARTUP, ("pat_mcast: BAD ndpp\n"));
1707 return(-1);
1708 }
1709
1710 elap_trackMcast(ifID, MCAST_TRACK_DELETE, data);
1711
1712 sdl.sdl_len = sizeof(struct sockaddr_dl);
1713 sdl.sdl_family = AF_LINK;
1714 sdl.sdl_index = 0;
1715 sdl.sdl_type = nddp->if_type;
1716 sdl.sdl_alen = nddp->if_addrlen;
1717 sdl.sdl_slen = 0;
1718 sdl.sdl_nlen = sprintf(sdl.sdl_data, "%s%d",
1719 nddp->if_name , nddp->if_unit);
1720
1721 dPrintf(D_M_PAT, D_L_STARTUP,
1722 ("pat_mcast: deleting multicast %08x%04x ifID:0x%x\n",
1723 *(unsigned*)data, (*(unsigned *)(data+2))&0x0000ffff,
1724 (unsigned)ifID));
1725 bzero(data, ETHERNET_ADDR_LEN);
1726
1727 if (if_delmulti(nddp, (struct sockaddr *)&sdl))
1728 return(-1);
1729 }
1730
1731 return 0;
1732}
1733
1734#endif