xref: /csrg-svn/sys/netiso/iso_snpac.c (revision 36392)
1*36392Ssklower /***********************************************************
2*36392Ssklower 		Copyright IBM Corporation 1987
3*36392Ssklower 
4*36392Ssklower                       All Rights Reserved
5*36392Ssklower 
6*36392Ssklower Permission to use, copy, modify, and distribute this software and its
7*36392Ssklower documentation for any purpose and without fee is hereby granted,
8*36392Ssklower provided that the above copyright notice appear in all copies and that
9*36392Ssklower both that copyright notice and this permission notice appear in
10*36392Ssklower supporting documentation, and that the name of IBM not be
11*36392Ssklower used in advertising or publicity pertaining to distribution of the
12*36392Ssklower software without specific, written prior permission.
13*36392Ssklower 
14*36392Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15*36392Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16*36392Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17*36392Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18*36392Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19*36392Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*36392Ssklower SOFTWARE.
21*36392Ssklower 
22*36392Ssklower ******************************************************************/
23*36392Ssklower 
24*36392Ssklower /*
25*36392Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26*36392Ssklower  */
27*36392Ssklower /* $Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $ */
28*36392Ssklower /* $Source: /usr/argo/sys/netiso/RCS/iso_snpac.c,v $ */
29*36392Ssklower 
30*36392Ssklower #ifndef lint
31*36392Ssklower static char *rcsid = "$Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $";
32*36392Ssklower #endif lint
33*36392Ssklower 
34*36392Ssklower #ifdef ISO
35*36392Ssklower 
36*36392Ssklower #include "../h/types.h"
37*36392Ssklower #include "../h/param.h"
38*36392Ssklower #include "../h/mbuf.h"
39*36392Ssklower #include "../h/domain.h"
40*36392Ssklower #include "../h/protosw.h"
41*36392Ssklower #include "../h/socket.h"
42*36392Ssklower #include "../h/socketvar.h"
43*36392Ssklower #include "../h/errno.h"
44*36392Ssklower #include "../h/ioctl.h"
45*36392Ssklower #include "../h/time.h"
46*36392Ssklower #include "../h/kernel.h"
47*36392Ssklower 
48*36392Ssklower #include "../net/if.h"
49*36392Ssklower #include "../net/route.h"
50*36392Ssklower 
51*36392Ssklower #include "../netiso/iso.h"
52*36392Ssklower #include "../netiso/iso_var.h"
53*36392Ssklower #include "../netiso/iso_snpac.h"
54*36392Ssklower #include "../netiso/clnp.h"
55*36392Ssklower #include "../netiso/clnp_stat.h"
56*36392Ssklower #include "../netiso/argo_debug.h"
57*36392Ssklower #include "../netiso/esis.h"
58*36392Ssklower 
59*36392Ssklower #define	SNPAC_BSIZ	20		/* bucket size */
60*36392Ssklower #define	SNPAC_NB	13		/* number of buckets */
61*36392Ssklower #define	SNPAC_SIZE	(SNPAC_BSIZ * SNPAC_NB)
62*36392Ssklower struct	snpa_cache	iso_snpac[SNPAC_SIZE];
63*36392Ssklower int					iso_snpac_size = SNPAC_SIZE;/* for iso_map command */
64*36392Ssklower int 				iso_systype = SNPA_ES;	/* default to be an ES */
65*36392Ssklower static struct iso_addr	zero_isoa;
66*36392Ssklower 
67*36392Ssklower #define	SNPAC_HASH(addr) \
68*36392Ssklower 	(((u_long) iso_hashchar(addr, addr->isoa_len)) % SNPAC_NB)
69*36392Ssklower 
70*36392Ssklower #define	SNPAC_LOOK(sc,addr) { \
71*36392Ssklower 	register n; \
72*36392Ssklower 	sc = &iso_snpac[SNPAC_HASH(addr) * SNPAC_BSIZ]; \
73*36392Ssklower 	for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) \
74*36392Ssklower 		if ((sc->sc_flags & SNPA_VALID) && \
75*36392Ssklower 			(iso_addrmatch1(&sc->sc_nsap, addr))) \
76*36392Ssklower 			break; \
77*36392Ssklower 	if (n >= SNPAC_BSIZ) \
78*36392Ssklower 		sc = 0; \
79*36392Ssklower }
80*36392Ssklower 
81*36392Ssklower struct snpa_cache	*snpac_new();
82*36392Ssklower 
83*36392Ssklower /*
84*36392Ssklower  *	We only keep track of a single IS at a time.
85*36392Ssklower  */
86*36392Ssklower struct snpa_cache	*known_is;
87*36392Ssklower 
88*36392Ssklower /*
89*36392Ssklower  *	Addresses taken from NBS agreements, December 1987.
90*36392Ssklower  *
91*36392Ssklower  *	These addresses assume on-the-wire transmission of least significant
92*36392Ssklower  *	bit first. This is the method used by 802.3. When these
93*36392Ssklower  *	addresses are passed to the token ring driver, (802.5), they
94*36392Ssklower  *	must be bit-swaped because 802.5 transmission order is MSb first.
95*36392Ssklower  *
96*36392Ssklower  *	Furthermore, according to IBM Austin, these addresses are not
97*36392Ssklower  *	true token ring multicast addresses. More work is necessary
98*36392Ssklower  *	to get multicast to work right on token ring.
99*36392Ssklower  *
100*36392Ssklower  *	Currently, the token ring driver does not handle multicast, so
101*36392Ssklower  *	these addresses are converted into the broadcast address in
102*36392Ssklower  *	lan_output() That means that if these multicast addresses change
103*36392Ssklower  *	the token ring driver must be altered.
104*36392Ssklower  */
105*36392Ssklower struct snpa_cache	all_es = {
106*36392Ssklower 	{ { 0x0 },							/* sc_nsap */
107*36392Ssklower 	6,									/* sc_len */
108*36392Ssklower 	{ 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }, /* sc_snpa */
109*36392Ssklower 	SNPA_VALID,							/* sc_flags */
110*36392Ssklower 	0	}								/* sc_ht */
111*36392Ssklower };
112*36392Ssklower struct snpa_cache	all_is = {
113*36392Ssklower 	{ { 0x0 },							/* sc_nsap */
114*36392Ssklower 	6,									/* sc_len */
115*36392Ssklower 	{ 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }, /* sc_snpa */
116*36392Ssklower 	SNPA_VALID,							/* sc_flags */
117*36392Ssklower 	0	}								/* sc_ht */
118*36392Ssklower };
119*36392Ssklower 
120*36392Ssklower 
121*36392Ssklower /*
122*36392Ssklower  * FUNCTION:		iso_snparesolve
123*36392Ssklower  *
124*36392Ssklower  * PURPOSE:			Resolve an iso address into snpa address
125*36392Ssklower  *
126*36392Ssklower  * RETURNS:			0 if addr is resolved
127*36392Ssklower  *					errno if addr is unknown
128*36392Ssklower  *
129*36392Ssklower  * SIDE EFFECTS:
130*36392Ssklower  *
131*36392Ssklower  * NOTES:			If an entry is found that matches the address, that
132*36392Ssklower  *					snpa is returned. If no entry is found, but an IS is
133*36392Ssklower  *					known, then the address of the IS is returned. If
134*36392Ssklower  *					neither an address is found that matches or an IS is
135*36392Ssklower  *					known, then the multi-cast address for "all ES" for
136*36392Ssklower  *					this interface is returned.
137*36392Ssklower  *
138*36392Ssklower  *					NB: the last case described above constitutes the
139*36392Ssklower  *					query configuration function 9542, sec 6.5
140*36392Ssklower  *					A mechanism is needed to prevent this function from
141*36392Ssklower  *					being invoked if the system is an IS.
142*36392Ssklower  */
143*36392Ssklower iso_snparesolve(ifp, dst, snpa, snpa_len)
144*36392Ssklower struct ifnet 		*ifp;	/* outgoing interface */
145*36392Ssklower struct sockaddr_iso *dst;	/* destination */
146*36392Ssklower char				*snpa;	/* RESULT: snpa to be used */
147*36392Ssklower int					*snpa_len;	/* RESULT: length of snpa */
148*36392Ssklower {
149*36392Ssklower 	extern struct ifnet 	loif;		/* loopback interface */
150*36392Ssklower 	struct snpa_cache		*sc;		/* ptr to snpa table entry */
151*36392Ssklower 	struct iso_addr			*destiso;	/* destination iso addr */
152*36392Ssklower 	int						s;
153*36392Ssklower 
154*36392Ssklower  	destiso = &dst->siso_addr;
155*36392Ssklower 
156*36392Ssklower 	/*
157*36392Ssklower 	 *	This hack allows us to send esis packets that have the destination snpa
158*36392Ssklower 	 *	addresss embedded in the destination nsap address
159*36392Ssklower 	 */
160*36392Ssklower 	if (destiso->isoa_afi == AFI_SNA) {
161*36392Ssklower 		/*
162*36392Ssklower 		 *	This is a subnetwork address. Return it immediately
163*36392Ssklower 		 */
164*36392Ssklower 		IFDEBUG(D_SNPA)
165*36392Ssklower 			printf("iso_snparesolve: return SN address\n");
166*36392Ssklower 		ENDDEBUG
167*36392Ssklower 
168*36392Ssklower 		*snpa_len = destiso->isoa_len - 1;	/* subtract size of AFI */
169*36392Ssklower 		bcopy((caddr_t) destiso->sna_idi, (caddr_t)snpa, *snpa_len);
170*36392Ssklower 		return (0);
171*36392Ssklower 	}
172*36392Ssklower 
173*36392Ssklower 	IFDEBUG(D_SNPA)
174*36392Ssklower 		printf("iso_snparesolve: resolving %s\n", clnp_iso_addrp(destiso));
175*36392Ssklower 	ENDDEBUG
176*36392Ssklower 
177*36392Ssklower 	/*
178*36392Ssklower 	 *	packet is not for us, check cache for an entry
179*36392Ssklower 	 */
180*36392Ssklower 	s = splimp();
181*36392Ssklower 	SNPAC_LOOK(sc, destiso);
182*36392Ssklower 	if (sc == 0) {			/* not found */
183*36392Ssklower 		/* If we are an IS, we can't do much with the packet */
184*36392Ssklower 		if (iso_systype == SNPA_IS)
185*36392Ssklower 			goto bad;
186*36392Ssklower 
187*36392Ssklower 		/*
188*36392Ssklower 		 *	Check if we know about an IS
189*36392Ssklower 		 */
190*36392Ssklower 		if ((known_is) && (known_is->sc_flags & SNPA_VALID)) {
191*36392Ssklower 			sc = known_is;
192*36392Ssklower 		} else if (ifp->if_flags & IFF_BROADCAST) {
193*36392Ssklower 			/*
194*36392Ssklower 			 *	no IS, no match. Return "all es" multicast address for this
195*36392Ssklower 			 *	interface, as per Query Configuration Function (9542 sec 6.5)
196*36392Ssklower 			 *
197*36392Ssklower 			 *	Note: there is a potential problem here. If the destination
198*36392Ssklower 			 *	is on the subnet and it does not respond with a ESH, but
199*36392Ssklower 			 *	does send back a TP CC, a connection could be established
200*36392Ssklower 			 *	where we always transmit the CLNP packet to "all es"
201*36392Ssklower 			 */
202*36392Ssklower 			sc = &all_es;
203*36392Ssklower 		} else {
204*36392Ssklower 			goto bad;
205*36392Ssklower 		}
206*36392Ssklower 	}
207*36392Ssklower 
208*36392Ssklower 	bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len);
209*36392Ssklower 	*snpa_len = sc->sc_len;
210*36392Ssklower 	splx(s);
211*36392Ssklower 	return (0);
212*36392Ssklower 
213*36392Ssklower bad:
214*36392Ssklower 	splx(s);
215*36392Ssklower 	return(ENETUNREACH);
216*36392Ssklower }
217*36392Ssklower 
218*36392Ssklower 
219*36392Ssklower /*
220*36392Ssklower  * FUNCTION:		snpac_look
221*36392Ssklower  *
222*36392Ssklower  * PURPOSE:			Look up an entry in the snpa cache
223*36392Ssklower  *
224*36392Ssklower  * RETURNS:			Pointer to snpa_cache structure, or null
225*36392Ssklower  *
226*36392Ssklower  * SIDE EFFECTS:
227*36392Ssklower  *
228*36392Ssklower  * NOTES:			This is simply SNPAC_LOOK as a procedure.
229*36392Ssklower  */
230*36392Ssklower struct snpa_cache *
231*36392Ssklower snpac_look(isoa)
232*36392Ssklower struct iso_addr *isoa;	/* destination nsap */
233*36392Ssklower {
234*36392Ssklower 	struct snpa_cache	*sc;
235*36392Ssklower 	int 				s = splimp();
236*36392Ssklower 
237*36392Ssklower 	SNPAC_LOOK(sc, isoa);
238*36392Ssklower 
239*36392Ssklower 	splx(s);
240*36392Ssklower 	return(sc);
241*36392Ssklower }
242*36392Ssklower 
243*36392Ssklower /*
244*36392Ssklower  * FUNCTION:		iso_8208snparesolve
245*36392Ssklower  *
246*36392Ssklower  * PURPOSE:			Find the X.121 address that corresponds to an NSAP addr
247*36392Ssklower  *
248*36392Ssklower  * RETURNS:			0 or unix errno
249*36392Ssklower  *
250*36392Ssklower  * SIDE EFFECTS:
251*36392Ssklower  *
252*36392Ssklower  * NOTES:			This ought to invoke the 8208 ES-IS function
253*36392Ssklower  */
254*36392Ssklower iso_8208snparesolve(dst, snpa, snpa_len)
255*36392Ssklower struct sockaddr_iso *dst;	/* destination */
256*36392Ssklower char				*snpa;	/* RESULT: snpa to be used */
257*36392Ssklower int					*snpa_len;	/* RESULT: length of snpa */
258*36392Ssklower {
259*36392Ssklower 	struct snpa_cache		*sc;		/* ptr to snpa table entry */
260*36392Ssklower 	struct iso_addr			*destiso;	/* destination iso addr */
261*36392Ssklower 	int						s;
262*36392Ssklower 	int						err = 0;
263*36392Ssklower 
264*36392Ssklower  	destiso = &dst->siso_addr;
265*36392Ssklower 
266*36392Ssklower 	s = splimp();
267*36392Ssklower 	SNPAC_LOOK(sc, destiso);
268*36392Ssklower 	if (sc) {
269*36392Ssklower 		bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len);
270*36392Ssklower 		*snpa_len = sc->sc_len;
271*36392Ssklower 	} else {
272*36392Ssklower 		err = ENETUNREACH;
273*36392Ssklower 	}
274*36392Ssklower 	splx(s);
275*36392Ssklower 	return (err);
276*36392Ssklower }
277*36392Ssklower 
278*36392Ssklower /*
279*36392Ssklower  * FUNCTION:		iso_8208snpaadd
280*36392Ssklower  *
281*36392Ssklower  * PURPOSE:			Add an entry to the snpa cache
282*36392Ssklower  *
283*36392Ssklower  * RETURNS:
284*36392Ssklower  *
285*36392Ssklower  * SIDE EFFECTS:
286*36392Ssklower  *
287*36392Ssklower  * NOTES:			used by cons
288*36392Ssklower  */
289*36392Ssklower iso_8208snpaadd(ifp, nsap, snpa, snpalen, ht)
290*36392Ssklower struct ifnet		*ifp;		/* interface info is related to */
291*36392Ssklower struct iso_addr		*nsap;		/* nsap to add */
292*36392Ssklower caddr_t				snpa;		/* translation */
293*36392Ssklower int					snpalen;	/* length in bytes */
294*36392Ssklower short				ht;			/* holding time (in seconds) */
295*36392Ssklower {
296*36392Ssklower 	snpac_add(ifp, nsap, snpa, snpalen, SNPA_ES, ht);
297*36392Ssklower }
298*36392Ssklower 
299*36392Ssklower /*
300*36392Ssklower  * FUNCTION:		iso_8208snpadelete
301*36392Ssklower  *
302*36392Ssklower  * PURPOSE:			Delete an entry from the snpa cache
303*36392Ssklower  *
304*36392Ssklower  * RETURNS:			nothing
305*36392Ssklower  *
306*36392Ssklower  * SIDE EFFECTS:
307*36392Ssklower  *
308*36392Ssklower  * NOTES:			used by CONS
309*36392Ssklower  */
310*36392Ssklower iso_8208snpadelete(nsap)
311*36392Ssklower struct iso_addr	*nsap;
312*36392Ssklower {
313*36392Ssklower 	struct snpa_cache	*sc = snpac_look(nsap);
314*36392Ssklower 
315*36392Ssklower 	if (sc != NULL)
316*36392Ssklower 		snpac_free(sc);
317*36392Ssklower }
318*36392Ssklower 
319*36392Ssklower /*
320*36392Ssklower  * FUNCTION:		snpac_new
321*36392Ssklower  *
322*36392Ssklower  * PURPOSE:			create a new entry in the iso address to ethernet
323*36392Ssklower  *					address table
324*36392Ssklower  *
325*36392Ssklower  * RETURNS:			pointer to newest entry
326*36392Ssklower  *
327*36392Ssklower  * SIDE EFFECTS:	times out old entries if no new entries are found
328*36392Ssklower  *
329*36392Ssklower  * NOTES:			If the bucket is full, then timeout the oldest entry
330*36392Ssklower  *					(ie. the one with the youngest holding time)
331*36392Ssklower  */
332*36392Ssklower struct snpa_cache *
333*36392Ssklower snpac_new(isoa)
334*36392Ssklower struct iso_addr *isoa;		/* iso address to enter into table */
335*36392Ssklower {
336*36392Ssklower 	register struct snpa_cache	*sc;
337*36392Ssklower 	register int 				n;
338*36392Ssklower 	int							smallest_ht = 1000000;
339*36392Ssklower 	struct snpa_cache			*maybe;
340*36392Ssklower 
341*36392Ssklower 	sc = &iso_snpac[SNPAC_HASH(isoa) * SNPAC_BSIZ];
342*36392Ssklower 	for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) {
343*36392Ssklower 
344*36392Ssklower 		IFDEBUG (D_IOCTL)
345*36392Ssklower 			printf("snpac_new: sc x%x ", sc);
346*36392Ssklower 
347*36392Ssklower 			if (sc->sc_flags & SNPA_VALID) {
348*36392Ssklower 				int i;
349*36392Ssklower 
350*36392Ssklower 				printf("(valid) %s ", clnp_iso_addrp(&sc->sc_nsap));
351*36392Ssklower 				for (i=0; i<sc->sc_len; i++)
352*36392Ssklower 					printf("%x%c", sc->sc_snpa[i], i < (sc->sc_len-1) ? ':'
353*36392Ssklower 						: '\n');
354*36392Ssklower 			} else {
355*36392Ssklower 				printf("invalid\n");
356*36392Ssklower 			}
357*36392Ssklower 		ENDDEBUG
358*36392Ssklower 
359*36392Ssklower 		if (sc->sc_flags & SNPA_VALID) {
360*36392Ssklower 			if (sc->sc_ht < smallest_ht) {
361*36392Ssklower 				smallest_ht = sc->sc_ht;
362*36392Ssklower 				maybe = sc;
363*36392Ssklower 			}
364*36392Ssklower 		} else {
365*36392Ssklower 			return sc; /* found unused slot */
366*36392Ssklower 		}
367*36392Ssklower 	}
368*36392Ssklower 	snpac_free(maybe);
369*36392Ssklower 	return maybe;
370*36392Ssklower }
371*36392Ssklower 
372*36392Ssklower /*
373*36392Ssklower  * FUNCTION:		snpac_free
374*36392Ssklower  *
375*36392Ssklower  * PURPOSE:			free an entry in the iso address map table
376*36392Ssklower  *
377*36392Ssklower  * RETURNS:			nothing
378*36392Ssklower  *
379*36392Ssklower  * SIDE EFFECTS:
380*36392Ssklower  *
381*36392Ssklower  * NOTES:			If there is a route entry associated with cache
382*36392Ssklower  *					entry, then delete that as well
383*36392Ssklower  */
384*36392Ssklower snpac_free(sc)
385*36392Ssklower register struct snpa_cache *sc;		/* entry to free */
386*36392Ssklower {
387*36392Ssklower 	int s = splimp();
388*36392Ssklower 
389*36392Ssklower 	if (known_is == sc) {
390*36392Ssklower 		snpac_rtrequest(SIOCDELRT, &zero_isoa, &known_is->sc_nsap,
391*36392Ssklower 			RTF_DYNAMIC|RTF_GATEWAY);
392*36392Ssklower 		known_is = NULL;
393*36392Ssklower 	}
394*36392Ssklower 	if (sc->sc_da.isoa_len > 0) {
395*36392Ssklower 		snpac_rtrequest(SIOCDELRT, &sc->sc_da, &known_is->sc_nsap,
396*36392Ssklower 			RTF_DYNAMIC|RTF_GATEWAY);
397*36392Ssklower 	}
398*36392Ssklower 	bzero((caddr_t)sc, sizeof(struct snpa_cache));
399*36392Ssklower 
400*36392Ssklower 	splx(s);
401*36392Ssklower }
402*36392Ssklower 
403*36392Ssklower /*
404*36392Ssklower  * FUNCTION:		snpac_add
405*36392Ssklower  *
406*36392Ssklower  * PURPOSE:			Add an entry to the snpa cache
407*36392Ssklower  *
408*36392Ssklower  * RETURNS:
409*36392Ssklower  *
410*36392Ssklower  * SIDE EFFECTS:
411*36392Ssklower  *
412*36392Ssklower  * NOTES:			If entry already exists, then update holding time.
413*36392Ssklower  */
414*36392Ssklower snpac_add(ifp, nsap, snpa, snpalen, type, ht)
415*36392Ssklower struct ifnet		*ifp;		/* interface info is related to */
416*36392Ssklower struct iso_addr		*nsap;		/* nsap to add */
417*36392Ssklower caddr_t				snpa;		/* translation */
418*36392Ssklower int					snpalen;	/* length in bytes */
419*36392Ssklower char				type;		/* SNPA_IS or SNPA_ES */
420*36392Ssklower short				ht;			/* holding time (in seconds) */
421*36392Ssklower {
422*36392Ssklower 	struct snpa_cache	*sc;
423*36392Ssklower 	int					s = splimp();
424*36392Ssklower 
425*36392Ssklower 	SNPAC_LOOK(sc, nsap);
426*36392Ssklower 	if (sc == NULL) {
427*36392Ssklower 		sc = snpac_new(nsap);
428*36392Ssklower 		sc->sc_nsap = *nsap;
429*36392Ssklower 	}
430*36392Ssklower 
431*36392Ssklower 	sc->sc_ht = ht;
432*36392Ssklower 
433*36392Ssklower 	sc->sc_len = min(snpalen, MAX_SNPALEN);
434*36392Ssklower 	bcopy(snpa, sc->sc_snpa, sc->sc_len);
435*36392Ssklower 	sc->sc_flags = SNPA_VALID | type;
436*36392Ssklower 	sc->sc_ifp = ifp;
437*36392Ssklower 
438*36392Ssklower 	if (type & SNPA_IS)
439*36392Ssklower 		snpac_logdefis(sc);
440*36392Ssklower 
441*36392Ssklower 	splx(s);
442*36392Ssklower }
443*36392Ssklower 
444*36392Ssklower /*
445*36392Ssklower  * FUNCTION:		snpac_ioctl
446*36392Ssklower  *
447*36392Ssklower  * PURPOSE:			handle ioctls to change the iso address map
448*36392Ssklower  *
449*36392Ssklower  * RETURNS:			unix error code
450*36392Ssklower  *
451*36392Ssklower  * SIDE EFFECTS:	changes the snpa_cache table declared above.
452*36392Ssklower  *
453*36392Ssklower  * NOTES:
454*36392Ssklower  */
455*36392Ssklower snpac_ioctl(cmd, data)
456*36392Ssklower int		cmd;		/* ioctl to process */
457*36392Ssklower caddr_t	data;	/* data for the cmd */
458*36392Ssklower {
459*36392Ssklower 	register struct snpa_req	*rq = (struct snpa_req *)data;
460*36392Ssklower 	register struct snpa_cache	*sc;
461*36392Ssklower 	register struct iso_addr	*isoa;
462*36392Ssklower 	int							s;
463*36392Ssklower 
464*36392Ssklower 	/* look up this address in table */
465*36392Ssklower 	isoa = &rq->sr_isoa;
466*36392Ssklower 
467*36392Ssklower 	/* sanity check */
468*36392Ssklower 	if (rq->sr_len > MAX_SNPALEN)
469*36392Ssklower 		return(EINVAL);
470*36392Ssklower 
471*36392Ssklower 	IFDEBUG (D_IOCTL)
472*36392Ssklower 		int i;
473*36392Ssklower 
474*36392Ssklower 		printf("snpac_ioctl: ");
475*36392Ssklower 		switch(cmd) {
476*36392Ssklower 			case SIOCSISOMAP: printf("set"); break;
477*36392Ssklower 			case SIOCDISOMAP: printf("delete"); break;
478*36392Ssklower 			case SIOCGISOMAP: printf("get"); break;
479*36392Ssklower 		}
480*36392Ssklower 		printf(" %s to ", clnp_iso_addrp(isoa));
481*36392Ssklower 		for (i=0; i<rq->sr_len; i++)
482*36392Ssklower 			printf("%x%c", rq->sr_snpa[i], i < (rq->sr_len-1) ? ':' : '\n');
483*36392Ssklower 	ENDDEBUG
484*36392Ssklower 
485*36392Ssklower 	s = splimp();
486*36392Ssklower 	SNPAC_LOOK(sc, isoa);
487*36392Ssklower 	if (sc == NULL) {	 /* not found */
488*36392Ssklower 		if (cmd != SIOCSISOMAP)
489*36392Ssklower 			return(ENXIO);
490*36392Ssklower 	}
491*36392Ssklower 
492*36392Ssklower 	switch(cmd) {
493*36392Ssklower 		case SIOCSISOMAP:	/* set entry */
494*36392Ssklower 			snpac_add(NULL, isoa, rq->sr_snpa, rq->sr_len,
495*36392Ssklower 				rq->sr_flags & (SNPA_ES|SNPA_IS|SNPA_PERM), rq->sr_ht);
496*36392Ssklower 			break;
497*36392Ssklower 
498*36392Ssklower 		case SIOCDISOMAP:	/* delete entry */
499*36392Ssklower 			snpac_free(sc);
500*36392Ssklower 			break;
501*36392Ssklower 
502*36392Ssklower 		case SIOCGISOMAP:	/* get entry */
503*36392Ssklower 			bcopy((caddr_t)&sc->sc_sr, rq, sizeof(struct snpa_req));
504*36392Ssklower 			break;
505*36392Ssklower 	}
506*36392Ssklower 	splx(s);
507*36392Ssklower 	return(0);
508*36392Ssklower }
509*36392Ssklower 
510*36392Ssklower /*
511*36392Ssklower  * FUNCTION:		iso_tryloopback
512*36392Ssklower  *
513*36392Ssklower  * PURPOSE:			Attempt to use the software loopback interface for pkt
514*36392Ssklower  *
515*36392Ssklower  * RETURNS:			0		if packet was sent successfully
516*36392Ssklower  *					errno	if there was a problem sending the packet
517*36392Ssklower  *							Ie. the return value of looutput
518*36392Ssklower  *					-1 		if software loopback is not appropriate
519*36392Ssklower  *
520*36392Ssklower  * SIDE EFFECTS:
521*36392Ssklower  *
522*36392Ssklower  * NOTES:
523*36392Ssklower  */
524*36392Ssklower iso_tryloopback(m, dst)
525*36392Ssklower struct mbuf			*m;		/* pkt */
526*36392Ssklower struct sockaddr_iso *dst;	/* destination */
527*36392Ssklower {
528*36392Ssklower 	struct iso_addr			*destiso;	/* destination iso addr */
529*36392Ssklower 
530*36392Ssklower  	destiso = &dst->siso_addr;
531*36392Ssklower 
532*36392Ssklower 	if (clnp_ours(destiso)) {
533*36392Ssklower 		IFDEBUG(D_SNPA)
534*36392Ssklower 			printf("iso_tryloopback: local destination\n");
535*36392Ssklower 		ENDDEBUG
536*36392Ssklower 		if (loif.if_flags & IFF_UP) {
537*36392Ssklower 			IFDEBUG(D_SNPA)
538*36392Ssklower 				printf("iso_tryloopback: calling looutput\n");
539*36392Ssklower 			ENDDEBUG
540*36392Ssklower 			return (looutput(&loif, m, (struct sockaddr *)dst));
541*36392Ssklower 		}
542*36392Ssklower 	}
543*36392Ssklower 	return (-1);
544*36392Ssklower }
545*36392Ssklower 
546*36392Ssklower /*
547*36392Ssklower  * FUNCTION:		snpac_systype
548*36392Ssklower  *
549*36392Ssklower  * PURPOSE:			Set/Get the system type and esis parameters
550*36392Ssklower  *
551*36392Ssklower  * RETURNS:			0 on success, or unix error code
552*36392Ssklower  *
553*36392Ssklower  * SIDE EFFECTS:
554*36392Ssklower  *
555*36392Ssklower  * NOTES:
556*36392Ssklower  */
557*36392Ssklower snpac_systype (cmd, data)
558*36392Ssklower int		cmd;	/* ioctl to process */
559*36392Ssklower caddr_t	data;	/* data for the cmd */
560*36392Ssklower {
561*36392Ssklower 	register struct systype_req *rq = (struct systype_req *)data;
562*36392Ssklower 	extern short	esis_holding_time, esis_config_time;
563*36392Ssklower 
564*36392Ssklower 	IFDEBUG (D_IOCTL)
565*36392Ssklower 		if (cmd == SIOCSSTYPE)
566*36392Ssklower 			printf("snpac_systype: cmd set, type x%x, ht %d, ct %d\n",
567*36392Ssklower 				rq->sr_type, rq->sr_holdt, rq->sr_configt);
568*36392Ssklower 		else
569*36392Ssklower 			printf("snpac_systype: cmd get\n");
570*36392Ssklower 	ENDDEBUG
571*36392Ssklower 
572*36392Ssklower 	if (cmd == SIOCSSTYPE) {
573*36392Ssklower 		if (!suser())
574*36392Ssklower 			return(EACCES);
575*36392Ssklower 		if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS))
576*36392Ssklower 			return(EINVAL);
577*36392Ssklower 		if (rq->sr_type & SNPA_ES) {
578*36392Ssklower 			iso_systype = SNPA_ES;
579*36392Ssklower 		} else if (rq->sr_type & SNPA_IS) {
580*36392Ssklower 			iso_systype = SNPA_IS;
581*36392Ssklower 		} else {
582*36392Ssklower 			return(EINVAL);
583*36392Ssklower 		}
584*36392Ssklower 		esis_holding_time = rq->sr_holdt;
585*36392Ssklower 		esis_config_time = rq->sr_configt;
586*36392Ssklower 	} else if (cmd == SIOCGSTYPE) {
587*36392Ssklower 		rq->sr_type = iso_systype;
588*36392Ssklower 		rq->sr_holdt = esis_holding_time;
589*36392Ssklower 		rq->sr_configt = esis_config_time;
590*36392Ssklower 	} else {
591*36392Ssklower 		return(EINVAL);
592*36392Ssklower 	}
593*36392Ssklower 	return(0);
594*36392Ssklower }
595*36392Ssklower 
596*36392Ssklower /*
597*36392Ssklower  * FUNCTION:		snpac_logdefis
598*36392Ssklower  *
599*36392Ssklower  * PURPOSE:			Mark the IS passed as the default IS
600*36392Ssklower  *
601*36392Ssklower  * RETURNS:			nothing
602*36392Ssklower  *
603*36392Ssklower  * SIDE EFFECTS:
604*36392Ssklower  *
605*36392Ssklower  * NOTES:
606*36392Ssklower  */
607*36392Ssklower snpac_logdefis(sc)
608*36392Ssklower struct snpa_cache	*sc;
609*36392Ssklower {
610*36392Ssklower 	if (known_is) {
611*36392Ssklower 		snpac_rtrequest(SIOCDELRT, &zero_isoa, &known_is->sc_nsap,
612*36392Ssklower 			RTF_DYNAMIC|RTF_GATEWAY);
613*36392Ssklower 	}
614*36392Ssklower 	known_is = sc;
615*36392Ssklower 	snpac_rtrequest(SIOCADDRT, &zero_isoa, &sc->sc_nsap,
616*36392Ssklower 		RTF_DYNAMIC|RTF_GATEWAY);
617*36392Ssklower }
618*36392Ssklower 
619*36392Ssklower /*
620*36392Ssklower  * FUNCTION:		snpac_age
621*36392Ssklower  *
622*36392Ssklower  * PURPOSE:			Time out snpac entries
623*36392Ssklower  *
624*36392Ssklower  * RETURNS:
625*36392Ssklower  *
626*36392Ssklower  * SIDE EFFECTS:
627*36392Ssklower  *
628*36392Ssklower  * NOTES:			When encountering an entry for the first time, snpac_age
629*36392Ssklower  *					may delete up to SNPAC_AGE too many seconds. Ie.
630*36392Ssklower  *					if the entry is added a moment before snpac_age is
631*36392Ssklower  *					called, the entry will immediately have SNPAC_AGE
632*36392Ssklower  *					seconds taken off the holding time, even though
633*36392Ssklower  *					it has only been held a brief moment.
634*36392Ssklower  *
635*36392Ssklower  *					The proper way to do this is set an expiry timeval
636*36392Ssklower  *					equal to current time + holding time. Then snpac_age
637*36392Ssklower  *					would time out entries where expiry date is older
638*36392Ssklower  *					than the current time.
639*36392Ssklower  */
640*36392Ssklower snpac_age()
641*36392Ssklower {
642*36392Ssklower 	register struct snpa_cache	*sc;
643*36392Ssklower 	register int 				i;
644*36392Ssklower 
645*36392Ssklower 	timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz);
646*36392Ssklower 
647*36392Ssklower 	sc = &iso_snpac[0];
648*36392Ssklower 	for (i=0; i<SNPAC_SIZE; i++, sc++) {
649*36392Ssklower 		if (((sc->sc_flags & SNPA_PERM) == 0) && (sc->sc_flags & SNPA_VALID)) {
650*36392Ssklower 			sc->sc_ht -= SNPAC_AGE;
651*36392Ssklower 			if (sc->sc_ht > 0)
652*36392Ssklower 				continue;
653*36392Ssklower 			else
654*36392Ssklower 				snpac_free(sc);
655*36392Ssklower 		}
656*36392Ssklower 	}
657*36392Ssklower }
658*36392Ssklower 
659*36392Ssklower /*
660*36392Ssklower  * FUNCTION:		snpac_ownmulti
661*36392Ssklower  *
662*36392Ssklower  * PURPOSE:			Determine if the snpa address is a multicast address
663*36392Ssklower  *					of the same type as the system.
664*36392Ssklower  *
665*36392Ssklower  * RETURNS:			true or false
666*36392Ssklower  *
667*36392Ssklower  * SIDE EFFECTS:
668*36392Ssklower  *
669*36392Ssklower  * NOTES:			Used by interface drivers when not in eavesdrop mode
670*36392Ssklower  *					as interm kludge until
671*36392Ssklower  *					real multicast addresses can be configured
672*36392Ssklower  */
673*36392Ssklower snpac_ownmulti(snpa, len)
674*36392Ssklower char	*snpa;
675*36392Ssklower int		len;
676*36392Ssklower {
677*36392Ssklower 	return (((iso_systype & SNPA_ES) && (!bcmp(snpa, all_es.sc_snpa, len)))
678*36392Ssklower 		|| ((iso_systype & SNPA_IS) && (!bcmp(snpa, all_is.sc_snpa, len))));
679*36392Ssklower }
680*36392Ssklower 
681*36392Ssklower /*
682*36392Ssklower  * FUNCTION:		snpac_flushifp
683*36392Ssklower  *
684*36392Ssklower  * PURPOSE:			Flush entries associated with specific ifp
685*36392Ssklower  *
686*36392Ssklower  * RETURNS:			nothing
687*36392Ssklower  *
688*36392Ssklower  * SIDE EFFECTS:
689*36392Ssklower  *
690*36392Ssklower  * NOTES:
691*36392Ssklower  */
692*36392Ssklower snpac_flushifp(ifp)
693*36392Ssklower struct ifnet	*ifp;
694*36392Ssklower {
695*36392Ssklower 	register struct snpa_cache	*sc;
696*36392Ssklower 	register int 				i;
697*36392Ssklower 
698*36392Ssklower 	sc = &iso_snpac[0];
699*36392Ssklower 	for (i=0; i<SNPAC_SIZE; i++, sc++) {
700*36392Ssklower 		if ((sc->sc_ifp == ifp) && (sc->sc_flags & SNPA_VALID)) {
701*36392Ssklower 			snpac_free(sc);
702*36392Ssklower 		}
703*36392Ssklower 	}
704*36392Ssklower }
705*36392Ssklower 
706*36392Ssklower /*
707*36392Ssklower  * FUNCTION:		snpac_rtrequest
708*36392Ssklower  *
709*36392Ssklower  * PURPOSE:			Make a routing request
710*36392Ssklower  *
711*36392Ssklower  * RETURNS:			nothing
712*36392Ssklower  *
713*36392Ssklower  * SIDE EFFECTS:
714*36392Ssklower  *
715*36392Ssklower  * NOTES:			In the future, this should make a request of a user
716*36392Ssklower  *					level routing daemon.
717*36392Ssklower  */
718*36392Ssklower snpac_rtrequest(req, dst, gateway, flags)
719*36392Ssklower int				req;
720*36392Ssklower struct iso_addr	*dst;
721*36392Ssklower struct iso_addr	*gateway;
722*36392Ssklower short			flags;
723*36392Ssklower {
724*36392Ssklower 	struct rtentry	rte;
725*36392Ssklower 	struct iso_addr	*isoa;
726*36392Ssklower 
727*36392Ssklower 	IFDEBUG(D_SNPA)
728*36392Ssklower 		printf("snpac_rtrequest: ");
729*36392Ssklower 		if (req == SIOCADDRT)
730*36392Ssklower 			printf("add");
731*36392Ssklower 		else if (req == SIOCDELRT)
732*36392Ssklower 			printf("delete");
733*36392Ssklower 		else
734*36392Ssklower 			printf("unknown command");
735*36392Ssklower 		printf(" dst: %s\n", clnp_iso_addrp(dst));
736*36392Ssklower 		printf("\tgateway: %s\n", clnp_iso_addrp(gateway));
737*36392Ssklower 	ENDDEBUG
738*36392Ssklower 
739*36392Ssklower 	bzero((caddr_t)&rte, sizeof(struct rtentry));
740*36392Ssklower 	rte.rt_dst.sa_family = rte.rt_gateway.sa_family = AF_ISO;
741*36392Ssklower 	isoa = &((struct sockaddr_iso *)&rte.rt_dst)->siso_addr;
742*36392Ssklower 	*isoa = *dst;
743*36392Ssklower 	isoa = &((struct sockaddr_iso *)&rte.rt_gateway)->siso_addr;
744*36392Ssklower 	*isoa = *gateway;
745*36392Ssklower 	rte.rt_flags = RTF_UP|flags;
746*36392Ssklower 
747*36392Ssklower 	rtrequest(req, &rte);
748*36392Ssklower }
749*36392Ssklower 
750*36392Ssklower 
751*36392Ssklower /*
752*36392Ssklower  * FUNCTION:		snpac_addrt
753*36392Ssklower  *
754*36392Ssklower  * PURPOSE:			Associate a routing entry with an snpac entry
755*36392Ssklower  *
756*36392Ssklower  * RETURNS:			nothing
757*36392Ssklower  *
758*36392Ssklower  * SIDE EFFECTS:
759*36392Ssklower  *
760*36392Ssklower  * NOTES:			If a cache entry exists for gateway, then
761*36392Ssklower  *					make a routing entry (host, gateway) and associate
762*36392Ssklower  *					with gateway.
763*36392Ssklower  *
764*36392Ssklower  *					If a route already exists and is different, first delete
765*36392Ssklower  *					it.
766*36392Ssklower  *
767*36392Ssklower  *					This could be made more efficient by checking
768*36392Ssklower  *					the existing route before adding a new one.
769*36392Ssklower  */
770*36392Ssklower snpac_addrt(host, gateway)
771*36392Ssklower struct iso_addr	*host;
772*36392Ssklower struct iso_addr	*gateway;
773*36392Ssklower {
774*36392Ssklower 	struct snpa_cache	*sc;
775*36392Ssklower 	int					s;
776*36392Ssklower 
777*36392Ssklower 	s = splimp();
778*36392Ssklower 	SNPAC_LOOK(sc, gateway);
779*36392Ssklower 	if (sc != NULL) {
780*36392Ssklower 		snpac_rtrequest(SIOCDELRT, &sc->sc_da, gateway,
781*36392Ssklower 			RTF_DYNAMIC|RTF_GATEWAY);
782*36392Ssklower 		snpac_rtrequest(SIOCADDRT, host, gateway, RTF_DYNAMIC|RTF_GATEWAY);
783*36392Ssklower 		bcopy(host, &sc->sc_da, sizeof(struct iso_addr));
784*36392Ssklower 	}
785*36392Ssklower 	s = splx(s);
786*36392Ssklower }
787*36392Ssklower #endif	ISO
788