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