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