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