]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/aurp_ri.c
xnu-344.32.tar.gz
[apple/xnu.git] / bsd / netat / aurp_ri.c
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 }