]> git.saurik.com Git - apple/xnu.git/blame - bsd/netat/ddp_rtmp.c
xnu-792.6.56.tar.gz
[apple/xnu.git] / bsd / netat / ddp_rtmp.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
ff6e181a
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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
1c79356b 12 *
ff6e181a
A
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
ff6e181a
A
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
1c79356b
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 * Copyright (c) 1993-1998 Apple Computer, Inc.
25 * All Rights Reserved.
26 */
27
28/*
29 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
30 */
31
32#include <sys/errno.h>
33#include <sys/types.h>
34#include <sys/param.h>
35#include <machine/spl.h>
36#include <sys/systm.h>
37#include <sys/kernel.h>
38#include <sys/proc.h>
39#include <sys/filedesc.h>
40#include <sys/fcntl.h>
41#include <sys/mbuf.h>
42#include <sys/ioctl.h>
43#include <sys/malloc.h>
44#include <sys/socket.h>
45#include <sys/socketvar.h>
46
47#include <net/if.h>
48
49#include <netat/sysglue.h>
50#include <netat/appletalk.h>
51#include <netat/at_var.h>
52#include <netat/ddp.h>
53#include <netat/rtmp.h>
54#include <netat/zip.h>
55#include <netat/routing_tables.h>
56#include <netat/debug.h>
57#include <netat/at_pcb.h>
58
9bccf70c
A
59#include <sys/kern_event.h>
60
1c79356b
A
61extern void rtmp_router_input();
62
63/****************************************************************/
64/* */
65/* */
66/* RTMP Protocol */
67/* */
68/* */
69/****************************************************************/
70
71
72/* rtmp.c: , 1.6; 2/26/93; Apple Computer, Inc." */
73
74
75#define NROUTERS2TRAK 8
76#define FIFTYSECS 10
77#define NODE(r) ((r)->ifARouter.s_node)
78#define NET(r) ((r)->ifARouter.s_net)
79#define INUSE(r) (NODE(r))
80
81void ddp_age_router();
82
83static struct routerinfo {
84 struct at_addr ifARouter;
85 at_ifaddr_t *ifID;
86 void *tmo;
87} trackedrouters[NROUTERS2TRAK];
88
89void trackrouter_rem_if(ifID)
90 register at_ifaddr_t *ifID;
91{
92 register i;
93 register struct routerinfo *router;
94
95 for (i = NROUTERS2TRAK; --i >= 0;) {
96 router = &trackedrouters[i];
97 if (trackedrouters[i].ifID == ifID) {
98 untimeout(ddp_age_router, (caddr_t)router);
99 break;
100 }
101 }
102}
103
104
105void routershutdown()
106{
107 register i;
108
109 for (i = NROUTERS2TRAK; --i >= 0;) {
110 register struct routerinfo *router;
111
112 router = &trackedrouters[i];
113 if (INUSE(router)) {
114 untimeout(ddp_age_router, (caddr_t) router);
115 bzero((caddr_t) router, sizeof(struct routerinfo));
116 }
117 }
118}
119
120int router_added = 0;
121int router_killed = 0;
122
123
124
125void trackrouter(ifID, net, node)
126 register at_ifaddr_t *ifID;
127 register unsigned short net;
128 register unsigned char node;
129{
130 register struct routerinfo *unused = NULL;
131 register i;
132
133 for (i = NROUTERS2TRAK; --i >= 0;) {
134 register struct routerinfo *router;
135
136 router = &trackedrouters[(i + node) & (NROUTERS2TRAK-1)];
137 if ((NODE(router) == node) && (NET(router) == net)) {
138 untimeout(ddp_age_router, (caddr_t) router);
139 timeout(ddp_age_router, (caddr_t) router, 50*SYS_HZ);
140 unused = NULL;
141 break;
142 }
143 else if (!INUSE(router) && !unused)
144 unused = router;
145 }
146 if (unused) {
9bccf70c 147 router_added++;
1c79356b 148
9bccf70c
A
149 if (ifID->ifARouter.s_net == 0) {
150 /* Send event that this interface just got a router. This does not
151 discriminate on whether this router is valid or not. If it is not
152 valid rtmp_input will send a KEV_ATALK_ROUTERUP_INVALID event. */
153 atalk_post_msg(ifID->aa_ifp, KEV_ATALK_ROUTERUP, 0, 0);
154 }
155
1c79356b
A
156 unused->ifID = ifID;
157 NET(unused) = net;
158 NODE(unused) = node;
9bccf70c 159 ifID->ifRouterState = ROUTER_AROUND;
1c79356b 160 timeout(ddp_age_router, (caddr_t) unused, 50*SYS_HZ);
9bccf70c 161
1c79356b
A
162 if (NET(ifID) == 0 && NODE(ifID) == 0) {
163 NET(ifID) = net;
164 NODE(ifID) = node;
1c79356b
A
165 }
166 }
167}
168
169/*
170 * This is the timeout function that is called after 50 seconds,
171 * if no router packets come in. That way we won't send extended
172 * frames to something that is not there. Untimeout is called if
173 * an RTMP packet comes in so this routine will not be called.
174 */
175void ddp_age_router(deadrouter)
176 register struct routerinfo *deadrouter;
177{
91447636 178 register at_ifaddr_t *ourrouter;
1c79356b 179
91447636
A
180 atalk_lock();
181
182 ourrouter = deadrouter->ifID;
183 if (ourrouter == NULL) {
184 atalk_unlock();
185 return;
186 }
1c79356b
A
187
188 dPrintf(D_M_RTMP, D_L_INFO,
189 ("ddp_age_router called deadrouter=%d:%d\n", NODE(deadrouter), NET(deadrouter)));
190
191 router_killed++;
192
193 if (NODE(ourrouter) == NODE(deadrouter) &&
194 NET(ourrouter) == NET(deadrouter)) {
195 register unsigned long atrandom = random();
196 register struct routerinfo *newrouter;
197 register i;
198
199 bzero((caddr_t) deadrouter, sizeof(struct routerinfo));
200 for (i = NROUTERS2TRAK; --i >= 0;) {
201 newrouter = &trackedrouters[(i + atrandom) & (NROUTERS2TRAK-1)];
202 if (INUSE(newrouter))
203 break;
204 else
205 newrouter = NULL;
206 }
207 if (newrouter) {
9bccf70c 208 /* Set our router to another on the list and go on with life */
1c79356b
A
209 NET(ourrouter) = NET(newrouter);
210 NODE(ourrouter) = NODE(newrouter);
211 }
212 else {
213 /* from gorouterless() */
9bccf70c 214 /* We have no other routers. */
1c79356b
A
215 ATTRACE(AT_MID_DDP, AT_SID_TIMERS, AT_LV_WARNING, FALSE,
216 "ddp_age_router entry : ARouter = 0x%x, RouterState = 0x%x",
217 ATALK_VALUE(ourrouter->ifARouter), ourrouter->ifRouterState, 0);
218
219 switch (ourrouter->ifRouterState) {
220 case ROUTER_AROUND :
9bccf70c
A
221 /* This is where we lose our cable.
222 Reset router fields and state accordingly. */
1c79356b
A
223 ourrouter->ifARouter.s_net = 0;
224 ourrouter->ifARouter.s_node = 0;
1c79356b
A
225 ourrouter->ifThisCableStart = DDP_MIN_NETWORK;
226 ourrouter->ifThisCableEnd = DDP_MAX_NETWORK;
227 ourrouter->ifRouterState = NO_ROUTER;
9bccf70c
A
228
229 /* Send event to indicate that we've lost our seed router. */
230 atalk_post_msg(ourrouter->aa_ifp, KEV_ATALK_ROUTERDOWN, 0, 0);
231
1c79356b
A
232 zip_control(ourrouter, ZIP_NO_ROUTER);
233 break;
234 case ROUTER_WARNING :
235 /* there was a router that we were ignoring...
236 * now, even that's gone. But we want to tackle the
237 * case where another router may come up after all
238 * of them have died...
239 */
240 ourrouter->ifRouterState = NO_ROUTER;
241 break;
242 }
243 }
244 } else
245 bzero((caddr_t) deadrouter, sizeof(struct routerinfo));
246
91447636 247 atalk_unlock();
1c79356b
A
248
249} /* ddp_age_router */
250
251void rtmp_input (mp, ifID)
252 register gbuf_t *mp;
253 register at_ifaddr_t *ifID;
254{
255 register at_net_al this_net;
256 register at_net_al range_start, range_end;
257 register at_ddp_t *ddp = (at_ddp_t *)gbuf_rptr(mp);
258 /* NOTE: there is an assumption here that the
259 * DATA follows the header. */
260 register at_rtmp *rtmp = (at_rtmp *)ddp->data;
261
262 if (gbuf_type(mp) != MSG_DATA) {
263 /* If this is a M_ERROR message, DDP is shutting down,
264 * nothing to do here...If it's something else, we don't
265 * understand what it is
266 */
267 gbuf_freem(mp);
268 return;
269 }
270
271 if (!ifID) {
272 gbuf_freem(mp);
273 return;
274 }
275 if (gbuf_len(mp) < (DDP_X_HDR_SIZE + sizeof(at_rtmp))) {
276 gbuf_freem(mp);
277 return;
278 }
279 this_net = ifID->ifThisNode.s_net;
280 if (rtmp->at_rtmp_id_length != 8) {
281 gbuf_freem(mp);
282 return;
283 }
284
285 {
286 at_rtmp_tuple *tp;
287 tp = ((at_rtmp_tuple *)&rtmp->at_rtmp_id[1]);
288 range_start = NET_VALUE(tp->at_rtmp_net);
289 tp = ((at_rtmp_tuple *)&rtmp->at_rtmp_id[4]);
290 range_end = NET_VALUE(tp->at_rtmp_net);
291
292 if (ifID->ifRouterState == ROUTER_AROUND) {
293 if ((ifID->ifThisCableStart == range_start) &&
294 (ifID->ifThisCableEnd == range_end)) {
295 trackrouter(ifID,
296 NET_VALUE(rtmp->at_rtmp_this_net),
297 rtmp->at_rtmp_id[0]
298 );
299 }
300 } else {
301 /* There was no router around earlier, one
302 * probably just came up.
303 */
304 if ((this_net >= DDP_STARTUP_LOW) &&
305 (this_net <= DDP_STARTUP_HIGH)) {
306 /* we're operating in the startup range,
307 * ignore the presence of router
308 */
309 if (ifID->ifRouterState == NO_ROUTER) {
9bccf70c
A
310 dPrintf(D_M_RTMP, D_L_INFO, ("rtmp_input: new router came up, INVALID: net \
311 in startup range.\n"));
312 /* trackrouter sends a KEV_ATALK_ROUTERUP event to note that
313 a new router has come up when we had none before. */
1c79356b
A
314 trackrouter(ifID,
315 NET_VALUE(rtmp->at_rtmp_this_net),
316 rtmp->at_rtmp_id[0]
317 );
318 ifID->ifRouterState = ROUTER_WARNING;
9bccf70c
A
319
320 /* This router is invalid. Send event. */
321 atalk_post_msg(ifID->aa_ifp, KEV_ATALK_ROUTERUP_INVALID, 0, 0);
1c79356b
A
322 }
323 } else {
324 /* our address
325 * is not in startup range; Is our
326 * address good for the cable??
327 */
328 if ((this_net >= range_start) &&
329 (this_net <= range_end)) {
330 /* Our address is in the range
331 * valid for this cable... Note
332 * the router address and then
333 * get ZIP rolling to get the
334 * zone info.
335 */
336 ifID->ifThisCableStart = range_start;
337 ifID->ifThisCableEnd = range_end;
9bccf70c
A
338
339 /* A seed router that gives us back our cable range came up.
340 It's a valid router and gives us our network back. */
341 atalk_post_msg(ifID->aa_ifp, KEV_ATALK_ROUTERUP, 0, 0);
342
1c79356b
A
343 trackrouter(ifID,
344 NET_VALUE(rtmp->at_rtmp_this_net),
345 rtmp->at_rtmp_id[0]
346 );
347 zip_control(ifID, ZIP_LATE_ROUTER);
348 } else {
349 /* Our address is not in the
350 * range valid for this cable..
351 * ignore presence of the
352 * router
353 */
354 if (ifID->ifRouterState == NO_ROUTER) {
9bccf70c
A
355 /* trackrouter sends a KEV_ATALK_ROUTERUP event to note that
356 a new router has come up when we had none before. */
1c79356b
A
357 trackrouter(ifID,
358 NET_VALUE(rtmp->at_rtmp_this_net),
359 rtmp->at_rtmp_id[0]
360 );
361 ifID->ifRouterState = ROUTER_WARNING;
9bccf70c
A
362
363 /* A new seed router came up, but the cable range is different
364 than what we had before. */
365 atalk_post_msg(ifID->aa_ifp, KEV_ATALK_ROUTERUP_INVALID, 0, 0);
1c79356b
A
366 }
367 }
368 }
369 }
370 }
371
372 gbuf_freem(mp);
373 return;
374}
375
376
377void rtmp_init()
378{
379 bzero((caddr_t)trackedrouters, sizeof(struct routerinfo)*NROUTERS2TRAK);
380}
381
382