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