1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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 */
36
37#ifdef AURP_SUPPORT
38
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
62
63static void AURPsndRIRsp(aurp_state_t *);
64
65/* */
66void 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
98/* locked version of AURPsndRIReq */
99void AURPsndRIReq_locked(state)
100	aurp_state_t *state;
101{
102	atalk_lock();
103	AURPsndRIReq(state);
104	atalk_unlock();
105}
106
107/* */
108void 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 */
144	timeout(AURPsndRIReq_locked, state, AURP_RetryInterval*HZ);
145	state->rcv_tmo = 1;
146}
147
148/* locked version of AURPsndRIRsp */
149void AURPsndRIRsp_locked(state)
150	aurp_state_t *state;
151{
152	atalk_lock();
153	AURPsndRIRsp(state);
154	atalk_unlock();
155}
156
157/* */
158void AURPsndRIRsp(state)
159	aurp_state_t *state;
160{
161	gbuf_t *m;
162	aurp_hdr_t *hdrp;
163	short len = 0;
164	int msize = 0;
165
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)) {
170		return;
171	}
172
173	/* update state info */
174	state->snd_state = AURPSTATE_WaitingForRIAck1;
175
176	if (state->rsp_m == 0) {
177		msize = sizeof(aurp_hdr_t);
178		if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_MED)) == 0) {
179			timeout(AURPsndRIRsp_locked, state, AURP_RetryInterval*HZ);
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 */
207	timeout(AURPsndRIRsp_locked, state, AURP_RetryInterval*HZ);
208	state->snd_tmo = 1;
209
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
219void AURPsndRIUpd_locked(state)
220	aurp_state_t *state;
221{
222	atalk_lock();
223	AURPsndRIUpd(state);
224	atalk_unlock();
225}
226
227/* */
228void 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
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)) {
241		return;
242	}
243
244	/* update state info */
245	state->snd_state = AURPSTATE_WaitingForRIAck2;
246
247	if (state->snd_tmo == 0) {
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 */
265	timeout(AURPsndRIUpd_locked, state, AURP_RetryInterval*HZ);
266	state->snd_tmo = 1;
267
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/* */
278void 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
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)) {
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		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		}
309		AURPsndRIRsp(state);
310	}
311
312	gbuf_freem(m);
313}
314
315/* */
316void AURPrcvRIRsp(state, m)
317	aurp_state_t *state;
318	gbuf_t *m;
319{
320	aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m);
321
322
323	/* make sure we're in a valid state to accept it */
324	if (state->rcv_state != AURPSTATE_WaitingForRIRsp) {
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) {
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) {
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;
356
357	dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvRIRsp: len=%ld\n", gbuf_len(m)));
358
359	/* cancel the retry timer */
360	untimeout(AURPsndRIReq_locked, state);
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/* */
382void 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/* */
441void 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;
448	int flag;
449
450	dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvRIAck: state=%d\n",
451		state->snd_state));
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 */
461			untimeout(AURPsndRIRsp_locked, state);
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 */
467			untimeout(AURPsndRIUpd_locked, state);
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;
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);
490	}
491
492	gbuf_freem(m);
493}
494
495/* */
496int 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/* */
534int 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/* */
643int 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 {
693l_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);
714l_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/* */
746void 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/* */
764void 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;
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			 */
824			if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_HI)) == 0)
825				continue;
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)) {
843			AURPsndRIUpd(state);
844			continue;
845		}
846	  }
847	}
848}
849
850#endif  /* AURP_SUPPORT */
851