|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1993-1998 Apple Computer, Inc.
27: * All Rights Reserved.
28: *
29: * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF APPLE COMPUTER, INC.
30: * The copyright notice above does not evidence any actual or
31: * intended publication of such source code.
32: */
33:
34: #include <sysglue.h>
35:
36: #include <at/appletalk.h>
37: #include <at/ddp.h>
38: #include <rtmp.h>
39: #include <lap.h>
40:
41: #include <at/at_lap.h>
42: #include <at_ddp.h>
43: #include <at_zip.h>
44: #include <routing_tables.h>
45: #include <atlog.h>
46:
47: extern void *atalk_timeout();
48: extern void atalk_untimeout();
49: extern void rtmp_router_input();
50:
51: /****************************************************************/
52: /* */
53: /* */
54: /* RTMP Protocol */
55: /* */
56: /* */
57: /****************************************************************/
58:
59:
60: /* rtmp.c: , 1.6; 2/26/93; Apple Computer, Inc." */
61:
62:
63: #define NROUTERS2TRAK 8
64: #define FIFTYSECS 10
65: #define NODE(r) ((r)->ifARouter.atalk_node)
66: #define NET(r) ((r)->ifARouter.atalk_net)
67: #define INUSE(r) (NODE(r))
68:
69: void ddp_age_router();
70:
71:
72:
73: static struct routerinfo {
74: struct atalk_addr ifARouter;
75: at_if_t *ifID;
76: void *tmo;
77: } trackedrouters[NROUTERS2TRAK];
78:
79: void trackrouter_rem_if(ifID)
80: register at_if_t *ifID;
81: {
82: register i;
83: register struct routerinfo *router;
84:
85: for (i = NROUTERS2TRAK; --i >= 0;) {
86: router = &trackedrouters[i];
87: if (trackedrouters[i].ifID == ifID) {
88: atalk_untimeout(ddp_age_router, (caddr_t) router, router->tmo);
89: break;
90: }
91: }
92: }
93:
94:
95: void routershutdown()
96: {
97: register i;
98:
99: for (i = NROUTERS2TRAK; --i >= 0;) {
100: register struct routerinfo *router;
101:
102: router = &trackedrouters[i];
103: if (INUSE(router)) {
104: atalk_untimeout(ddp_age_router, (caddr_t) router, router->tmo);
105: bzero((caddr_t) router, sizeof(struct routerinfo));
106: }
107: }
108: }
109:
110: int router_added = 0;
111: int router_killed = 0;
112:
113:
114:
115: void trackrouter(ifID, net, node)
116: register at_if_t *ifID;
117: register unsigned short net;
118: register unsigned char node;
119: {
120: register struct routerinfo *unused = NULL;
121: register i;
122:
123: for (i = NROUTERS2TRAK; --i >= 0;) {
124: register struct routerinfo *router;
125:
126: router = &trackedrouters[(i + node) & (NROUTERS2TRAK-1)];
127: if ((NODE(router) == node) && (NET_VALUE(NET(router)) == net)) {
128: atalk_untimeout(ddp_age_router, (caddr_t) router, router->tmo);
129: router->tmo = atalk_timeout(ddp_age_router, (caddr_t) router, 50*SYS_HZ);
130: unused = NULL;
131: break;
132: }
133: else if (!INUSE(router) && !unused)
134: unused = router;
135: }
136: if (unused) {
137: router_added++;
138:
139: unused->ifID = ifID;
140: NET_ASSIGN(NET(unused), net);
141: NODE(unused) = node;
142: unused->tmo = atalk_timeout(ddp_age_router, (caddr_t) unused, 50*SYS_HZ);
143: if (NET_EQUAL0(NET(ifID)) && NODE(ifID) == 0) {
144: NET_ASSIGN(NET(ifID), net);
145: NODE(ifID) = node;
146: ifID->ifRouterState = ROUTER_AROUND;
147: }
148: }
149: }
150:
151:
152:
153: void ddp_age_router(deadrouter)
154: register struct routerinfo *deadrouter;
155: {
156: register at_if_t *ourrouter = deadrouter->ifID;
157:
158: dPrintf(D_M_RTMP, D_L_INFO,
159: ("ddp_age_router called deadrouter=%d:%d\n", NODE(deadrouter), NET(deadrouter)));
160:
161: router_killed++;
162:
163: if (NODE(ourrouter) == NODE(deadrouter) &&
164: NET_EQUAL(NET(ourrouter), NET(deadrouter))) {
165: register unsigned long atrandom = random();
166: register struct routerinfo *newrouter;
167: register i;
168:
169: bzero((caddr_t) deadrouter, sizeof(struct routerinfo));
170: for (i = NROUTERS2TRAK; --i >= 0;) {
171: newrouter = &trackedrouters[(i + atrandom) & (NROUTERS2TRAK-1)];
172: if (INUSE(newrouter))
173: break;
174: else
175: newrouter = NULL;
176: }
177: if (newrouter) {
178: NET_NET(NET(ourrouter), NET(newrouter));
179: NODE(ourrouter) = NODE(newrouter);
180: }
181: else {
182: void gorouterless();
183: gorouterless(ourrouter);
184: }
185: } else
186: bzero((caddr_t) deadrouter, sizeof(struct routerinfo));
187: }
188:
189:
190:
191: /*
192: * This is the timeout function that is called after 50 seconds,
193: * if no router packets come in. That way we won't send extended
194: * frames to something that is not there. Untimeout is called if
195: * an RTMP packet comes in so this routine will not be called.
196: */
197:
198: static void gorouterless(int_ifID)
199: {
200: register at_if_t *ifID = (at_if_t *)int_ifID;
201:
202: ATTRACE(AT_MID_DDP, AT_SID_TIMERS, AT_LV_WARNING, FALSE,
203: "ddp_age_router entry : ARouter = 0x%x, RouterState = 0x%x",
204: ATALK_VALUE(ifID->ifARouter), ifID->ifRouterState, 0);
205:
206: switch (ifID->ifRouterState) {
207: case ROUTER_AROUND :
208: ATALK_ASSIGN(ifID->ifARouter, 0, 0, 0);
209: dPrintf(D_M_RTMP,D_L_INFO,
210: ("rtmp.c Gorouterless!!!!!!!!\n"));
211: ifID->ifThisCableStart = 2;
212: ifID->ifThisCableEnd = 0xfffd;
213: ifID->ifRouterState = NO_ROUTER;
214: zip_control (ifID, ZIP_NO_ROUTER);
215: break;
216: case ROUTER_WARNING :
217: /* there was a router that we were ignoring...
218: * now, even that's gone. But we want to tackle the
219: * case where another router may come up after all
220: * of them have died...
221: */
222: ifID->ifRouterState = NO_ROUTER;
223: break;
224: }
225: }
226:
227:
228:
229: void
230: rtmp_input (mp, ifID)
231: register gbuf_t *mp;
232: register at_if_t *ifID;
233: {
234: register at_net_al this_net;
235: register at_net_al range_start, range_end;
236: register at_ddp_t *ddp = (at_ddp_t *)gbuf_rptr(mp);
237: /* NOTE: there is an assumption here that the
238: * DATA follows the header. */
239: register at_rtmp *rtmp = (at_rtmp *)ddp->data;
240:
241: if (gbuf_type(mp) != MSG_DATA) {
242: /* If this is a M_ERROR message, DDP is shutting down,
243: * nothing to do here...If it's something else, we don't
244: * understand what it is
245: */
246: gbuf_freem(mp);
247: return;
248: }
249:
250: if (!ifID) {
251: gbuf_freem(mp);
252: return;
253: }
254: if (gbuf_len(mp) < (DDP_X_HDR_SIZE + sizeof(at_rtmp))) {
255: gbuf_freem(mp);
256: return;
257: }
258: this_net = NET_VALUE(ifID->ifThisNode.atalk_net);
259: if (rtmp->at_rtmp_id_length != 8) {
260: gbuf_freem(mp);
261: return;
262: }
263:
264: {
265: at_rtmp_tuple *tp;
266: tp = ((at_rtmp_tuple *)&rtmp->at_rtmp_id[1]);
267: range_start = NET_VALUE(tp->at_rtmp_net);
268: tp = ((at_rtmp_tuple *)&rtmp->at_rtmp_id[4]);
269: range_end = NET_VALUE(tp->at_rtmp_net);
270:
271: if (ifID->ifRouterState == ROUTER_AROUND) {
272: if ((ifID->ifThisCableStart == range_start) &&
273: (ifID->ifThisCableEnd == range_end)) {
274: trackrouter(
275: ifID,
276: NET_VALUE(rtmp->at_rtmp_this_net),
277: rtmp->at_rtmp_id[0]
278: );
279: }
280: } else {
281: /* There was no router around earlier, one
282: * probably just came up.
283: */
284: if ((this_net >= DDP_STARTUP_LOW) &&
285: (this_net <= DDP_STARTUP_HIGH)) {
286: /* we're operating in the startup range,
287: * ignore the presence of router
288: */
289: if (ifID->ifRouterState == NO_ROUTER) {
290: dPrintf(D_M_RTMP, D_L_STARTUP,
291: ("Warning: new router came up: invalid startup net/node\n"));
292: trackrouter(
293: ifID,
294: NET_VALUE(rtmp->at_rtmp_this_net),
295: rtmp->at_rtmp_id[0]
296: );
297: ifID->ifRouterState = ROUTER_WARNING;
298: }
299: } else {
300: /* our address
301: * is not in startup range; Is our
302: * address good for the cable??
303: */
304: if ((this_net >= range_start) &&
305: (this_net <= range_end)) {
306: /* Our address is in the range
307: * valid for this cable... Note
308: * the router address and then
309: * get ZIP rolling to get the
310: * zone info.
311: */
312: ifID->ifThisCableStart = range_start;
313: ifID->ifThisCableEnd = range_end;
314: trackrouter(
315: ifID,
316: NET_VALUE(rtmp->at_rtmp_this_net),
317: rtmp->at_rtmp_id[0]
318: );
319: zip_control(ifID, ZIP_LATE_ROUTER);
320: } else {
321: /* Our address is not in the
322: * range valid for this cable..
323: * ignore presence of the
324: * router
325: */
326: if (ifID->ifRouterState == NO_ROUTER) {
327: dPrintf(D_M_RTMP,D_L_ERROR,
328: ("Warning: new router came up: invalid net/node\n"));
329: trackrouter(
330: ifID,
331: NET_VALUE(rtmp->at_rtmp_this_net),
332: rtmp->at_rtmp_id[0]
333: );
334: ifID->ifRouterState =
335: ROUTER_WARNING;
336: }
337: }
338: }
339: }
340: }
341:
342: gbuf_freem(mp);
343: return;
344: }
345:
346:
347: int rtmp_init()
348: {
349: bzero((caddr_t) trackedrouters, sizeof(struct routerinfo)*NROUTERS2TRAK);
350:
351: if (!ROUTING_MODE)
352: return((int)rtmp_input);
353:
354: else
355: return ((int)rtmp_router_input);
356: }
357:
358:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.