|
|
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) 1993-1998 Apple Computer, Inc.
24: * All Rights Reserved.
25: */
26:
27: /*
28: * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
29: */
30:
31: #include <sys/errno.h>
32: #include <sys/types.h>
33: #include <sys/param.h>
34: #include <machine/spl.h>
35: #include <sys/systm.h>
36: #include <sys/kernel.h>
37: #include <sys/proc.h>
38: #include <sys/filedesc.h>
39: #include <sys/fcntl.h>
40: #include <sys/mbuf.h>
41: #include <sys/ioctl.h>
42: #include <sys/malloc.h>
43: #include <sys/socket.h>
44: #include <sys/socketvar.h>
45:
46: #include <net/if.h>
47:
48: #include <netat/sysglue.h>
49: #include <netat/appletalk.h>
50: #include <netat/at_var.h>
51: #include <netat/ddp.h>
52: #include <netat/rtmp.h>
53: #include <netat/lap.h>
54: #include <netat/zip.h>
55: #include <netat/routing_tables.h>
56: #include <netat/debug.h>
57: #include <netat/at_pcb.h>
58:
59: extern void rtmp_router_input();
60:
61: /****************************************************************/
62: /* */
63: /* */
64: /* RTMP Protocol */
65: /* */
66: /* */
67: /****************************************************************/
68:
69:
70: /* rtmp.c: , 1.6; 2/26/93; Apple Computer, Inc." */
71:
72:
73: #define NROUTERS2TRAK 8
74: #define FIFTYSECS 10
75: #define NODE(r) ((r)->ifARouter.s_node)
76: #define NET(r) ((r)->ifARouter.s_net)
77: #define INUSE(r) (NODE(r))
78:
79: void ddp_age_router();
80:
81: static struct routerinfo {
82: struct at_addr ifARouter;
83: at_ifaddr_t *ifID;
84: void *tmo;
85: } trackedrouters[NROUTERS2TRAK];
86:
87: void trackrouter_rem_if(ifID)
88: register at_ifaddr_t *ifID;
89: {
90: register i;
91: register struct routerinfo *router;
92:
93: for (i = NROUTERS2TRAK; --i >= 0;) {
94: router = &trackedrouters[i];
95: if (trackedrouters[i].ifID == ifID) {
96: untimeout(ddp_age_router, (caddr_t)router);
97: break;
98: }
99: }
100: }
101:
102:
103: void routershutdown()
104: {
105: register i;
106:
107: for (i = NROUTERS2TRAK; --i >= 0;) {
108: register struct routerinfo *router;
109:
110: router = &trackedrouters[i];
111: if (INUSE(router)) {
112: untimeout(ddp_age_router, (caddr_t) router);
113: bzero((caddr_t) router, sizeof(struct routerinfo));
114: }
115: }
116: }
117:
118: int router_added = 0;
119: int router_killed = 0;
120:
121:
122:
123: void trackrouter(ifID, net, node)
124: register at_ifaddr_t *ifID;
125: register unsigned short net;
126: register unsigned char node;
127: {
128: register struct routerinfo *unused = NULL;
129: register i;
130:
131: for (i = NROUTERS2TRAK; --i >= 0;) {
132: register struct routerinfo *router;
133:
134: router = &trackedrouters[(i + node) & (NROUTERS2TRAK-1)];
135: if ((NODE(router) == node) && (NET(router) == net)) {
136: untimeout(ddp_age_router, (caddr_t) router);
137: timeout(ddp_age_router, (caddr_t) router, 50*SYS_HZ);
138: unused = NULL;
139: break;
140: }
141: else if (!INUSE(router) && !unused)
142: unused = router;
143: }
144: if (unused) {
145: router_added++;
146:
147: unused->ifID = ifID;
148: NET(unused) = net;
149: NODE(unused) = node;
150: timeout(ddp_age_router, (caddr_t) unused, 50*SYS_HZ);
151: if (NET(ifID) == 0 && NODE(ifID) == 0) {
152: NET(ifID) = net;
153: NODE(ifID) = node;
154: ifID->ifRouterState = ROUTER_AROUND;
155: }
156: }
157: }
158:
159: /*
160: * This is the timeout function that is called after 50 seconds,
161: * if no router packets come in. That way we won't send extended
162: * frames to something that is not there. Untimeout is called if
163: * an RTMP packet comes in so this routine will not be called.
164: */
165: void ddp_age_router(deadrouter)
166: register struct routerinfo *deadrouter;
167: {
168: register at_ifaddr_t *ourrouter = deadrouter->ifID;
169:
170: dPrintf(D_M_RTMP, D_L_INFO,
171: ("ddp_age_router called deadrouter=%d:%d\n", NODE(deadrouter), NET(deadrouter)));
172:
173: router_killed++;
174:
175: if (NODE(ourrouter) == NODE(deadrouter) &&
176: NET(ourrouter) == NET(deadrouter)) {
177: register unsigned long atrandom = random();
178: register struct routerinfo *newrouter;
179: register i;
180:
181: bzero((caddr_t) deadrouter, sizeof(struct routerinfo));
182: for (i = NROUTERS2TRAK; --i >= 0;) {
183: newrouter = &trackedrouters[(i + atrandom) & (NROUTERS2TRAK-1)];
184: if (INUSE(newrouter))
185: break;
186: else
187: newrouter = NULL;
188: }
189: if (newrouter) {
190: NET(ourrouter) = NET(newrouter);
191: NODE(ourrouter) = NODE(newrouter);
192: }
193: else {
194: /* from gorouterless() */
195: ATTRACE(AT_MID_DDP, AT_SID_TIMERS, AT_LV_WARNING, FALSE,
196: "ddp_age_router entry : ARouter = 0x%x, RouterState = 0x%x",
197: ATALK_VALUE(ourrouter->ifARouter), ourrouter->ifRouterState, 0);
198:
199: switch (ourrouter->ifRouterState) {
200: case ROUTER_AROUND :
201: ourrouter->ifARouter.s_net = 0;
202: ourrouter->ifARouter.s_node = 0;
203: dPrintf(D_M_RTMP,D_L_INFO,
204: ("rtmp.c Gorouterless!!!!!!!!\n"));
205: ourrouter->ifThisCableStart = DDP_MIN_NETWORK;
206: ourrouter->ifThisCableEnd = DDP_MAX_NETWORK;
207: ourrouter->ifRouterState = NO_ROUTER;
208: zip_control(ourrouter, ZIP_NO_ROUTER);
209: break;
210: case ROUTER_WARNING :
211: /* there was a router that we were ignoring...
212: * now, even that's gone. But we want to tackle the
213: * case where another router may come up after all
214: * of them have died...
215: */
216: ourrouter->ifRouterState = NO_ROUTER;
217: break;
218: }
219: }
220: } else
221: bzero((caddr_t) deadrouter, sizeof(struct routerinfo));
222: } /* ddp_age_router */
223:
224: void rtmp_input (mp, ifID)
225: register gbuf_t *mp;
226: register at_ifaddr_t *ifID;
227: {
228: register at_net_al this_net;
229: register at_net_al range_start, range_end;
230: register at_ddp_t *ddp = (at_ddp_t *)gbuf_rptr(mp);
231: /* NOTE: there is an assumption here that the
232: * DATA follows the header. */
233: register at_rtmp *rtmp = (at_rtmp *)ddp->data;
234:
235: if (gbuf_type(mp) != MSG_DATA) {
236: /* If this is a M_ERROR message, DDP is shutting down,
237: * nothing to do here...If it's something else, we don't
238: * understand what it is
239: */
240: gbuf_freem(mp);
241: return;
242: }
243:
244: if (!ifID) {
245: gbuf_freem(mp);
246: return;
247: }
248: if (gbuf_len(mp) < (DDP_X_HDR_SIZE + sizeof(at_rtmp))) {
249: gbuf_freem(mp);
250: return;
251: }
252: this_net = ifID->ifThisNode.s_net;
253: if (rtmp->at_rtmp_id_length != 8) {
254: gbuf_freem(mp);
255: return;
256: }
257:
258: {
259: at_rtmp_tuple *tp;
260: tp = ((at_rtmp_tuple *)&rtmp->at_rtmp_id[1]);
261: range_start = NET_VALUE(tp->at_rtmp_net);
262: tp = ((at_rtmp_tuple *)&rtmp->at_rtmp_id[4]);
263: range_end = NET_VALUE(tp->at_rtmp_net);
264:
265: if (ifID->ifRouterState == ROUTER_AROUND) {
266: if ((ifID->ifThisCableStart == range_start) &&
267: (ifID->ifThisCableEnd == range_end)) {
268: trackrouter(ifID,
269: NET_VALUE(rtmp->at_rtmp_this_net),
270: rtmp->at_rtmp_id[0]
271: );
272: }
273: } else {
274: /* There was no router around earlier, one
275: * probably just came up.
276: */
277: if ((this_net >= DDP_STARTUP_LOW) &&
278: (this_net <= DDP_STARTUP_HIGH)) {
279: /* we're operating in the startup range,
280: * ignore the presence of router
281: */
282: if (ifID->ifRouterState == NO_ROUTER) {
283: dPrintf(D_M_RTMP, D_L_STARTUP,
284: ("Warning: new router came up: invalid startup net/node\n"));
285: trackrouter(ifID,
286: NET_VALUE(rtmp->at_rtmp_this_net),
287: rtmp->at_rtmp_id[0]
288: );
289: ifID->ifRouterState = ROUTER_WARNING;
290: }
291: } else {
292: /* our address
293: * is not in startup range; Is our
294: * address good for the cable??
295: */
296: if ((this_net >= range_start) &&
297: (this_net <= range_end)) {
298: /* Our address is in the range
299: * valid for this cable... Note
300: * the router address and then
301: * get ZIP rolling to get the
302: * zone info.
303: */
304: ifID->ifThisCableStart = range_start;
305: ifID->ifThisCableEnd = range_end;
306: trackrouter(ifID,
307: NET_VALUE(rtmp->at_rtmp_this_net),
308: rtmp->at_rtmp_id[0]
309: );
310: zip_control(ifID, ZIP_LATE_ROUTER);
311: } else {
312: /* Our address is not in the
313: * range valid for this cable..
314: * ignore presence of the
315: * router
316: */
317: if (ifID->ifRouterState == NO_ROUTER) {
318: dPrintf(D_M_RTMP,D_L_ERROR,
319: ("Warning: new router came up: invalid net/node\n"));
320: trackrouter(ifID,
321: NET_VALUE(rtmp->at_rtmp_this_net),
322: rtmp->at_rtmp_id[0]
323: );
324: ifID->ifRouterState = ROUTER_WARNING;
325: }
326: }
327: }
328: }
329: }
330:
331: gbuf_freem(mp);
332: return;
333: }
334:
335:
336: void rtmp_init()
337: {
338: bzero((caddr_t)trackedrouters, sizeof(struct routerinfo)*NROUTERS2TRAK);
339: }
340:
341:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.