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