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