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