xref: /original-bsd/sys/netiso/iso.c (revision 7fa9e8f7)
17981378eSbostic /*-
2fdf395daSbostic  * Copyright (c) 1991, 1993
3fdf395daSbostic  *	The Regents of the University of California.  All rights reserved.
47981378eSbostic  *
57981378eSbostic  * %sccs.include.redist.c%
67981378eSbostic  *
7*7fa9e8f7Scgd  *	@(#)iso.c	8.3 (Berkeley) 01/09/95
87981378eSbostic  */
97981378eSbostic 
10e014b9acSsklower /***********************************************************
11e014b9acSsklower 		Copyright IBM Corporation 1987
12e014b9acSsklower 
13e014b9acSsklower                       All Rights Reserved
14e014b9acSsklower 
15e014b9acSsklower Permission to use, copy, modify, and distribute this software and its
16e014b9acSsklower documentation for any purpose and without fee is hereby granted,
17e014b9acSsklower provided that the above copyright notice appear in all copies and that
18e014b9acSsklower both that copyright notice and this permission notice appear in
19e014b9acSsklower supporting documentation, and that the name of IBM not be
20e014b9acSsklower used in advertising or publicity pertaining to distribution of the
21e014b9acSsklower software without specific, written prior permission.
22e014b9acSsklower 
23e014b9acSsklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24e014b9acSsklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25e014b9acSsklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26e014b9acSsklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27e014b9acSsklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28e014b9acSsklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29e014b9acSsklower SOFTWARE.
30e014b9acSsklower 
31e014b9acSsklower ******************************************************************/
32e014b9acSsklower 
33e014b9acSsklower /*
34e014b9acSsklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
35e014b9acSsklower  */
36e014b9acSsklower /*
37e014b9acSsklower  * $Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $
38e014b9acSsklower  * $Source: /usr/argo/sys/netiso/RCS/iso.c,v $
39e014b9acSsklower  *
40e014b9acSsklower  * iso.c: miscellaneous routines to support the iso address family
41e014b9acSsklower  */
42e014b9acSsklower 
43e1ca26eaSbostic #include <sys/param.h>
44e1ca26eaSbostic #include <sys/systm.h>
45e1ca26eaSbostic #include <sys/ioctl.h>
46e1ca26eaSbostic #include <sys/mbuf.h>
47e1ca26eaSbostic #include <sys/domain.h>
48e1ca26eaSbostic #include <sys/protosw.h>
49e1ca26eaSbostic #include <sys/socket.h>
50e1ca26eaSbostic #include <sys/socketvar.h>
51e1ca26eaSbostic #include <sys/errno.h>
52e014b9acSsklower 
53e1ca26eaSbostic #include <net/if.h>
54e1ca26eaSbostic #include <net/route.h>
55e014b9acSsklower 
56e1ca26eaSbostic #include <netiso/iso.h>
57e1ca26eaSbostic #include <netiso/iso_var.h>
58e1ca26eaSbostic #include <netiso/iso_snpac.h>
59e1ca26eaSbostic #include <netiso/iso_pcb.h>
60e1ca26eaSbostic #include <netiso/clnp.h>
61e1ca26eaSbostic #include <netiso/argo_debug.h>
6268756140Ssklower #ifdef TUBA
6368756140Ssklower #include <netiso/tuba_table.h>
6468756140Ssklower #endif
65e014b9acSsklower 
66e014b9acSsklower #ifdef ISO
67e014b9acSsklower 
68e014b9acSsklower int	iso_interfaces = 0;		/* number of external interfaces */
69e014b9acSsklower extern	struct ifnet loif;	/* loopback interface */
701dd7e156Ssklower int	ether_output();
711dd7e156Ssklower void	llc_rtrequest();
72e014b9acSsklower 
73e014b9acSsklower /*
74e014b9acSsklower  * FUNCTION:		iso_addrmatch1
75e014b9acSsklower  *
76e014b9acSsklower  * PURPOSE:			decide if the two iso_addrs passed are equal
77e014b9acSsklower  *
78e014b9acSsklower  * RETURNS:			true if the addrs match, false if they do not
79e014b9acSsklower  *
80e014b9acSsklower  * SIDE EFFECTS:
81e014b9acSsklower  *
82e014b9acSsklower  * NOTES:
83e014b9acSsklower  */
iso_addrmatch1(isoaa,isoab)84e014b9acSsklower iso_addrmatch1(isoaa, isoab)
850b7547b2Ssklower register struct iso_addr *isoaa, *isoab;		/* addresses to check */
86e014b9acSsklower {
870b7547b2Ssklower 	u_int	compare_len;
88e014b9acSsklower 
89e014b9acSsklower 	IFDEBUG(D_ROUTE)
90e014b9acSsklower 		printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len,
91e014b9acSsklower 			isoab->isoa_len);
92e014b9acSsklower 		printf("a:\n");
930b7547b2Ssklower 		dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len);
94e014b9acSsklower 		printf("b:\n");
950b7547b2Ssklower 		dump_buf(isoab->isoa_genaddr, isoab->isoa_len);
96e014b9acSsklower 	ENDDEBUG
97e014b9acSsklower 
98e014b9acSsklower 	if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) {
99e014b9acSsklower 		IFDEBUG(D_ROUTE)
100e014b9acSsklower 			printf("iso_addrmatch1: returning false because of lengths\n");
101e014b9acSsklower 		ENDDEBUG
102e014b9acSsklower 		return 0;
103e014b9acSsklower 	}
104e014b9acSsklower 
1050b7547b2Ssklower #ifdef notdef
106e014b9acSsklower 	/* TODO : generalize this to all afis with masks */
107e014b9acSsklower 	if(	isoaa->isoa_afi == AFI_37 ) {
108e014b9acSsklower 		/* must not compare 2 least significant digits, or for
109e014b9acSsklower 		 * that matter, the DSP
110e014b9acSsklower 		 */
111e014b9acSsklower 		compare_len = ADDR37_IDI_LEN - 1;
112e014b9acSsklower 	}
1130b7547b2Ssklower #endif
114e014b9acSsklower 
115e014b9acSsklower 	IFDEBUG(D_ROUTE)
116e014b9acSsklower 		int i;
117e014b9acSsklower 		char *a, *b;
118e014b9acSsklower 
1190b7547b2Ssklower 		a = isoaa->isoa_genaddr;
1200b7547b2Ssklower 		b = isoab->isoa_genaddr;
121e014b9acSsklower 
122e014b9acSsklower 		for (i=0; i<compare_len; i++) {
123e014b9acSsklower 			printf("<%x=%x>", a[i]&0xff, b[i]&0xff);
124e014b9acSsklower 			if (a[i] != b[i]) {
125e014b9acSsklower 				printf("\naddrs are not equal at byte %d\n", i);
126e014b9acSsklower 				return(0);
127e014b9acSsklower 			}
128e014b9acSsklower 		}
129e014b9acSsklower 		printf("\n");
130e014b9acSsklower 		printf("addrs are equal\n");
131e014b9acSsklower 		return (1);
132e014b9acSsklower 	ENDDEBUG
1330b7547b2Ssklower 	return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len));
134e014b9acSsklower }
135e014b9acSsklower 
136e014b9acSsklower /*
137e014b9acSsklower  * FUNCTION:		iso_addrmatch
138e014b9acSsklower  *
139e014b9acSsklower  * PURPOSE:			decide if the two sockadrr_isos passed are equal
140e014b9acSsklower  *
141e014b9acSsklower  * RETURNS:			true if the addrs match, false if they do not
142e014b9acSsklower  *
143e014b9acSsklower  * SIDE EFFECTS:
144e014b9acSsklower  *
145e014b9acSsklower  * NOTES:
146e014b9acSsklower  */
147e014b9acSsklower iso_addrmatch(sisoa, sisob)
148e014b9acSsklower struct sockaddr_iso	*sisoa, *sisob;		/* addresses to check */
149e014b9acSsklower {
150e014b9acSsklower 	return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr));
151e014b9acSsklower }
1520b7547b2Ssklower #ifdef notdef
153e014b9acSsklower /*
154e014b9acSsklower  * FUNCTION:		iso_netmatch
155e014b9acSsklower  *
156e014b9acSsklower  * PURPOSE:			similar to iso_addrmatch but takes sockaddr_iso
157e014b9acSsklower  *					as argument.
158e014b9acSsklower  *
159e014b9acSsklower  * RETURNS:			true if same net, false if not
160e014b9acSsklower  *
161e014b9acSsklower  * SIDE EFFECTS:
162e014b9acSsklower  *
163e014b9acSsklower  * NOTES:
164e014b9acSsklower  */
165e014b9acSsklower iso_netmatch(sisoa, sisob)
166e014b9acSsklower struct sockaddr_iso *sisoa, *sisob;
167e014b9acSsklower {
168e014b9acSsklower 	u_char			bufa[sizeof(struct sockaddr_iso)];
169e014b9acSsklower 	u_char			bufb[sizeof(struct sockaddr_iso)];
170e014b9acSsklower 	register int	lena, lenb;
171e014b9acSsklower 
172e014b9acSsklower 	lena = iso_netof(&sisoa->siso_addr, bufa);
173e014b9acSsklower 	lenb = iso_netof(&sisob->siso_addr, bufb);
174e014b9acSsklower 
175e014b9acSsklower 	IFDEBUG(D_ROUTE)
176e014b9acSsklower 		printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb);
177e014b9acSsklower 		printf("a:\n");
178e014b9acSsklower 		dump_buf(bufa, lena);
179e014b9acSsklower 		printf("b:\n");
180e014b9acSsklower 		dump_buf(bufb, lenb);
181e014b9acSsklower 	ENDDEBUG
182e014b9acSsklower 
183e014b9acSsklower 	return ((lena == lenb) && (!bcmp(bufa, bufb, lena)));
184e014b9acSsklower }
1855cbc22e2Sbostic #endif /* notdef */
186e014b9acSsklower 
187e014b9acSsklower /*
188e014b9acSsklower  * FUNCTION:		iso_hashchar
189e014b9acSsklower  *
190e014b9acSsklower  * PURPOSE:			Hash all character in the buffer specified into
191e014b9acSsklower  *					a long. Return the long.
192e014b9acSsklower  *
193e014b9acSsklower  * RETURNS:			The hash value.
194e014b9acSsklower  *
195e014b9acSsklower  * SIDE EFFECTS:
196e014b9acSsklower  *
197e014b9acSsklower  * NOTES:			The hash is achieved by exclusive ORing 4 byte
198e014b9acSsklower  *					quantities.
199e014b9acSsklower  */
200e014b9acSsklower u_long
iso_hashchar(buf,len)201e014b9acSsklower iso_hashchar(buf, len)
202e014b9acSsklower register caddr_t	buf;		/* buffer to pack from */
203e014b9acSsklower register int		len;		/* length of buffer */
204e014b9acSsklower {
205e014b9acSsklower 	register u_long	h = 0;
206e014b9acSsklower 	register int	i;
207e014b9acSsklower 
208e014b9acSsklower 	for (i=0; i<len; i+=4) {
209e014b9acSsklower 		register u_long	l = 0;
210e014b9acSsklower 
211e014b9acSsklower 		if ((len - i) < 4) {
212e014b9acSsklower 			/* buffer not multiple of 4 */
213e014b9acSsklower 			switch (len - i) {
214e014b9acSsklower 				case 3:
215e014b9acSsklower 					l |= buf[i+2] << 8;
216e014b9acSsklower 				case 2:
217e014b9acSsklower 					l |= buf[i+1] << 16;
218e014b9acSsklower 				case 1:
219e014b9acSsklower 					l |= buf[i] << 24;
220e014b9acSsklower 					break;
221e014b9acSsklower 				default:
222e014b9acSsklower 					printf("iso_hashchar: unexpected value x%x\n", len - i);
223e014b9acSsklower 					break;
224e014b9acSsklower 			}
225e014b9acSsklower 		} else {
226e014b9acSsklower 			l |= buf[i] << 24;
227e014b9acSsklower 			l |= buf[i+1] << 16;
228e014b9acSsklower 			l |= buf[i+2] << 8;
229e014b9acSsklower 			l |= buf[i+3];
230e014b9acSsklower 		}
231e014b9acSsklower 
232e014b9acSsklower 		h ^= l;
233e014b9acSsklower 	}
234e014b9acSsklower 
235e014b9acSsklower 	h ^= (u_long) (len % 4);
236e014b9acSsklower 
237e014b9acSsklower 	return(h);
238e014b9acSsklower }
2390b7547b2Ssklower #ifdef notdef
240e014b9acSsklower /*
241e014b9acSsklower  * FUNCTION:		iso_hash
242e014b9acSsklower  *
243e014b9acSsklower  * PURPOSE:			Fill in fields of afhash structure based upon addr passed.
244e014b9acSsklower  *
245e014b9acSsklower  * RETURNS:			none
246e014b9acSsklower  *
247e014b9acSsklower  * SIDE EFFECTS:
248e014b9acSsklower  *
249e014b9acSsklower  * NOTES:
250e014b9acSsklower  */
251e014b9acSsklower iso_hash(siso, hp)
252e014b9acSsklower struct sockaddr_iso	*siso;		/* address to perform hash on */
253e014b9acSsklower struct afhash		*hp;		/* RETURN: hash info here */
254e014b9acSsklower {
255e014b9acSsklower 	u_long			buf[sizeof(struct sockaddr_iso)+1/4];
256e014b9acSsklower 	register int	bufsize;
257e014b9acSsklower 
258e014b9acSsklower 
259e014b9acSsklower 	bzero(buf, sizeof(buf));
260e014b9acSsklower 
261e014b9acSsklower 	bufsize = iso_netof(&siso->siso_addr, buf);
262e014b9acSsklower 	hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize);
263e014b9acSsklower 
264e014b9acSsklower 	IFDEBUG(D_ROUTE)
265e014b9acSsklower 		printf("iso_hash: iso_netof: bufsize = %d\n", bufsize);
266e014b9acSsklower 	ENDDEBUG
267e014b9acSsklower 
268e014b9acSsklower 	hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr,
269e014b9acSsklower 		siso->siso_addr.isoa_len);
270e014b9acSsklower 
271e014b9acSsklower 	IFDEBUG(D_ROUTE)
272e014b9acSsklower 		printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n",
273e014b9acSsklower 			clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash,
274e014b9acSsklower 			hp->afh_hosthash);
275e014b9acSsklower 	ENDDEBUG
276e014b9acSsklower }
277e014b9acSsklower /*
278e014b9acSsklower  * FUNCTION:		iso_netof
279e014b9acSsklower  *
280e014b9acSsklower  * PURPOSE:			Extract the network portion of the iso address.
281e014b9acSsklower  *					The network portion of the iso address varies depending
282e014b9acSsklower  *					on the type of address. The network portion of the
283e014b9acSsklower  *					address will include the IDP. The network portion is:
284e014b9acSsklower  *
285e014b9acSsklower  *						TYPE			DESC
286e014b9acSsklower  *					t37					The AFI and x.121 (IDI)
287e014b9acSsklower  *					osinet				The AFI, orgid, snetid
288e014b9acSsklower  *					rfc986				The AFI, vers and network part of
289e014b9acSsklower  *										internet address.
290e014b9acSsklower  *
291e014b9acSsklower  * RETURNS:			number of bytes placed into buf.
292e014b9acSsklower  *
293e014b9acSsklower  * SIDE EFFECTS:
294e014b9acSsklower  *
295e014b9acSsklower  * NOTES:			Buf is assumed to be big enough
296e014b9acSsklower  */
297e014b9acSsklower iso_netof(isoa, buf)
298e014b9acSsklower struct iso_addr	*isoa;		/* address */
299e014b9acSsklower caddr_t			buf;		/* RESULT: network portion of address here */
300e014b9acSsklower {
301e014b9acSsklower 	u_int		len = 1;	/* length of afi */
302e014b9acSsklower 
303e014b9acSsklower 	switch (isoa->isoa_afi) {
304e014b9acSsklower 		case AFI_37:
305e014b9acSsklower 			/*
306e014b9acSsklower 			 * Due to classic x.25 tunnel vision, there is no
307e014b9acSsklower 			 * net portion of an x.121 address.  For our purposes
308e014b9acSsklower 			 * the AFI will do, so that all x.25 -type addresses
309e014b9acSsklower 			 * map to the single x.25 SNPA. (Cannot have more than
310e014b9acSsklower 			 * one, obviously).
311e014b9acSsklower 			 */
312e014b9acSsklower 
313e014b9acSsklower 			break;
314e014b9acSsklower 
315e014b9acSsklower /* 		case AFI_OSINET:*/
316e014b9acSsklower 		case AFI_RFC986: {
317e014b9acSsklower 			u_short	idi;	/* value of idi */
318e014b9acSsklower 
319e014b9acSsklower 			/* osinet and rfc986 have idi in the same place */
320e014b9acSsklower 			CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi);
321e014b9acSsklower 
322e014b9acSsklower 			if (idi == IDI_OSINET)
323e014b9acSsklower /*
324e014b9acSsklower  *	Network portion of OSINET address can only be the IDI. Clearly,
325e014b9acSsklower  *	with one x25 interface, one could get to several orgids, and
326e014b9acSsklower  *	several snetids.
327e014b9acSsklower 				len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN +
328e014b9acSsklower 						OVLOSINET_SNETID_LEN);
329e014b9acSsklower  */
330e014b9acSsklower 				len += ADDROSINET_IDI_LEN;
331e014b9acSsklower 			else if (idi == IDI_RFC986) {
332e014b9acSsklower 				u_long				inetaddr;
333e014b9acSsklower 				struct ovl_rfc986	*o986 = (struct ovl_rfc986 *)isoa;
334e014b9acSsklower 
335e014b9acSsklower 				/* bump len to include idi and version (1 byte) */
336e014b9acSsklower 				len += ADDRRFC986_IDI_LEN + 1;
337e014b9acSsklower 
338e014b9acSsklower 				/* get inet addr long aligned */
339e014b9acSsklower 				bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr));
340e014b9acSsklower 				inetaddr = ntohl(inetaddr);	/* convert to host byte order */
341e014b9acSsklower 
342e014b9acSsklower 				IFDEBUG(D_ROUTE)
343e014b9acSsklower 					printf("iso_netof: isoa ");
344e014b9acSsklower 					dump_buf(isoa, sizeof(*isoa));
345e014b9acSsklower 					printf("iso_netof: inetaddr 0x%x ", inetaddr);
346e014b9acSsklower 				ENDDEBUG
347e014b9acSsklower 
348e014b9acSsklower 				/* bump len by size of network portion of inet address */
349e014b9acSsklower 				if (IN_CLASSA(inetaddr)) {
350e014b9acSsklower 					len += 4-IN_CLASSA_NSHIFT/8;
351e014b9acSsklower 					IFDEBUG(D_ROUTE)
352e014b9acSsklower 						printf("iso_netof: class A net len is now %d\n", len);
353e014b9acSsklower 					ENDDEBUG
354e014b9acSsklower 				} else if (IN_CLASSB(inetaddr)) {
355e014b9acSsklower 					len += 4-IN_CLASSB_NSHIFT/8;
356e014b9acSsklower 					IFDEBUG(D_ROUTE)
357e014b9acSsklower 						printf("iso_netof: class B net len is now %d\n", len);
358e014b9acSsklower 					ENDDEBUG
359e014b9acSsklower 				} else {
360e014b9acSsklower 					len += 4-IN_CLASSC_NSHIFT/8;
361e014b9acSsklower 					IFDEBUG(D_ROUTE)
362e014b9acSsklower 						printf("iso_netof: class C net len is now %d\n", len);
363e014b9acSsklower 					ENDDEBUG
364e014b9acSsklower 				}
365e014b9acSsklower 			} else
366e014b9acSsklower 				len = 0;
367e014b9acSsklower 		} break;
368e014b9acSsklower 
369e014b9acSsklower 		default:
370e014b9acSsklower 			len = 0;
371e014b9acSsklower 	}
372e014b9acSsklower 
373e014b9acSsklower 	bcopy((caddr_t)isoa, buf, len);
374e014b9acSsklower 	IFDEBUG(D_ROUTE)
37553524399Ssklower 		printf("iso_netof: isoa ");
376e014b9acSsklower 		dump_buf(isoa, len);
37753524399Ssklower 		printf("iso_netof: net ");
378e014b9acSsklower 		dump_buf(buf, len);
379e014b9acSsklower 	ENDDEBUG
380e014b9acSsklower 	return len;
381e014b9acSsklower }
3825cbc22e2Sbostic #endif /* notdef */
383e014b9acSsklower /*
3840b7547b2Ssklower  * Generic iso control operations (ioctl's).
3850b7547b2Ssklower  * Ifp is 0 if not an interface-specific ioctl.
386e014b9acSsklower  */
3870b7547b2Ssklower /* ARGSUSED */
388e014b9acSsklower iso_control(so, cmd, data, ifp)
3890b7547b2Ssklower 	struct socket *so;
390*7fa9e8f7Scgd 	u_long cmd;
3910b7547b2Ssklower 	caddr_t data;
3920b7547b2Ssklower 	register struct ifnet *ifp;
393e014b9acSsklower {
3940b7547b2Ssklower 	register struct iso_ifreq *ifr = (struct iso_ifreq *)data;
395e014b9acSsklower 	register struct iso_ifaddr *ia = 0;
3960b7547b2Ssklower 	register struct ifaddr *ifa;
3970b7547b2Ssklower 	struct iso_ifaddr *oia;
3980b7547b2Ssklower 	struct iso_aliasreq *ifra = (struct iso_aliasreq *)data;
3990b7547b2Ssklower 	int error, hostIsNew, maskIsNew;
400e014b9acSsklower 
4010b7547b2Ssklower 	/*
4020b7547b2Ssklower 	 * Find address for this interface, if it exists.
4030b7547b2Ssklower 	 */
4040b7547b2Ssklower 	if (ifp)
4050b7547b2Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
4060b7547b2Ssklower 			if (ia->ia_ifp == ifp)
4070b7547b2Ssklower 				break;
408e014b9acSsklower 
409e014b9acSsklower 	switch (cmd) {
4100b7547b2Ssklower 
4110b7547b2Ssklower 	case SIOCAIFADDR_ISO:
4120b7547b2Ssklower 	case SIOCDIFADDR_ISO:
4130b7547b2Ssklower 		if (ifra->ifra_addr.siso_family == AF_ISO)
4140b7547b2Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
4150b7547b2Ssklower 			if (ia->ia_ifp == ifp  &&
4160b7547b2Ssklower 			    SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
4170b7547b2Ssklower 				break;
4180b7547b2Ssklower 		}
41934dd6a78Ssklower 		if ((so->so_state & SS_PRIV) == 0)
42034dd6a78Ssklower 			return (EPERM);
421e014b9acSsklower 		if (ifp == 0)
4220b7547b2Ssklower 			panic("iso_control");
4230b7547b2Ssklower 		if (ia == (struct iso_ifaddr *)0) {
4240b7547b2Ssklower 			struct iso_ifaddr *nia;
4250b7547b2Ssklower 			if (cmd == SIOCDIFADDR_ISO)
426e014b9acSsklower 				return (EADDRNOTAVAIL);
42768756140Ssklower #ifdef TUBA
42868756140Ssklower 			/* XXXXXX can't be done in the proto init routines */
42968756140Ssklower 			if (tuba_tree == 0)
43068756140Ssklower 				tuba_table_init();
43168756140Ssklower #endif
4320b7547b2Ssklower 			MALLOC(nia, struct iso_ifaddr *, sizeof(*nia),
4330b7547b2Ssklower 				       M_IFADDR, M_WAITOK);
4340b7547b2Ssklower 			if (nia == (struct iso_ifaddr *)0)
435e014b9acSsklower 				return (ENOBUFS);
4360b7547b2Ssklower 			bzero((caddr_t)nia, sizeof(*nia));
437e014b9acSsklower 			if (ia = iso_ifaddr) {
438e014b9acSsklower 				for ( ; ia->ia_next; ia = ia->ia_next)
439e014b9acSsklower 					;
4400b7547b2Ssklower 				ia->ia_next = nia;
441e014b9acSsklower 			} else
4420b7547b2Ssklower 				iso_ifaddr = nia;
4430b7547b2Ssklower 			ia = nia;
444e014b9acSsklower 			if (ifa = ifp->if_addrlist) {
445e014b9acSsklower 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
446e014b9acSsklower 					;
447e014b9acSsklower 				ifa->ifa_next = (struct ifaddr *) ia;
448e014b9acSsklower 			} else
449e014b9acSsklower 				ifp->if_addrlist = (struct ifaddr *) ia;
4500b7547b2Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
4510b7547b2Ssklower 			ia->ia_ifa.ifa_dstaddr
4520b7547b2Ssklower 					= (struct sockaddr *)&ia->ia_dstaddr;
4530b7547b2Ssklower 			ia->ia_ifa.ifa_netmask
4540b7547b2Ssklower 					= (struct sockaddr *)&ia->ia_sockmask;
455e014b9acSsklower 			ia->ia_ifp = ifp;
456e014b9acSsklower 			if (ifp != &loif)
457e014b9acSsklower 				iso_interfaces++;
4580b7547b2Ssklower 		}
4590b7547b2Ssklower 		break;
460e014b9acSsklower 
4610b7547b2Ssklower #define cmdbyte(x)	(((x) >> 8) & 0xff)
4620b7547b2Ssklower 	default:
4630b7547b2Ssklower 		if (cmdbyte(cmd) == 'a')
46434dd6a78Ssklower 			return (snpac_ioctl(so, cmd, data));
4650b7547b2Ssklower 		if (ia == (struct iso_ifaddr *)0)
466e014b9acSsklower 			return (EADDRNOTAVAIL);
4670b7547b2Ssklower 		break;
4680b7547b2Ssklower 	}
4690b7547b2Ssklower 	switch (cmd) {
470e014b9acSsklower 
4710b7547b2Ssklower 	case SIOCGIFADDR_ISO:
4720b7547b2Ssklower 		ifr->ifr_Addr = ia->ia_addr;
4730b7547b2Ssklower 		break;
474e014b9acSsklower 
4750b7547b2Ssklower 	case SIOCGIFDSTADDR_ISO:
4760b7547b2Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
4770b7547b2Ssklower 			return (EINVAL);
4780b7547b2Ssklower 		ifr->ifr_Addr = ia->ia_dstaddr;
4790b7547b2Ssklower 		break;
480e014b9acSsklower 
4810b7547b2Ssklower 	case SIOCGIFNETMASK_ISO:
4820b7547b2Ssklower 		ifr->ifr_Addr = ia->ia_sockmask;
4830b7547b2Ssklower 		break;
4840b7547b2Ssklower 
4850b7547b2Ssklower 	case SIOCAIFADDR_ISO:
48644e1ed6cSsklower 		maskIsNew = 0; hostIsNew = 1; error = 0;
4870b7547b2Ssklower 		if (ia->ia_addr.siso_family == AF_ISO) {
4880b7547b2Ssklower 			if (ifra->ifra_addr.siso_len == 0) {
4890b7547b2Ssklower 				ifra->ifra_addr = ia->ia_addr;
4900b7547b2Ssklower 				hostIsNew = 0;
4910b7547b2Ssklower 			} else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
4920b7547b2Ssklower 				hostIsNew = 0;
4930b7547b2Ssklower 		}
4940b7547b2Ssklower 		if (ifra->ifra_mask.siso_len) {
4950b7547b2Ssklower 			iso_ifscrub(ifp, ia);
4960b7547b2Ssklower 			ia->ia_sockmask = ifra->ifra_mask;
4970b7547b2Ssklower 			maskIsNew = 1;
4980b7547b2Ssklower 		}
4990b7547b2Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
5000b7547b2Ssklower 		    (ifra->ifra_dstaddr.siso_family == AF_ISO)) {
5010b7547b2Ssklower 			iso_ifscrub(ifp, ia);
5020b7547b2Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
5030b7547b2Ssklower 			maskIsNew  = 1; /* We lie; but the effect's the same */
5040b7547b2Ssklower 		}
5050b7547b2Ssklower 		if (ifra->ifra_addr.siso_family == AF_ISO &&
5060b7547b2Ssklower 					    (hostIsNew || maskIsNew)) {
5070b7547b2Ssklower 			error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0);
5080b7547b2Ssklower 		}
5090b7547b2Ssklower 		if (ifra->ifra_snpaoffset)
5100b7547b2Ssklower 			ia->ia_snpaoffset = ifra->ifra_snpaoffset;
5110b7547b2Ssklower 		return (error);
5120b7547b2Ssklower 
5130b7547b2Ssklower 	case SIOCDIFADDR_ISO:
5140b7547b2Ssklower 		iso_ifscrub(ifp, ia);
5150b7547b2Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
5160b7547b2Ssklower 			ifp->if_addrlist = ifa->ifa_next;
5170b7547b2Ssklower 		else {
5180b7547b2Ssklower 			while (ifa->ifa_next &&
5190b7547b2Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
5200b7547b2Ssklower 				    ifa = ifa->ifa_next;
5210b7547b2Ssklower 			if (ifa->ifa_next)
5220b7547b2Ssklower 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
5230b7547b2Ssklower 			else
5240b7547b2Ssklower 				printf("Couldn't unlink isoifaddr from ifp\n");
5250b7547b2Ssklower 		}
5260b7547b2Ssklower 		oia = ia;
5270b7547b2Ssklower 		if (oia == (ia = iso_ifaddr)) {
5280b7547b2Ssklower 			iso_ifaddr = ia->ia_next;
5290b7547b2Ssklower 		} else {
5300b7547b2Ssklower 			while (ia->ia_next && (ia->ia_next != oia)) {
5310b7547b2Ssklower 				ia = ia->ia_next;
5320b7547b2Ssklower 			}
5330b7547b2Ssklower 			if (ia->ia_next)
5340b7547b2Ssklower 			    ia->ia_next = oia->ia_next;
5350b7547b2Ssklower 			else
5360b7547b2Ssklower 				printf("Didn't unlink isoifadr from list\n");
5370b7547b2Ssklower 		}
53841634bf6Ssklower 		IFAFREE((&oia->ia_ifa));
5390b7547b2Ssklower 		break;
540e014b9acSsklower 
541e014b9acSsklower 	default:
542e014b9acSsklower 		if (ifp == 0 || ifp->if_ioctl == 0)
543e014b9acSsklower 			return (EOPNOTSUPP);
544e014b9acSsklower 		return ((*ifp->if_ioctl)(ifp, cmd, data));
545e014b9acSsklower 	}
5460b7547b2Ssklower 	return (0);
547e014b9acSsklower }
548e014b9acSsklower 
5490b7547b2Ssklower /*
5500b7547b2Ssklower  * Delete any existing route for an interface.
5510b7547b2Ssklower  */
iso_ifscrub(ifp,ia)5520b7547b2Ssklower iso_ifscrub(ifp, ia)
5530b7547b2Ssklower 	register struct ifnet *ifp;
5540b7547b2Ssklower 	register struct iso_ifaddr *ia;
5550b7547b2Ssklower {
5564f8f8de6Ssklower 	int nsellength = ia->ia_addr.siso_tlen;
5570b7547b2Ssklower 	if ((ia->ia_flags & IFA_ROUTE) == 0)
5580b7547b2Ssklower 		return;
5594f8f8de6Ssklower 	ia->ia_addr.siso_tlen = 0;
5600b7547b2Ssklower 	if (ifp->if_flags & IFF_LOOPBACK)
5610b7547b2Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
5620b7547b2Ssklower 	else if (ifp->if_flags & IFF_POINTOPOINT)
5630b7547b2Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
5640b7547b2Ssklower 	else {
5650b7547b2Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
5660b7547b2Ssklower 	}
5674f8f8de6Ssklower 	ia->ia_addr.siso_tlen = nsellength;
5680b7547b2Ssklower 	ia->ia_flags &= ~IFA_ROUTE;
5690b7547b2Ssklower }
5700b7547b2Ssklower 
5710b7547b2Ssklower /*
5720b7547b2Ssklower  * Initialize an interface's internet address
5730b7547b2Ssklower  * and routing table entry.
5740b7547b2Ssklower  */
iso_ifinit(ifp,ia,siso,scrub)5750b7547b2Ssklower iso_ifinit(ifp, ia, siso, scrub)
5760b7547b2Ssklower 	register struct ifnet *ifp;
5770b7547b2Ssklower 	register struct iso_ifaddr *ia;
5780b7547b2Ssklower 	struct sockaddr_iso *siso;
5790b7547b2Ssklower {
5800b7547b2Ssklower 	struct sockaddr_iso oldaddr;
5814f8f8de6Ssklower 	int s = splimp(), error, nsellength;
5820b7547b2Ssklower 
5830b7547b2Ssklower 	oldaddr = ia->ia_addr;
5840b7547b2Ssklower 	ia->ia_addr = *siso;
5850b7547b2Ssklower 	/*
5860b7547b2Ssklower 	 * Give the interface a chance to initialize
5870b7547b2Ssklower 	 * if this is its first address,
5880b7547b2Ssklower 	 * and to validate the address if necessary.
5890b7547b2Ssklower 	 */
5901dd7e156Ssklower 	if (ifp->if_ioctl &&
5911dd7e156Ssklower 				(error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
5920b7547b2Ssklower 		splx(s);
5930b7547b2Ssklower 		ia->ia_addr = oldaddr;
5940b7547b2Ssklower 		return (error);
5950b7547b2Ssklower 	}
5960b7547b2Ssklower 	if (scrub) {
5970b7547b2Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
5980b7547b2Ssklower 		iso_ifscrub(ifp, ia);
5990b7547b2Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
6000b7547b2Ssklower 	}
6014f8f8de6Ssklower 	/* XXX -- The following is here temporarily out of laziness
6024f8f8de6Ssklower 	   in not changing every ethernet driver's if_ioctl routine */
6034f8f8de6Ssklower 	if (ifp->if_output == ether_output) {
6044f8f8de6Ssklower 		ia->ia_ifa.ifa_rtrequest = llc_rtrequest;
6054f8f8de6Ssklower 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
6064f8f8de6Ssklower 	}
6070b7547b2Ssklower 	/*
6080b7547b2Ssklower 	 * Add route for the network.
6090b7547b2Ssklower 	 */
6104f8f8de6Ssklower 	nsellength = ia->ia_addr.siso_tlen;
6114f8f8de6Ssklower 	ia->ia_addr.siso_tlen = 0;
6120b7547b2Ssklower 	if (ifp->if_flags & IFF_LOOPBACK) {
6130b7547b2Ssklower 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
61450feba3cSsklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
6150b7547b2Ssklower 	} else if (ifp->if_flags & IFF_POINTOPOINT &&
6160b7547b2Ssklower 		 ia->ia_dstaddr.siso_family == AF_ISO)
61750feba3cSsklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
6180b7547b2Ssklower 	else {
61950feba3cSsklower 		rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
62050feba3cSsklower 			ia->ia_ifa.ifa_netmask);
621f2b38841Ssklower 		ia->ia_dstaddr.siso_nlen =
622f2b38841Ssklower 			min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6));
62350feba3cSsklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
6240b7547b2Ssklower 	}
6254f8f8de6Ssklower 	ia->ia_addr.siso_tlen = nsellength;
6260b7547b2Ssklower 	ia->ia_flags |= IFA_ROUTE;
6270b7547b2Ssklower 	splx(s);
62850feba3cSsklower 	return (error);
6290b7547b2Ssklower }
6300b7547b2Ssklower #ifdef notdef
6310b7547b2Ssklower 
632e014b9acSsklower struct ifaddr *
iso_ifwithidi(addr)633e014b9acSsklower iso_ifwithidi(addr)
634e014b9acSsklower 	register struct sockaddr *addr;
635e014b9acSsklower {
636e014b9acSsklower 	register struct ifnet *ifp;
637e014b9acSsklower 	register struct ifaddr *ifa;
638e014b9acSsklower 	register u_int af = addr->sa_family;
639e014b9acSsklower 
640e014b9acSsklower 	if (af != AF_ISO)
641e014b9acSsklower 		return (0);
642e014b9acSsklower 	IFDEBUG(D_ROUTE)
643e014b9acSsklower 		printf(">>> iso_ifwithidi addr\n");
644e014b9acSsklower 		dump_isoaddr( (struct sockaddr_iso *)(addr));
645e014b9acSsklower 		printf("\n");
646e014b9acSsklower 	ENDDEBUG
647e014b9acSsklower 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
648e014b9acSsklower 		IFDEBUG(D_ROUTE)
649e014b9acSsklower 			printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
650e014b9acSsklower 		ENDDEBUG
651e014b9acSsklower 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
652e014b9acSsklower 			IFDEBUG(D_ROUTE)
653e014b9acSsklower 				printf("iso_ifwithidi address ");
6540b7547b2Ssklower 				dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr));
655e014b9acSsklower 			ENDDEBUG
6560b7547b2Ssklower 			if (ifa->ifa_addr->sa_family != addr->sa_family)
657e014b9acSsklower 				continue;
658e014b9acSsklower 
659e014b9acSsklower #define	IFA_SIS(ifa)\
6600b7547b2Ssklower 	((struct sockaddr_iso *)((ifa)->ifa_addr))
661e014b9acSsklower 
662e014b9acSsklower 			IFDEBUG(D_ROUTE)
663e014b9acSsklower 				printf(" af same, args to iso_eqtype:\n");
664e014b9acSsklower 				printf("0x%x ", IFA_SIS(ifa)->siso_addr);
665e014b9acSsklower 				printf(" 0x%x\n",
666e014b9acSsklower 				&(((struct sockaddr_iso *)addr)->siso_addr));
667e014b9acSsklower 			ENDDEBUG
668e014b9acSsklower 
669e014b9acSsklower 			if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr),
670e014b9acSsklower 				&(((struct sockaddr_iso *)addr)->siso_addr))) {
671e014b9acSsklower 				IFDEBUG(D_ROUTE)
672e014b9acSsklower 					printf("ifa_ifwithidi: ifa found\n");
673e014b9acSsklower 				ENDDEBUG
674e014b9acSsklower 				return (ifa);
675e014b9acSsklower 			}
676e014b9acSsklower 			IFDEBUG(D_ROUTE)
677e014b9acSsklower 				printf(" iso_eqtype failed\n");
678e014b9acSsklower 			ENDDEBUG
679e014b9acSsklower 		}
680e014b9acSsklower 	}
681e014b9acSsklower 	return ((struct ifaddr *)0);
682e014b9acSsklower }
683e014b9acSsklower 
6845cbc22e2Sbostic #endif /* notdef */
685e014b9acSsklower /*
686e014b9acSsklower  * FUNCTION:		iso_ck_addr
687e014b9acSsklower  *
688e014b9acSsklower  * PURPOSE:			return true if the iso_addr passed is
689e014b9acSsklower  *					within the legal size limit for an iso address.
690e014b9acSsklower  *
691e014b9acSsklower  * RETURNS:			true or false
692e014b9acSsklower  *
693e014b9acSsklower  * SIDE EFFECTS:
694e014b9acSsklower  *
695e014b9acSsklower  */
696e014b9acSsklower iso_ck_addr(isoa)
697e014b9acSsklower struct iso_addr	*isoa;	/* address to check */
698e014b9acSsklower {
699e014b9acSsklower 	return (isoa->isoa_len <= 20);
700e014b9acSsklower 
701e014b9acSsklower }
702e014b9acSsklower 
7030b7547b2Ssklower #ifdef notdef
704e014b9acSsklower /*
705e014b9acSsklower  * FUNCTION:		iso_eqtype
706e014b9acSsklower  *
707e014b9acSsklower  * PURPOSE:			Determine if two iso addresses are of the same type.
708e014b9acSsklower  *  This is flaky.  Really we should consider all type 47 addrs to be the
709e014b9acSsklower  *  same - but there do exist different structures for 47 addrs.
710e014b9acSsklower  *  Gosip adds a 3rd.
711e014b9acSsklower  *
712e014b9acSsklower  * RETURNS:			true if the addresses are the same type
713e014b9acSsklower  *
714e014b9acSsklower  * SIDE EFFECTS:
715e014b9acSsklower  *
716e014b9acSsklower  * NOTES:			By type, I mean rfc986, t37, or osinet
717e014b9acSsklower  *
718e014b9acSsklower  *					This will first compare afis. If they match, then
719e014b9acSsklower  *					if the addr is not t37, the idis must be compared.
720e014b9acSsklower  */
721e014b9acSsklower iso_eqtype(isoaa, isoab)
722e014b9acSsklower struct iso_addr	*isoaa;		/* first addr to check */
723e014b9acSsklower struct iso_addr	*isoab;		/* other addr to check */
724e014b9acSsklower {
725e014b9acSsklower 	if (isoaa->isoa_afi == isoab->isoa_afi) {
726e014b9acSsklower 		if (isoaa->isoa_afi == AFI_37)
727e014b9acSsklower 			return(1);
728e014b9acSsklower 		else
729e014b9acSsklower 			return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
730e014b9acSsklower 	}
731e014b9acSsklower 	return(0);
732e014b9acSsklower }
7335cbc22e2Sbostic #endif /* notdef */
734e014b9acSsklower /*
7350b7547b2Ssklower  * FUNCTION:		iso_localifa()
736e014b9acSsklower  *
7370b7547b2Ssklower  * PURPOSE:			Find an interface addresss having a given destination
7380b7547b2Ssklower  *					or at least matching the net.
739e014b9acSsklower  *
740e014b9acSsklower  * RETURNS:			ptr to an interface address
741e014b9acSsklower  *
742e014b9acSsklower  * SIDE EFFECTS:
743e014b9acSsklower  *
744e014b9acSsklower  * NOTES:
745e014b9acSsklower  */
746e014b9acSsklower struct iso_ifaddr *
iso_localifa(siso)7470b7547b2Ssklower iso_localifa(siso)
7480b7547b2Ssklower 	register struct sockaddr_iso *siso;
749e014b9acSsklower {
750e014b9acSsklower 	register struct iso_ifaddr *ia;
7510b7547b2Ssklower 	register char *cp1, *cp2, *cp3;
7520b7547b2Ssklower 	register struct ifnet *ifp;
7530b7547b2Ssklower 	struct iso_ifaddr *ia_maybe = 0;
7540b7547b2Ssklower 	/*
7550b7547b2Ssklower 	 * We make one pass looking for both net matches and an exact
7560b7547b2Ssklower 	 * dst addr.
7570b7547b2Ssklower 	 */
7580b7547b2Ssklower 	for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
7590b7547b2Ssklower 		if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
7600b7547b2Ssklower 			continue;
7610b7547b2Ssklower 		if (ifp->if_flags & IFF_POINTOPOINT) {
7620b7547b2Ssklower 			if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
7630b7547b2Ssklower 				SAME_ISOADDR(&ia->ia_dstaddr, siso))
764e014b9acSsklower 				return (ia);
7650b7547b2Ssklower 			else
7660b7547b2Ssklower 				if (SAME_ISOADDR(&ia->ia_addr, siso))
7670b7547b2Ssklower 					ia_maybe = ia;
7680b7547b2Ssklower 			continue;
7690b7547b2Ssklower 		}
7700b7547b2Ssklower 		if (ia->ia_sockmask.siso_len) {
7710b7547b2Ssklower 			char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask;
7720b7547b2Ssklower 			cp1 = ia->ia_sockmask.siso_data;
7730b7547b2Ssklower 			cp2 = siso->siso_data;
7740b7547b2Ssklower 			cp3 = ia->ia_addr.siso_data;
775d65650a8Ssklower 			while (cp1 < cplim)
7760b7547b2Ssklower 				if (*cp1++ & (*cp2++ ^ *cp3++))
7770b7547b2Ssklower 					goto next;
7780b7547b2Ssklower 			ia_maybe = ia;
7790b7547b2Ssklower 		}
7800b7547b2Ssklower 		if (SAME_ISOADDR(&ia->ia_addr, siso))
7810b7547b2Ssklower 			return ia;
7820b7547b2Ssklower 	next:;
7830b7547b2Ssklower 	}
7840b7547b2Ssklower 	return ia_maybe;
785e014b9acSsklower }
786e014b9acSsklower 
7877e563708Ssklower #ifdef	TPCONS
788e1ca26eaSbostic #include <netiso/cons.h>
7895cbc22e2Sbostic #endif	/* TPCONS */
790e014b9acSsklower /*
791e014b9acSsklower  * FUNCTION:		iso_nlctloutput
792e014b9acSsklower  *
793e014b9acSsklower  * PURPOSE:			Set options at the network level
794e014b9acSsklower  *
795e014b9acSsklower  * RETURNS:			E*
796e014b9acSsklower  *
797e014b9acSsklower  * SIDE EFFECTS:
798e014b9acSsklower  *
799e014b9acSsklower  * NOTES:			This could embody some of the functions of
800e014b9acSsklower  *					rclnp_ctloutput and cons_ctloutput.
801e014b9acSsklower  */
iso_nlctloutput(cmd,optname,pcb,m)802e014b9acSsklower iso_nlctloutput(cmd, optname, pcb, m)
803e014b9acSsklower int			cmd;		/* command:set or get */
804e014b9acSsklower int			optname;	/* option of interest */
805e014b9acSsklower caddr_t		pcb;		/* nl pcb */
806e014b9acSsklower struct mbuf	*m;			/* data for set, buffer for get */
807e014b9acSsklower {
808e014b9acSsklower 	struct isopcb	*isop = (struct isopcb *)pcb;
809e014b9acSsklower 	int				error = 0;	/* return value */
810e014b9acSsklower 	caddr_t			data;		/* data for option */
811e014b9acSsklower 	int				data_len;	/* data's length */
812e014b9acSsklower 
813e014b9acSsklower 	IFDEBUG(D_ISO)
814e014b9acSsklower 		printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n",
815e014b9acSsklower 			cmd, optname, pcb, m);
816e014b9acSsklower 	ENDDEBUG
817e014b9acSsklower 
818e014b9acSsklower 	if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
819e014b9acSsklower 		return(EOPNOTSUPP);
820e014b9acSsklower 
821e014b9acSsklower 	data = mtod(m, caddr_t);
822e014b9acSsklower 	data_len = (m)->m_len;
823e014b9acSsklower 
824e014b9acSsklower 	IFDEBUG(D_ISO)
825e014b9acSsklower 		printf("iso_nlctloutput: data is:\n");
826e014b9acSsklower 		dump_buf(data, data_len);
827e014b9acSsklower 	ENDDEBUG
828e014b9acSsklower 
829e014b9acSsklower 	switch (optname) {
830e014b9acSsklower 
8317e563708Ssklower #ifdef	TPCONS
832e014b9acSsklower 		case CONSOPT_X25CRUD:
833e014b9acSsklower 			if (cmd == PRCO_GETOPT) {
834e014b9acSsklower 				error = EOPNOTSUPP;
835e014b9acSsklower 				break;
836e014b9acSsklower 			}
837e014b9acSsklower 
838e014b9acSsklower 			if (data_len > MAXX25CRUDLEN) {
839e014b9acSsklower 				error = EINVAL;
840e014b9acSsklower 				break;
841e014b9acSsklower 			}
842e014b9acSsklower 
843e014b9acSsklower 			IFDEBUG(D_ISO)
844e014b9acSsklower 				printf("iso_nlctloutput: setting x25 crud\n");
845e014b9acSsklower 			ENDDEBUG
846e014b9acSsklower 
8470b7547b2Ssklower 			bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len);
848e014b9acSsklower 			isop->isop_x25crud_len = data_len;
849e014b9acSsklower 			break;
8505cbc22e2Sbostic #endif	/* TPCONS */
851e014b9acSsklower 
852e014b9acSsklower 		default:
853e014b9acSsklower 			error = EOPNOTSUPP;
854e014b9acSsklower 	}
855eaae3387Ssklower 	if (cmd == PRCO_SETOPT)
856eaae3387Ssklower 		m_freem(m);
857e014b9acSsklower 	return error;
858e014b9acSsklower }
8595cbc22e2Sbostic #endif /* ISO */
860e014b9acSsklower 
861e014b9acSsklower #ifdef ARGO_DEBUG
862e014b9acSsklower 
863e014b9acSsklower /*
864e014b9acSsklower  * FUNCTION:		dump_isoaddr
865e014b9acSsklower  *
866e014b9acSsklower  * PURPOSE:			debugging
867e014b9acSsklower  *
868e014b9acSsklower  * RETURNS:			nada
869e014b9acSsklower  *
870e014b9acSsklower  */
871e014b9acSsklower dump_isoaddr(s)
872e014b9acSsklower 	struct sockaddr_iso *s;
873e014b9acSsklower {
8740b7547b2Ssklower 	char *clnp_saddr_isop();
875e014b9acSsklower 	register int i;
876e014b9acSsklower 
877e014b9acSsklower 	if( s->siso_family == AF_ISO) {
8780b7547b2Ssklower 		printf("ISO address: suffixlen %d, %s\n",
8790b3e9d7fSsklower 			s->siso_tlen, clnp_saddr_isop(s));
880e014b9acSsklower 	} else if( s->siso_family == AF_INET) {
881e014b9acSsklower 		/* hack */
882e014b9acSsklower 		struct sockaddr_in *sin = (struct sockaddr_in *)s;
883e014b9acSsklower 
884e014b9acSsklower 		printf("%d.%d.%d.%d: %d",
885e014b9acSsklower 			(sin->sin_addr.s_addr>>24)&0xff,
886e014b9acSsklower 			(sin->sin_addr.s_addr>>16)&0xff,
887e014b9acSsklower 			(sin->sin_addr.s_addr>>8)&0xff,
888e014b9acSsklower 			(sin->sin_addr.s_addr)&0xff,
889e014b9acSsklower 			sin->sin_port);
890e014b9acSsklower 	}
891e014b9acSsklower }
892e014b9acSsklower 
8935cbc22e2Sbostic #endif /* ARGO_DEBUG */
894