]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
43866e37 | 6 | * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. |
1c79356b | 7 | * |
43866e37 A |
8 | * This file contains Original Code and/or Modifications of Original Code |
9 | * as defined in and that are subject to the Apple Public Source License | |
10 | * Version 2.0 (the 'License'). You may not use this file except in | |
11 | * compliance with the License. Please obtain a copy of the License at | |
12 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
13 | * file. | |
14 | * | |
15 | * The Original Code and all software distributed under the License are | |
16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
43866e37 A |
19 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
20 | * Please see the License for the specific language governing rights and | |
21 | * limitations under the License. | |
1c79356b A |
22 | * |
23 | * @APPLE_LICENSE_HEADER_END@ | |
24 | */ | |
25 | /* | |
26 | * Copyright (c) 1996 Apple Computer, Inc. | |
27 | * | |
28 | * Created April 8, 1996 by Tuyen Nguyen | |
29 | * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX. | |
30 | * | |
31 | * File: ri.c | |
32 | */ | |
33 | #include <sys/errno.h> | |
34 | #include <sys/types.h> | |
35 | #include <sys/param.h> | |
36 | #include <machine/spl.h> | |
37 | #include <sys/systm.h> | |
38 | #include <sys/kernel.h> | |
39 | #include <sys/proc.h> | |
40 | #include <sys/filedesc.h> | |
41 | #include <sys/fcntl.h> | |
42 | #include <sys/mbuf.h> | |
43 | #include <sys/socket.h> | |
44 | #include <sys/socketvar.h> | |
45 | #include <net/if.h> | |
46 | ||
47 | #include <netat/sysglue.h> | |
48 | #include <netat/appletalk.h> | |
49 | #include <netat/at_var.h> | |
50 | #include <netat/rtmp.h> | |
51 | #include <netat/routing_tables.h> | |
52 | #include <netat/at_pcb.h> | |
53 | #include <netat/aurp.h> | |
54 | #include <netat/debug.h> | |
55 | ||
55e303ae A |
56 | |
57 | static void AURPsndRIRsp(aurp_state_t *); | |
58 | ||
1c79356b A |
59 | /* */ |
60 | void AURPsndRIAck(state, m, flags) | |
61 | aurp_state_t *state; | |
62 | gbuf_t *m; | |
63 | unsigned short flags; | |
64 | { | |
65 | unsigned short sequence_number; | |
66 | aurp_hdr_t *hdrp; | |
67 | int msize = sizeof(aurp_hdr_t); | |
68 | ||
69 | if (m) { | |
70 | sequence_number = ((aurp_hdr_t *)gbuf_rptr(m))->sequence_number; | |
71 | gbuf_wset(m,sizeof(aurp_hdr_t)); | |
72 | } else { | |
73 | sequence_number = state->rcv_sequence_number; | |
74 | if ((m = (gbuf_t *)gbuf_alloc(msize, PRI_MED)) == 0) | |
75 | return; | |
76 | gbuf_wset(m,msize); | |
77 | } | |
78 | ||
79 | /* construct the RI Ack packet */ | |
80 | hdrp = (aurp_hdr_t *)gbuf_rptr(m); | |
81 | hdrp->connection_id = state->rcv_connection_id; | |
82 | hdrp->sequence_number = sequence_number; | |
83 | hdrp->command_code = AURPCMD_RIAck; | |
84 | hdrp->flags = flags; | |
85 | ||
86 | /* send the packet */ | |
87 | dPrintf(D_M_AURP, D_L_INFO, ("AURPsndRIAck: node=%d\n", | |
88 | state->rem_node)); | |
89 | AURPsend(m, AUD_AURP, state->rem_node); | |
90 | } | |
91 | ||
92 | /* funneled version of AURPsndRIReq */ | |
93 | void AURPsndRIReq_funnel(state) | |
94 | aurp_state_t *state; | |
95 | { | |
96 | thread_funnel_set(network_flock, TRUE); | |
97 | AURPsndRIReq(state); | |
98 | thread_funnel_set(network_flock, FALSE); | |
99 | } | |
100 | ||
101 | /* */ | |
102 | void AURPsndRIReq(state) | |
103 | aurp_state_t *state; | |
104 | { | |
105 | int msize; | |
106 | gbuf_t *m; | |
107 | aurp_hdr_t *hdrp; | |
108 | ||
109 | ||
110 | if (state->rcv_state == AURPSTATE_Unconnected) { | |
111 | return; | |
112 | } | |
113 | if (state->rcv_tmo && (state->rcv_state != AURPSTATE_WaitingForRIRsp)) { | |
114 | return; | |
115 | } | |
116 | ||
117 | msize = sizeof(aurp_hdr_t); | |
118 | if ((m = (gbuf_t *)gbuf_alloc(msize, PRI_MED)) != 0) { | |
119 | gbuf_wset(m,msize); | |
120 | ||
121 | /* construct the RI request packet */ | |
122 | hdrp = (aurp_hdr_t *)gbuf_rptr(m); | |
123 | hdrp->connection_id = state->rcv_connection_id; | |
124 | hdrp->sequence_number = 0; | |
125 | hdrp->command_code = AURPCMD_RIReq; | |
126 | hdrp->flags = 0; | |
127 | ||
128 | /* update state info */ | |
129 | state->rcv_state = AURPSTATE_WaitingForRIRsp; | |
130 | ||
131 | /* send the packet */ | |
132 | dPrintf(D_M_AURP, D_L_INFO, ("AURPsndRIReq: node=%d\n", | |
133 | state->rem_node)); | |
134 | AURPsend(m, AUD_AURP, state->rem_node); | |
135 | } | |
136 | ||
137 | /* start the retry timer */ | |
138 | timeout(AURPsndRIReq_funnel, state, AURP_RetryInterval*HZ); | |
139 | state->rcv_tmo = 1; | |
140 | } | |
141 | ||
142 | /* funneled version of AURPsndRIRsp */ | |
143 | void AURPsndRIRsp_funnel(state) | |
144 | aurp_state_t *state; | |
145 | { | |
146 | thread_funnel_set(network_flock, TRUE); | |
147 | AURPsndRIRsp(state); | |
148 | thread_funnel_set(network_flock, FALSE); | |
149 | } | |
150 | ||
151 | /* */ | |
152 | void AURPsndRIRsp(state) | |
153 | aurp_state_t *state; | |
154 | { | |
155 | gbuf_t *m; | |
156 | aurp_hdr_t *hdrp; | |
157 | short len = 0; | |
158 | int s, msize = 0; | |
159 | ||
160 | ATDISABLE(s, aurpgen_lock); | |
161 | ||
162 | /* make sure we're in a valid state to send RI response */ | |
163 | if ((state->snd_state == AURPSTATE_Unconnected) || | |
164 | (state->snd_state == AURPSTATE_WaitingForRIAck2)) { | |
165 | ATENABLE(s, aurpgen_lock); | |
166 | return; | |
167 | } | |
168 | ||
169 | /* update state info */ | |
170 | state->snd_state = AURPSTATE_WaitingForRIAck1; | |
171 | ||
172 | if (state->rsp_m == 0) { | |
173 | ATENABLE(s, aurpgen_lock); | |
174 | msize = sizeof(aurp_hdr_t); | |
175 | if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_MED)) == 0) { | |
176 | timeout(AURPsndRIRsp_funnel, state, AURP_RetryInterval*HZ); | |
177 | state->snd_tmo = 1; | |
178 | return; | |
179 | } | |
180 | gbuf_wset(m,msize); | |
181 | state->rsp_m = m; | |
182 | ||
183 | /* construct the RI response packet */ | |
184 | hdrp = (aurp_hdr_t *)gbuf_rptr(m); | |
185 | hdrp->connection_id = state->snd_connection_id; | |
186 | hdrp->sequence_number = state->snd_sequence_number; | |
187 | hdrp->command_code = AURPCMD_RIRsp; | |
188 | hdrp->flags = 0; | |
189 | ||
190 | /* get routing info of the local networks */ | |
191 | state->snd_next_entry = AURPgetri( | |
192 | state->snd_next_entry, gbuf_wptr(m), &len); | |
193 | gbuf_winc(m,len); | |
194 | ||
195 | /* set the last flag if this is the last response packet */ | |
196 | if (!state->snd_next_entry) | |
197 | hdrp->flags = AURPFLG_LAST; | |
198 | } | |
199 | ||
200 | /* keep a copy of the packet for retry */ | |
201 | m = (gbuf_t *)gbuf_dupb(state->rsp_m); | |
202 | ||
203 | /* start the retry timer */ | |
204 | timeout(AURPsndRIRsp_funnel, state, AURP_RetryInterval*HZ); | |
205 | state->snd_tmo = 1; | |
206 | ||
207 | if (msize == 0) | |
208 | ATENABLE(s, aurpgen_lock); | |
209 | ||
210 | /* send the packet */ | |
211 | if (m) { | |
212 | dPrintf(D_M_AURP, D_L_INFO, ("AURPsndRIRsp: len=%d\n", len)); | |
213 | AURPsend(m, AUD_AURP, state->rem_node); | |
214 | } | |
215 | ||
216 | } | |
217 | ||
218 | void AURPsndRIUpd_funnel(state) | |
219 | aurp_state_t *state; | |
220 | { | |
221 | thread_funnel_set(network_flock, TRUE); | |
222 | AURPsndRIUpd(state); | |
223 | thread_funnel_set(network_flock, FALSE); | |
224 | } | |
225 | ||
226 | /* */ | |
227 | void AURPsndRIUpd(state) | |
228 | aurp_state_t *state; | |
229 | { | |
230 | gbuf_t *m; | |
231 | aurp_hdr_t *hdrp; | |
232 | short len = 0; | |
233 | int s, msize = 0; | |
234 | ||
235 | ATDISABLE(s, aurpgen_lock); | |
236 | ||
237 | /* make sure we're in a valid state to send update */ | |
238 | if (state->snd_next_entry || (state->upd_m == 0) || | |
239 | (state->snd_state == AURPSTATE_Unconnected) || | |
240 | (state->snd_state == AURPSTATE_WaitingForRIAck1)) { | |
241 | ATENABLE(s, aurpgen_lock); | |
242 | return; | |
243 | } | |
244 | ||
245 | /* update state info */ | |
246 | state->snd_state = AURPSTATE_WaitingForRIAck2; | |
247 | ||
248 | if (state->snd_tmo == 0) { | |
249 | ATENABLE(s, aurpgen_lock); | |
250 | msize = sizeof(aurp_hdr_t); | |
251 | m = state->upd_m; | |
252 | len = gbuf_len(m); | |
253 | gbuf_rdec(m,msize); | |
254 | ||
255 | /* construct the RI update packet */ | |
256 | hdrp = (aurp_hdr_t *)gbuf_rptr(m); | |
257 | hdrp->connection_id = state->snd_connection_id; | |
258 | hdrp->sequence_number = state->snd_sequence_number; | |
259 | hdrp->command_code = AURPCMD_RIUpd; | |
260 | hdrp->flags = 0; | |
261 | } | |
262 | ||
263 | /* keep a copy of the packet for retry */ | |
264 | m = (gbuf_t *)gbuf_dupb(state->upd_m); | |
265 | ||
266 | /* start the retry timer */ | |
267 | timeout(AURPsndRIUpd_funnel, state, AURP_RetryInterval*HZ); | |
268 | state->snd_tmo = 1; | |
269 | ||
270 | if (msize == 0) | |
271 | ATENABLE(s, aurpgen_lock); | |
272 | ||
273 | /* send the packet */ | |
274 | if (m) { | |
275 | dPrintf(D_M_AURP, D_L_INFO, ("AURPsndRIUpd: len=%d\n", len)); | |
276 | AURPsend(m, AUD_AURP, state->rem_node); | |
277 | } | |
278 | ||
279 | } | |
280 | ||
281 | /* */ | |
282 | void AURPrcvRIReq(state, m) | |
283 | aurp_state_t *state; | |
284 | gbuf_t *m; | |
285 | { | |
286 | aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m); | |
287 | int s; | |
288 | ||
289 | ATDISABLE(s, aurpgen_lock); | |
290 | ||
291 | /* make sure we're in a valid state to accept it */ | |
292 | if ((state->snd_state == AURPSTATE_Unconnected) || | |
293 | (state->snd_state == AURPSTATE_WaitingForRIAck2)) { | |
294 | ATENABLE(s, aurpgen_lock); | |
295 | dPrintf(D_M_AURP, D_L_WARNING, ("AURPrcvRIReq: unexpected request\n")); | |
296 | gbuf_freem(m); | |
297 | return; | |
298 | } | |
299 | ||
300 | /* check for the correct connection id */ | |
301 | if (hdrp->connection_id != state->snd_connection_id) { | |
302 | ATENABLE(s, aurpgen_lock); | |
303 | dPrintf(D_M_AURP, D_L_WARNING, | |
304 | ("AURPrcvRIReq: invalid connection id, r=%d, m=%d\n", | |
305 | hdrp->connection_id, state->snd_connection_id)); | |
306 | gbuf_freem(m); | |
307 | return; | |
308 | } | |
309 | ||
310 | if (state->snd_state != AURPSTATE_WaitingForRIAck1) { | |
311 | state->snd_next_entry = 0; | |
312 | if (state->rsp_m) { | |
313 | gbuf_freem(state->rsp_m); | |
314 | state->rsp_m = 0; | |
315 | } | |
316 | ATENABLE(s, aurpgen_lock); | |
317 | AURPsndRIRsp(state); | |
318 | } else | |
319 | ATENABLE(s, aurpgen_lock); | |
320 | ||
321 | gbuf_freem(m); | |
322 | } | |
323 | ||
324 | /* */ | |
325 | void AURPrcvRIRsp(state, m) | |
326 | aurp_state_t *state; | |
327 | gbuf_t *m; | |
328 | { | |
329 | aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m); | |
330 | int s; | |
331 | ||
332 | ATDISABLE(s, aurpgen_lock); | |
333 | ||
334 | /* make sure we're in a valid state to accept it */ | |
335 | if (state->rcv_state != AURPSTATE_WaitingForRIRsp) { | |
336 | ATENABLE(s, aurpgen_lock); | |
337 | dPrintf(D_M_AURP, D_L_WARNING, ("AURPrcvRIRsp: unexpected response\n")); | |
338 | gbuf_freem(m); | |
339 | return; | |
340 | } | |
341 | ||
342 | /* check for the correct connection id */ | |
343 | if (hdrp->connection_id != state->rcv_connection_id) { | |
344 | ATENABLE(s, aurpgen_lock); | |
345 | dPrintf(D_M_AURP, D_L_WARNING, | |
346 | ("AURPrcvRIRsp: invalid connection id, r=%d, m=%d\n", | |
347 | hdrp->connection_id, state->rcv_connection_id)); | |
348 | gbuf_freem(m); | |
349 | return; | |
350 | } | |
351 | ||
352 | /* check for the correct sequence number */ | |
353 | if (hdrp->sequence_number != state->rcv_sequence_number) { | |
354 | ATENABLE(s, aurpgen_lock); | |
355 | if ( ((state->rcv_sequence_number == AURP_FirstSeqNum) && | |
356 | (hdrp->sequence_number == AURP_LastSeqNum)) || | |
357 | (hdrp->sequence_number == (state->rcv_sequence_number-1)) ) { | |
358 | AURPsndRIAck(state, m, AURPFLG_SZI); | |
359 | } else { | |
360 | dPrintf(D_M_AURP, D_L_WARNING, | |
361 | ("AURPrcvRIRsp: invalid sequence number, r=%d, m=%d\n", | |
362 | hdrp->sequence_number, state->rcv_sequence_number)); | |
363 | gbuf_freem(m); | |
364 | } | |
365 | return; | |
366 | } | |
367 | gbuf_rinc(m,sizeof(*hdrp)); | |
368 | if (hdrp->flags & AURPFLG_LAST) | |
369 | state->rcv_state = AURPSTATE_Connected; | |
370 | ATENABLE(s, aurpgen_lock); | |
371 | ||
372 | dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvRIRsp: len=%ld\n", gbuf_len(m))); | |
373 | ||
374 | /* cancel the retry timer */ | |
375 | untimeout(AURPsndRIReq_funnel, state); | |
376 | state->rcv_tmo = 0; | |
377 | ||
378 | /* send RI ack */ | |
379 | AURPsndRIAck(state, 0, AURPFLG_SZI); | |
380 | ||
381 | /* update state info */ | |
382 | if (++state->rcv_sequence_number == 0) | |
383 | state->rcv_sequence_number = AURP_FirstSeqNum; | |
384 | ||
385 | /* process routing info of the tunnel peer */ | |
386 | if (AURPsetri(state->rem_node, m)) { | |
387 | dPrintf(D_M_AURP, D_L_ERROR, ("AURPrcvRIRsp: AURPsetri() error\n")); | |
388 | } | |
389 | gbuf_freem(m); | |
390 | ||
391 | /* set the get zone flag to get zone info later if required */ | |
392 | if (state->rcv_state == AURPSTATE_Connected) | |
393 | state->get_zi = 1; | |
394 | } | |
395 | ||
396 | /* */ | |
397 | void AURPrcvRIUpd(state, m) | |
398 | aurp_state_t *state; | |
399 | gbuf_t *m; | |
400 | { | |
401 | aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m); | |
402 | ||
403 | /* make sure we're in a valid state to accept it */ | |
404 | if (state->rcv_state == AURPSTATE_Unconnected) { | |
405 | dPrintf(D_M_AURP, D_L_WARNING, ("AURPrcvRIUpd: unexpected response\n")); | |
406 | gbuf_freem(m); | |
407 | return; | |
408 | } | |
409 | ||
410 | /* check for the correct connection id */ | |
411 | if (hdrp->connection_id != state->rcv_connection_id) { | |
412 | dPrintf(D_M_AURP, D_L_WARNING, | |
413 | ("AURPrcvRIUpd: invalid connection id, r=%d, m=%d\n", | |
414 | hdrp->connection_id, state->rcv_connection_id)); | |
415 | gbuf_freem(m); | |
416 | return; | |
417 | } | |
418 | ||
419 | /* check for the correct sequence number */ | |
420 | if (hdrp->sequence_number != state->rcv_sequence_number) { | |
421 | if ( ((state->rcv_sequence_number == AURP_FirstSeqNum) && | |
422 | (hdrp->sequence_number == AURP_LastSeqNum)) || | |
423 | (hdrp->sequence_number == (state->rcv_sequence_number-1)) ) { | |
424 | AURPsndRIAck(state, m, AURPFLG_SZI); | |
425 | } else { | |
426 | dPrintf(D_M_AURP, D_L_WARNING, | |
427 | ("AURPrcvRIUpd: invalid sequence number, r=%d, m=%d\n", | |
428 | hdrp->sequence_number, state->rcv_sequence_number)); | |
429 | gbuf_freem(m); | |
430 | } | |
431 | return; | |
432 | } | |
433 | gbuf_rinc(m,sizeof(*hdrp)); | |
434 | ||
435 | dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvRIUpd: len=%ld\n", gbuf_len(m))); | |
436 | ||
437 | /* send RI ack */ | |
438 | AURPsndRIAck(state, 0, AURPFLG_SZI); | |
439 | ||
440 | /* update state info */ | |
441 | if (++state->rcv_sequence_number == 0) | |
442 | state->rcv_sequence_number = AURP_FirstSeqNum; | |
443 | ||
444 | /* process update routing info of the tunnel peer */ | |
445 | if (AURPupdateri(state->rem_node, m)) { | |
446 | dPrintf(D_M_AURP, D_L_ERROR, ("AURPrcvRIUpd: AURPupdateri() error\n")); | |
447 | } | |
448 | ||
449 | /* set the get zone flag to get zone info later if required */ | |
450 | state->get_zi = 1; | |
451 | ||
452 | gbuf_freem(m); | |
453 | } | |
454 | ||
455 | /* */ | |
456 | void AURPrcvRIAck(state, m) | |
457 | aurp_state_t *state; | |
458 | gbuf_t *m; | |
459 | { | |
460 | gbuf_t *dat_m; | |
461 | aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m); | |
462 | unsigned char snd_state; | |
463 | int s; | |
464 | int flag; | |
465 | ||
466 | dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvRIAck: state=%d\n", | |
467 | state->snd_state)); | |
468 | ATDISABLE(s, aurpgen_lock); | |
469 | ||
470 | /* make sure we're in a valid state to accept it */ | |
471 | snd_state = state->snd_state; | |
472 | if (((snd_state == AURPSTATE_WaitingForRIAck1) || | |
473 | (snd_state == AURPSTATE_WaitingForRIAck2)) && | |
474 | (hdrp->sequence_number == state->snd_sequence_number)) { | |
475 | ||
476 | if (snd_state == AURPSTATE_WaitingForRIAck1) { | |
477 | /* ack from the tunnel peer to our RI response */ | |
478 | untimeout(AURPsndRIRsp_funnel, state); | |
479 | dat_m = state->rsp_m; | |
480 | state->rsp_m = 0; | |
481 | flag = 1; | |
482 | } else { | |
483 | /* ack from the tunnel peer to our RI update */ | |
484 | untimeout(AURPsndRIUpd_funnel, state); | |
485 | dat_m = state->upd_m; | |
486 | state->upd_m = 0; | |
487 | flag = 2; | |
488 | } | |
489 | state->snd_tmo = 0; | |
490 | gbuf_rinc(dat_m,sizeof(aurp_hdr_t)); | |
491 | ||
492 | /* increment the sequence number */ | |
493 | if (++state->snd_sequence_number == 0) | |
494 | state->snd_sequence_number = AURP_FirstSeqNum; | |
495 | ||
496 | /* update state info */ | |
497 | state->snd_state = AURPSTATE_Connected; | |
498 | ATENABLE(s, aurpgen_lock); | |
499 | ||
500 | if (state->snd_next_entry) /* more RI responses to send? */ | |
501 | AURPsndRIRsp(state); | |
502 | ||
503 | /* check to see if we need to send ZI responses */ | |
504 | if (hdrp->flags & AURPFLG_SZI) | |
505 | AURPsndZRsp(state, dat_m, flag); | |
506 | else if (dat_m) | |
507 | gbuf_freem(dat_m); | |
508 | } else | |
509 | ATENABLE(s, aurpgen_lock); | |
510 | ||
511 | gbuf_freem(m); | |
512 | } | |
513 | ||
514 | /* */ | |
515 | int AURPgetri(next_entry, buf, len) | |
516 | short next_entry; | |
517 | unsigned char *buf; | |
518 | short *len; | |
519 | { | |
520 | short entry_num = next_entry; | |
521 | RT_entry *entry = (RT_entry *)&RT_table[next_entry]; | |
522 | ||
523 | for (*len=0; entry_num < RT_maxentry; entry_num++,entry++) { | |
524 | if ((net_port != entry->NetPort) && | |
525 | !(entry->AURPFlag & AURP_NetHiden)) { | |
526 | if ((entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) { | |
527 | if (entry->NetStart) { | |
528 | /* route info for extended network */ | |
529 | *(short *)buf = entry->NetStart; | |
530 | buf += sizeof(short); | |
531 | *buf++ = 0x80 | (entry->NetDist & 0x1F); | |
532 | *(short *)buf = entry->NetStop; | |
533 | buf += sizeof(short); | |
534 | *buf++ = 0; | |
535 | *len += 6; | |
536 | } else { | |
537 | /* route info for non-extended network */ | |
538 | *(short *)buf = entry->NetStop; | |
539 | buf += sizeof(short); | |
540 | *buf++ = (entry->NetDist & 0x1F); | |
541 | *len += 3; | |
542 | } | |
543 | } | |
544 | } | |
545 | if (*len > AURP_MaxPktSize) | |
546 | break; | |
547 | } | |
548 | ||
549 | return (entry_num == RT_maxentry) ? 0 : entry_num; | |
550 | } | |
551 | ||
552 | /* */ | |
553 | int AURPsetri(node, m) | |
554 | unsigned char node; | |
555 | gbuf_t *m; | |
556 | { | |
557 | int tuples_cnt; | |
558 | unsigned char *tuples_ptr; | |
559 | RT_entry new_rt, *curr_rt; | |
560 | ||
561 | new_rt.NextIRNet = 0; | |
562 | new_rt.NextIRNode = node; | |
563 | new_rt.NetPort = net_port; | |
564 | ||
565 | /* | |
566 | * Process all the tuples against our routing table | |
567 | */ | |
568 | tuples_ptr = (char *)gbuf_rptr(m); | |
569 | tuples_cnt = (gbuf_len(m))/3; | |
570 | ||
571 | while (tuples_cnt--) { | |
572 | new_rt.NetDist = TUPLEDIST(tuples_ptr) + 1; | |
573 | new_rt.EntryState = RTE_STATE_GOOD; | |
574 | new_rt.NetStart = TUPLENET(tuples_ptr); | |
575 | tuples_ptr += 3; | |
576 | if (tuples_ptr[-1] & 0x80) { | |
577 | new_rt.NetStop = TUPLENET((tuples_ptr)); | |
578 | tuples_ptr += 3; | |
579 | tuples_cnt--; | |
580 | } else { | |
581 | new_rt.NetStop = new_rt.NetStart; | |
582 | new_rt.NetStart = 0; | |
583 | } | |
584 | if ((new_rt.NetStop == 0) || (new_rt.NetStop < new_rt.NetStart)) { | |
585 | dPrintf(D_M_AURP, D_L_WARNING, | |
586 | ("AURPsetri: %d, invalid tuple received [%d-%d]\n", | |
587 | net_port, new_rt.NetStart, new_rt.NetStop)); | |
588 | continue; | |
589 | } | |
590 | ||
591 | if ((curr_rt = rt_blookup(new_rt.NetStop)) != 0) { /* found? */ | |
592 | /* ignore loop if present */ | |
593 | if (curr_rt->NetPort != net_port) | |
594 | continue; | |
595 | ||
596 | if (new_rt.NetDist < 16) { | |
597 | /* | |
598 | * check if the definition of the route has changed | |
599 | */ | |
600 | if ((new_rt.NetStop != curr_rt->NetStop) || | |
601 | (new_rt.NetStart != curr_rt->NetStart)) { | |
602 | if ((new_rt.NetStop == curr_rt->NetStop) && | |
603 | (new_rt.NetStop == curr_rt->NetStart) && | |
604 | (new_rt.NetStart == 0)) { | |
605 | new_rt.NetStart = new_rt.NetStop; | |
606 | } else if ((new_rt.NetStop == curr_rt->NetStop) && | |
607 | (new_rt.NetStart == new_rt.NetStop) && | |
608 | (curr_rt->NetStart == 0)) { | |
609 | dPrintf(D_M_AURP, D_L_WARNING, | |
610 | ("AURPsetri: [%d-%d] has changed to [%d-%d], Dist=%d\n", | |
611 | curr_rt->NetStart, curr_rt->NetStop, | |
612 | new_rt.NetStart, new_rt.NetStop, new_rt.NetDist)); | |
613 | new_rt.NetStart = 0; | |
614 | } else { | |
615 | dPrintf(D_M_AURP, D_L_WARNING, | |
616 | ("AURPsetri: Net Conflict, Curr=[%d-%d], New=[%d-%d]\n", | |
617 | curr_rt->NetStart,curr_rt->NetStop, | |
618 | new_rt.NetStart,new_rt.NetStop)); | |
619 | zt_remove_zones(curr_rt->ZoneBitMap); | |
620 | rt_delete(curr_rt->NetStop, curr_rt->NetStart); | |
621 | continue; | |
622 | } | |
623 | } | |
624 | } | |
625 | ||
626 | if ((new_rt.NetDist <= curr_rt->NetDist) && | |
627 | (new_rt.NetDist < 16)) { | |
628 | /* | |
629 | * found a shorter or more recent route, | |
630 | * replace with the new entry | |
631 | */ | |
632 | curr_rt->NetDist = new_rt.NetDist; | |
633 | curr_rt->NextIRNode = new_rt.NextIRNode; | |
634 | dPrintf(D_M_AURP_LOW,D_L_INFO, | |
635 | ("AURPsetri: shorter route found [%d-%d], update\n", | |
636 | new_rt.NetStart,new_rt.NetStop)); | |
637 | } | |
638 | ||
639 | } else { /* no entry found */ | |
640 | if (new_rt.NetDist < 16) { | |
641 | new_rt.EntryState = RTE_STATE_GOOD; | |
642 | dPrintf(D_M_AURP, D_L_INFO, | |
643 | ("AURPsetri: new_rt [%d-%d], tuple #%d\n", | |
644 | new_rt.NetStart, new_rt.NetStop, tuples_cnt)); | |
645 | if (rt_insert(new_rt.NetStop, new_rt.NetStart, | |
646 | new_rt.NextIRNet, new_rt.NextIRNode, | |
647 | new_rt.NetDist, new_rt.NetPort, | |
648 | new_rt.EntryState) == (RT_entry *)0) { | |
649 | dPrintf(D_M_AURP,D_L_ERROR, | |
650 | ("AURPsetri: RTMP table full [%d-%d]\n", | |
651 | new_rt.NetStart,new_rt.NetStop)); | |
652 | return -1; | |
653 | } | |
654 | } | |
655 | } | |
656 | } /* end of main while */ | |
657 | ||
658 | return 0; | |
659 | } | |
660 | ||
661 | /* */ | |
662 | int AURPupdateri(node, m) | |
663 | unsigned char node; | |
664 | gbuf_t *m; | |
665 | { | |
666 | char ev, ev_len; | |
667 | RT_entry new_rt, *old_rt; | |
668 | ||
669 | while (gbuf_len(m) > 0) { | |
670 | ev = *gbuf_rptr(m); /* event code */ | |
671 | gbuf_rinc(m,1); | |
672 | if (gbuf_rptr(m)[2] & 0x80) { | |
673 | /* event tuple for extended network */ | |
674 | new_rt.NetStart = *(unsigned short *)gbuf_rptr(m); | |
675 | new_rt.NetStop = *(unsigned short *)&gbuf_rptr(m)[3]; | |
676 | new_rt.NetDist = gbuf_rptr(m)[2] & 0x7f; | |
677 | ev_len = 5; | |
678 | } else { | |
679 | /* event tuple for non-extended network */ | |
680 | new_rt.NetStart = 0; | |
681 | new_rt.NetStop = *(unsigned short *)gbuf_rptr(m); | |
682 | new_rt.NetDist = gbuf_rptr(m)[2]; | |
683 | ev_len = 3; | |
684 | } | |
685 | ||
686 | switch (ev) { | |
687 | case AURPEV_Null: | |
688 | break; | |
689 | ||
690 | case AURPEV_NetAdded: | |
691 | gbuf_rinc(m,ev_len); | |
692 | new_rt.NextIRNet = 0; | |
693 | new_rt.NextIRNode = node; | |
694 | new_rt.NetPort = net_port; | |
695 | if ((new_rt.NetDist == 0) || (new_rt.NetStop == 0) || | |
696 | (new_rt.NetStop < new_rt.NetStart)) { | |
697 | dPrintf(D_M_AURP,D_L_WARNING, | |
698 | ("AURPupdateri: %d, invalid NetAdded received [%d-%d]\n", | |
699 | net_port, new_rt.NetStart, new_rt.NetStop)); | |
700 | break; | |
701 | } | |
702 | ||
703 | if ((old_rt = rt_blookup(new_rt.NetStop)) != 0) { /* found? */ | |
704 | if (old_rt->NetPort == net_port) { | |
705 | /* | |
706 | * process this event as if it was an NDC event; | |
707 | * update the route's distance | |
708 | */ | |
709 | old_rt->NetDist = new_rt.NetDist; | |
710 | } | |
711 | } else { | |
712 | l_add: if ((new_rt.NetDist < 16) && (new_rt.NetDist != NOTIFY_N_DIST)) { | |
713 | new_rt.EntryState = RTE_STATE_GOOD; | |
714 | dPrintf(D_M_AURP, D_L_INFO, | |
715 | ("AURPupdateri: NetAdded [%d-%d]\n", | |
716 | new_rt.NetStart, new_rt.NetStop)); | |
717 | if (rt_insert(new_rt.NetStop, new_rt.NetStart, | |
718 | new_rt.NextIRNet, new_rt.NextIRNode, | |
719 | new_rt.NetDist, new_rt.NetPort, | |
720 | new_rt.EntryState) == (RT_entry *)0) { | |
721 | dPrintf(D_M_AURP, D_L_WARNING, | |
722 | ("AURPupdateri: RTMP table full [%d-%d]\n", | |
723 | new_rt.NetStart,new_rt.NetStop)); | |
724 | return 0; | |
725 | } | |
726 | } | |
727 | } | |
728 | break; | |
729 | ||
730 | case AURPEV_NetDeleted: | |
731 | case AURPEV_NetRouteChange: | |
732 | gbuf_rinc(m,ev_len); | |
733 | l_delete: if ((old_rt = rt_blookup(new_rt.NetStop)) != 0) { /* found? */ | |
734 | if (old_rt->NetPort == net_port) { | |
735 | zt_remove_zones(old_rt->ZoneBitMap); | |
736 | rt_delete(old_rt->NetStop, old_rt->NetStart); | |
737 | } | |
738 | } | |
739 | break; | |
740 | ||
741 | case AURPEV_NetDistChange: | |
742 | gbuf_rinc(m,ev_len); | |
743 | if (new_rt.NetDist == 15) | |
744 | goto l_delete; /* process this event as if was an ND event */ | |
745 | if ((old_rt = rt_blookup(new_rt.NetStop)) != 0) { /* found? */ | |
746 | if (old_rt->NetPort == net_port) { | |
747 | /* | |
748 | * update the route's distance | |
749 | */ | |
750 | old_rt->NetDist = new_rt.NetDist; | |
751 | } | |
752 | } else | |
753 | goto l_add; /* process this event as if was an NA event */ | |
754 | break; | |
755 | ||
756 | case AURPEV_NetZoneChange: | |
757 | break; | |
758 | } | |
759 | } | |
760 | ||
761 | return 0; | |
762 | } | |
763 | ||
764 | /* */ | |
765 | void AURPpurgeri(node) | |
766 | unsigned char node; | |
767 | { | |
768 | short entry_num; | |
769 | RT_entry *entry = (RT_entry *)RT_table; | |
770 | ||
771 | /* | |
772 | * purge all routes associated with the tunnel peer | |
773 | */ | |
774 | for (entry_num=0; entry_num < RT_maxentry; entry_num++,entry++) { | |
775 | if ((net_port == entry->NetPort) && (node == entry->NextIRNode)) { | |
776 | zt_remove_zones(entry->ZoneBitMap); | |
777 | rt_delete(entry->NetStop, entry->NetStart); | |
778 | } | |
779 | } | |
780 | } | |
781 | ||
782 | /* */ | |
783 | void AURPrtupdate(entry, ev) | |
784 | RT_entry *entry; | |
785 | unsigned char ev; | |
786 | { | |
787 | unsigned char i, node, ev_len, ev_tuple[6]; | |
788 | gbuf_t *m; | |
789 | aurp_state_t *state = (aurp_state_t *)&aurp_state[1]; | |
790 | int s, msize = sizeof(aurp_hdr_t); | |
791 | ||
792 | dPrintf(D_M_AURP, D_L_TRACE, ("AURPrtupdate: event=%d, net=[%d-%d]\n", | |
793 | ev, entry->NetStart, entry->NetStop)); | |
794 | ||
795 | /* | |
796 | * check that the network can be exported; if not, | |
797 | * we must not make it visible beyond the local networks | |
798 | */ | |
799 | if (net_export) { | |
800 | for (i=0; i < net_access_cnt; i++) { | |
801 | if ((net_access[i] == entry->NetStart) || | |
802 | (net_access[i] == entry->NetStop)) | |
803 | break; | |
804 | } | |
805 | if (i == net_access_cnt) | |
806 | return; | |
807 | } else { | |
808 | for (i=0; i < net_access_cnt; i++) { | |
809 | if ((net_access[i] == entry->NetStart) || | |
810 | (net_access[i] == entry->NetStop)) | |
811 | return; | |
812 | } | |
813 | } | |
814 | ||
815 | /* | |
816 | * create the update event tuple | |
817 | */ | |
818 | ev_tuple[0] = ev; /* event code */ | |
819 | if (entry->NetStart) { | |
820 | *(unsigned short *)&ev_tuple[1] = entry->NetStart; | |
821 | ev_tuple[3] = 0x80 | (entry->NetDist & 0x1F); | |
822 | *(unsigned short *)&ev_tuple[4] = entry->NetStop; | |
823 | ev_len = 6; | |
824 | } else { | |
825 | *(unsigned short *)&ev_tuple[1] = entry->NetStop; | |
826 | ev_tuple[3] = (entry->NetDist & 0x1F); | |
827 | ev_len = 4; | |
828 | } | |
829 | ||
830 | for (node=1; node <= dst_addr_cnt; node++, state++) { | |
831 | if ((ev == AURPEV_NetAdded) && | |
832 | (!(state->snd_sui & AURPFLG_NA))) continue; | |
833 | if ((ev == AURPEV_NetDeleted) && | |
834 | (!(state->snd_sui & AURPFLG_ND))) continue; | |
835 | if ((ev == AURPEV_NetDistChange) && | |
836 | (!(state->snd_sui & AURPFLG_NDC))) continue; | |
837 | ATDISABLE(s, aurpgen_lock); | |
838 | if ((state->snd_state != AURPSTATE_Unconnected) && | |
839 | (state->snd_state != AURPSTATE_WaitingForRIAck2)) { | |
840 | if ((m = state->upd_m) == 0) { | |
841 | /* | |
842 | * we don't have the RI update buffer yet, allocate one | |
843 | */ | |
844 | ATENABLE(s, aurpgen_lock); | |
845 | if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_HI)) == 0) | |
846 | continue; | |
847 | ATDISABLE(s, aurpgen_lock); | |
848 | state->upd_m = m; | |
849 | gbuf_rinc(m,msize); | |
850 | gbuf_wset(m,0); | |
851 | } | |
852 | ||
853 | /* | |
854 | * add the update event tuple to the RI update buffer; | |
855 | * the RI update buffer will be sent when the periodic update | |
856 | * timer expires | |
857 | */ | |
858 | bcopy(ev_tuple, gbuf_wptr(m), ev_len); | |
859 | gbuf_winc(m,ev_len); | |
860 | ||
861 | /* | |
862 | * if the RI update buffer is full, send the RI update now | |
863 | */ | |
864 | if (gbuf_len(m) > (AURP_MaxPktSize-6)) { | |
865 | ATENABLE(s, aurpgen_lock); | |
866 | AURPsndRIUpd(state); | |
867 | continue; | |
868 | } | |
869 | } | |
870 | ATENABLE(s, aurpgen_lock); | |
871 | } | |
872 | } |