xref: /csrg-svn/sys/netiso/iso.c (revision 54823)
149268Sbostic /*-
249268Sbostic  * Copyright (c) 1991 The Regents of the University of California.
349268Sbostic  * All rights reserved.
449268Sbostic  *
549268Sbostic  * %sccs.include.redist.c%
649268Sbostic  *
7*54823Ssklower  *	@(#)iso.c	7.18 (Berkeley) 07/09/92
849268Sbostic  */
949268Sbostic 
1036384Ssklower /***********************************************************
1136384Ssklower 		Copyright IBM Corporation 1987
1236384Ssklower 
1336384Ssklower                       All Rights Reserved
1436384Ssklower 
1536384Ssklower Permission to use, copy, modify, and distribute this software and its
1636384Ssklower documentation for any purpose and without fee is hereby granted,
1736384Ssklower provided that the above copyright notice appear in all copies and that
1836384Ssklower both that copyright notice and this permission notice appear in
1936384Ssklower supporting documentation, and that the name of IBM not be
2036384Ssklower used in advertising or publicity pertaining to distribution of the
2136384Ssklower software without specific, written prior permission.
2236384Ssklower 
2336384Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2436384Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2536384Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2636384Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2736384Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2836384Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2936384Ssklower SOFTWARE.
3036384Ssklower 
3136384Ssklower ******************************************************************/
3236384Ssklower 
3336384Ssklower /*
3436384Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
3536384Ssklower  */
3636384Ssklower /*
3736384Ssklower  * $Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $
3836384Ssklower  * $Source: /usr/argo/sys/netiso/RCS/iso.c,v $
3936384Ssklower  *
4036384Ssklower  * iso.c: miscellaneous routines to support the iso address family
4136384Ssklower  */
4236384Ssklower 
4337469Ssklower #include "types.h"
4437469Ssklower #include "param.h"
4537469Ssklower #include "ioctl.h"
4637469Ssklower #include "mbuf.h"
4737469Ssklower #include "domain.h"
4837469Ssklower #include "protosw.h"
4937469Ssklower #include "socket.h"
5037469Ssklower #include "socketvar.h"
5137469Ssklower #include "errno.h"
5236384Ssklower 
5336384Ssklower #include "../net/if.h"
5436384Ssklower #include "../net/route.h"
5536384Ssklower #include "../net/af.h"
5636384Ssklower 
5737469Ssklower #include "iso.h"
5837469Ssklower #include "iso_var.h"
5937469Ssklower #include "iso_snpac.h"
6037469Ssklower #include "iso_pcb.h"
6137469Ssklower #include "clnp.h"
6237469Ssklower #include "argo_debug.h"
6336384Ssklower 
6436384Ssklower #ifdef ISO
6536384Ssklower 
6636384Ssklower int	iso_interfaces = 0;		/* number of external interfaces */
6736384Ssklower extern	struct ifnet loif;	/* loopback interface */
68*54823Ssklower int	ether_output();
69*54823Ssklower void	llc_rtrequest();
7036384Ssklower 
7136384Ssklower /*
7236384Ssklower  * FUNCTION:		iso_addrmatch1
7336384Ssklower  *
7436384Ssklower  * PURPOSE:			decide if the two iso_addrs passed are equal
7536384Ssklower  *
7636384Ssklower  * RETURNS:			true if the addrs match, false if they do not
7736384Ssklower  *
7836384Ssklower  * SIDE EFFECTS:
7936384Ssklower  *
8036384Ssklower  * NOTES:
8136384Ssklower  */
8236384Ssklower iso_addrmatch1(isoaa, isoab)
8337469Ssklower register struct iso_addr *isoaa, *isoab;		/* addresses to check */
8436384Ssklower {
8537469Ssklower 	u_int	compare_len;
8636384Ssklower 
8736384Ssklower 	IFDEBUG(D_ROUTE)
8836384Ssklower 		printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len,
8936384Ssklower 			isoab->isoa_len);
9036384Ssklower 		printf("a:\n");
9137469Ssklower 		dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len);
9236384Ssklower 		printf("b:\n");
9337469Ssklower 		dump_buf(isoab->isoa_genaddr, isoab->isoa_len);
9436384Ssklower 	ENDDEBUG
9536384Ssklower 
9636384Ssklower 	if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) {
9736384Ssklower 		IFDEBUG(D_ROUTE)
9836384Ssklower 			printf("iso_addrmatch1: returning false because of lengths\n");
9936384Ssklower 		ENDDEBUG
10036384Ssklower 		return 0;
10136384Ssklower 	}
10236384Ssklower 
10337469Ssklower #ifdef notdef
10436384Ssklower 	/* TODO : generalize this to all afis with masks */
10536384Ssklower 	if(	isoaa->isoa_afi == AFI_37 ) {
10636384Ssklower 		/* must not compare 2 least significant digits, or for
10736384Ssklower 		 * that matter, the DSP
10836384Ssklower 		 */
10936384Ssklower 		compare_len = ADDR37_IDI_LEN - 1;
11036384Ssklower 	}
11137469Ssklower #endif
11236384Ssklower 
11336384Ssklower 	IFDEBUG(D_ROUTE)
11436384Ssklower 		int i;
11536384Ssklower 		char *a, *b;
11636384Ssklower 
11737469Ssklower 		a = isoaa->isoa_genaddr;
11837469Ssklower 		b = isoab->isoa_genaddr;
11936384Ssklower 
12036384Ssklower 		for (i=0; i<compare_len; i++) {
12136384Ssklower 			printf("<%x=%x>", a[i]&0xff, b[i]&0xff);
12236384Ssklower 			if (a[i] != b[i]) {
12336384Ssklower 				printf("\naddrs are not equal at byte %d\n", i);
12436384Ssklower 				return(0);
12536384Ssklower 			}
12636384Ssklower 		}
12736384Ssklower 		printf("\n");
12836384Ssklower 		printf("addrs are equal\n");
12936384Ssklower 		return (1);
13036384Ssklower 	ENDDEBUG
13137469Ssklower 	return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len));
13236384Ssklower }
13336384Ssklower 
13436384Ssklower /*
13536384Ssklower  * FUNCTION:		iso_addrmatch
13636384Ssklower  *
13736384Ssklower  * PURPOSE:			decide if the two sockadrr_isos passed are equal
13836384Ssklower  *
13936384Ssklower  * RETURNS:			true if the addrs match, false if they do not
14036384Ssklower  *
14136384Ssklower  * SIDE EFFECTS:
14236384Ssklower  *
14336384Ssklower  * NOTES:
14436384Ssklower  */
14536384Ssklower iso_addrmatch(sisoa, sisob)
14636384Ssklower struct sockaddr_iso	*sisoa, *sisob;		/* addresses to check */
14736384Ssklower {
14836384Ssklower 	return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr));
14936384Ssklower }
15037469Ssklower #ifdef notdef
15136384Ssklower /*
15236384Ssklower  * FUNCTION:		iso_netmatch
15336384Ssklower  *
15436384Ssklower  * PURPOSE:			similar to iso_addrmatch but takes sockaddr_iso
15536384Ssklower  *					as argument.
15636384Ssklower  *
15736384Ssklower  * RETURNS:			true if same net, false if not
15836384Ssklower  *
15936384Ssklower  * SIDE EFFECTS:
16036384Ssklower  *
16136384Ssklower  * NOTES:
16236384Ssklower  */
16336384Ssklower iso_netmatch(sisoa, sisob)
16436384Ssklower struct sockaddr_iso *sisoa, *sisob;
16536384Ssklower {
16636384Ssklower 	u_char			bufa[sizeof(struct sockaddr_iso)];
16736384Ssklower 	u_char			bufb[sizeof(struct sockaddr_iso)];
16836384Ssklower 	register int	lena, lenb;
16936384Ssklower 
17036384Ssklower 	lena = iso_netof(&sisoa->siso_addr, bufa);
17136384Ssklower 	lenb = iso_netof(&sisob->siso_addr, bufb);
17236384Ssklower 
17336384Ssklower 	IFDEBUG(D_ROUTE)
17436384Ssklower 		printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb);
17536384Ssklower 		printf("a:\n");
17636384Ssklower 		dump_buf(bufa, lena);
17736384Ssklower 		printf("b:\n");
17836384Ssklower 		dump_buf(bufb, lenb);
17936384Ssklower 	ENDDEBUG
18036384Ssklower 
18136384Ssklower 	return ((lena == lenb) && (!bcmp(bufa, bufb, lena)));
18236384Ssklower }
18337469Ssklower #endif notdef
18436384Ssklower 
18536384Ssklower /*
18636384Ssklower  * FUNCTION:		iso_hashchar
18736384Ssklower  *
18836384Ssklower  * PURPOSE:			Hash all character in the buffer specified into
18936384Ssklower  *					a long. Return the long.
19036384Ssklower  *
19136384Ssklower  * RETURNS:			The hash value.
19236384Ssklower  *
19336384Ssklower  * SIDE EFFECTS:
19436384Ssklower  *
19536384Ssklower  * NOTES:			The hash is achieved by exclusive ORing 4 byte
19636384Ssklower  *					quantities.
19736384Ssklower  */
19836384Ssklower u_long
19936384Ssklower iso_hashchar(buf, len)
20036384Ssklower register caddr_t	buf;		/* buffer to pack from */
20136384Ssklower register int		len;		/* length of buffer */
20236384Ssklower {
20336384Ssklower 	register u_long	h = 0;
20436384Ssklower 	register int	i;
20536384Ssklower 
20636384Ssklower 	for (i=0; i<len; i+=4) {
20736384Ssklower 		register u_long	l = 0;
20836384Ssklower 
20936384Ssklower 		if ((len - i) < 4) {
21036384Ssklower 			/* buffer not multiple of 4 */
21136384Ssklower 			switch (len - i) {
21236384Ssklower 				case 3:
21336384Ssklower 					l |= buf[i+2] << 8;
21436384Ssklower 				case 2:
21536384Ssklower 					l |= buf[i+1] << 16;
21636384Ssklower 				case 1:
21736384Ssklower 					l |= buf[i] << 24;
21836384Ssklower 					break;
21936384Ssklower 				default:
22036384Ssklower 					printf("iso_hashchar: unexpected value x%x\n", len - i);
22136384Ssklower 					break;
22236384Ssklower 			}
22336384Ssklower 		} else {
22436384Ssklower 			l |= buf[i] << 24;
22536384Ssklower 			l |= buf[i+1] << 16;
22636384Ssklower 			l |= buf[i+2] << 8;
22736384Ssklower 			l |= buf[i+3];
22836384Ssklower 		}
22936384Ssklower 
23036384Ssklower 		h ^= l;
23136384Ssklower 	}
23236384Ssklower 
23336384Ssklower 	h ^= (u_long) (len % 4);
23436384Ssklower 
23536384Ssklower 	return(h);
23636384Ssklower }
23737469Ssklower #ifdef notdef
23836384Ssklower /*
23936384Ssklower  * FUNCTION:		iso_hash
24036384Ssklower  *
24136384Ssklower  * PURPOSE:			Fill in fields of afhash structure based upon addr passed.
24236384Ssklower  *
24336384Ssklower  * RETURNS:			none
24436384Ssklower  *
24536384Ssklower  * SIDE EFFECTS:
24636384Ssklower  *
24736384Ssklower  * NOTES:
24836384Ssklower  */
24936384Ssklower iso_hash(siso, hp)
25036384Ssklower struct sockaddr_iso	*siso;		/* address to perform hash on */
25136384Ssklower struct afhash		*hp;		/* RETURN: hash info here */
25236384Ssklower {
25336384Ssklower 	u_long			buf[sizeof(struct sockaddr_iso)+1/4];
25436384Ssklower 	register int	bufsize;
25536384Ssklower 
25636384Ssklower 
25736384Ssklower 	bzero(buf, sizeof(buf));
25836384Ssklower 
25936384Ssklower 	bufsize = iso_netof(&siso->siso_addr, buf);
26036384Ssklower 	hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize);
26136384Ssklower 
26236384Ssklower 	IFDEBUG(D_ROUTE)
26336384Ssklower 		printf("iso_hash: iso_netof: bufsize = %d\n", bufsize);
26436384Ssklower 	ENDDEBUG
26536384Ssklower 
26636384Ssklower 	hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr,
26736384Ssklower 		siso->siso_addr.isoa_len);
26836384Ssklower 
26936384Ssklower 	IFDEBUG(D_ROUTE)
27036384Ssklower 		printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n",
27136384Ssklower 			clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash,
27236384Ssklower 			hp->afh_hosthash);
27336384Ssklower 	ENDDEBUG
27436384Ssklower }
27536384Ssklower /*
27636384Ssklower  * FUNCTION:		iso_netof
27736384Ssklower  *
27836384Ssklower  * PURPOSE:			Extract the network portion of the iso address.
27936384Ssklower  *					The network portion of the iso address varies depending
28036384Ssklower  *					on the type of address. The network portion of the
28136384Ssklower  *					address will include the IDP. The network portion is:
28236384Ssklower  *
28336384Ssklower  *						TYPE			DESC
28436384Ssklower  *					t37					The AFI and x.121 (IDI)
28536384Ssklower  *					osinet				The AFI, orgid, snetid
28636384Ssklower  *					rfc986				The AFI, vers and network part of
28736384Ssklower  *										internet address.
28836384Ssklower  *
28936384Ssklower  * RETURNS:			number of bytes placed into buf.
29036384Ssklower  *
29136384Ssklower  * SIDE EFFECTS:
29236384Ssklower  *
29336384Ssklower  * NOTES:			Buf is assumed to be big enough
29436384Ssklower  */
29536384Ssklower iso_netof(isoa, buf)
29636384Ssklower struct iso_addr	*isoa;		/* address */
29736384Ssklower caddr_t			buf;		/* RESULT: network portion of address here */
29836384Ssklower {
29936384Ssklower 	u_int		len = 1;	/* length of afi */
30036384Ssklower 
30136384Ssklower 	switch (isoa->isoa_afi) {
30236384Ssklower 		case AFI_37:
30336384Ssklower 			/*
30436384Ssklower 			 * Due to classic x.25 tunnel vision, there is no
30536384Ssklower 			 * net portion of an x.121 address.  For our purposes
30636384Ssklower 			 * the AFI will do, so that all x.25 -type addresses
30736384Ssklower 			 * map to the single x.25 SNPA. (Cannot have more than
30836384Ssklower 			 * one, obviously).
30936384Ssklower 			 */
31036384Ssklower 
31136384Ssklower 			break;
31236384Ssklower 
31336384Ssklower /* 		case AFI_OSINET:*/
31436384Ssklower 		case AFI_RFC986: {
31536384Ssklower 			u_short	idi;	/* value of idi */
31636384Ssklower 
31736384Ssklower 			/* osinet and rfc986 have idi in the same place */
31836384Ssklower 			CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi);
31936384Ssklower 
32036384Ssklower 			if (idi == IDI_OSINET)
32136384Ssklower /*
32236384Ssklower  *	Network portion of OSINET address can only be the IDI. Clearly,
32336384Ssklower  *	with one x25 interface, one could get to several orgids, and
32436384Ssklower  *	several snetids.
32536384Ssklower 				len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN +
32636384Ssklower 						OVLOSINET_SNETID_LEN);
32736384Ssklower  */
32836384Ssklower 				len += ADDROSINET_IDI_LEN;
32936384Ssklower 			else if (idi == IDI_RFC986) {
33036384Ssklower 				u_long				inetaddr;
33136384Ssklower 				struct ovl_rfc986	*o986 = (struct ovl_rfc986 *)isoa;
33236384Ssklower 
33336384Ssklower 				/* bump len to include idi and version (1 byte) */
33436384Ssklower 				len += ADDRRFC986_IDI_LEN + 1;
33536384Ssklower 
33636384Ssklower 				/* get inet addr long aligned */
33736384Ssklower 				bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr));
33836384Ssklower 				inetaddr = ntohl(inetaddr);	/* convert to host byte order */
33936384Ssklower 
34036384Ssklower 				IFDEBUG(D_ROUTE)
34136384Ssklower 					printf("iso_netof: isoa ");
34236384Ssklower 					dump_buf(isoa, sizeof(*isoa));
34336384Ssklower 					printf("iso_netof: inetaddr 0x%x ", inetaddr);
34436384Ssklower 				ENDDEBUG
34536384Ssklower 
34636384Ssklower 				/* bump len by size of network portion of inet address */
34736384Ssklower 				if (IN_CLASSA(inetaddr)) {
34836384Ssklower 					len += 4-IN_CLASSA_NSHIFT/8;
34936384Ssklower 					IFDEBUG(D_ROUTE)
35036384Ssklower 						printf("iso_netof: class A net len is now %d\n", len);
35136384Ssklower 					ENDDEBUG
35236384Ssklower 				} else if (IN_CLASSB(inetaddr)) {
35336384Ssklower 					len += 4-IN_CLASSB_NSHIFT/8;
35436384Ssklower 					IFDEBUG(D_ROUTE)
35536384Ssklower 						printf("iso_netof: class B net len is now %d\n", len);
35636384Ssklower 					ENDDEBUG
35736384Ssklower 				} else {
35836384Ssklower 					len += 4-IN_CLASSC_NSHIFT/8;
35936384Ssklower 					IFDEBUG(D_ROUTE)
36036384Ssklower 						printf("iso_netof: class C net len is now %d\n", len);
36136384Ssklower 					ENDDEBUG
36236384Ssklower 				}
36336384Ssklower 			} else
36436384Ssklower 				len = 0;
36536384Ssklower 		} break;
36636384Ssklower 
36736384Ssklower 		default:
36836384Ssklower 			len = 0;
36936384Ssklower 	}
37036384Ssklower 
37136384Ssklower 	bcopy((caddr_t)isoa, buf, len);
37236384Ssklower 	IFDEBUG(D_ROUTE)
37336384Ssklower 		printf("in_netof: isoa ");
37436384Ssklower 		dump_buf(isoa, len);
37536384Ssklower 		printf("in_netof: net ");
37636384Ssklower 		dump_buf(buf, len);
37736384Ssklower 	ENDDEBUG
37836384Ssklower 	return len;
37936384Ssklower }
38037469Ssklower #endif notdef
38136384Ssklower /*
38237469Ssklower  * Generic iso control operations (ioctl's).
38337469Ssklower  * Ifp is 0 if not an interface-specific ioctl.
38436384Ssklower  */
38537469Ssklower /* ARGSUSED */
38636384Ssklower iso_control(so, cmd, data, ifp)
38737469Ssklower 	struct socket *so;
38837469Ssklower 	int cmd;
38937469Ssklower 	caddr_t data;
39037469Ssklower 	register struct ifnet *ifp;
39136384Ssklower {
39237469Ssklower 	register struct iso_ifreq *ifr = (struct iso_ifreq *)data;
39337469Ssklower 	register struct iso_ifaddr *ia = 0;
39437469Ssklower 	register struct ifaddr *ifa;
39537469Ssklower 	struct iso_ifaddr *oia;
39637469Ssklower 	struct iso_aliasreq *ifra = (struct iso_aliasreq *)data;
39737469Ssklower 	int error, hostIsNew, maskIsNew;
39836384Ssklower 
39937469Ssklower 	/*
40037469Ssklower 	 * Find address for this interface, if it exists.
40137469Ssklower 	 */
40237469Ssklower 	if (ifp)
40337469Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
40437469Ssklower 			if (ia->ia_ifp == ifp)
40537469Ssklower 				break;
40636384Ssklower 
40736384Ssklower 	switch (cmd) {
40837469Ssklower 
40937469Ssklower 	case SIOCAIFADDR_ISO:
41037469Ssklower 	case SIOCDIFADDR_ISO:
41137469Ssklower 		if (ifra->ifra_addr.siso_family == AF_ISO)
41237469Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
41337469Ssklower 			if (ia->ia_ifp == ifp  &&
41437469Ssklower 			    SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
41537469Ssklower 				break;
41637469Ssklower 		}
41750232Ssklower 		if ((so->so_state & SS_PRIV) == 0)
41850232Ssklower 			return (EPERM);
41936384Ssklower 		if (ifp == 0)
42037469Ssklower 			panic("iso_control");
42137469Ssklower 		if (ia == (struct iso_ifaddr *)0) {
42237469Ssklower 			struct iso_ifaddr *nia;
42337469Ssklower 			if (cmd == SIOCDIFADDR_ISO)
42437469Ssklower 				return (EADDRNOTAVAIL);
42537469Ssklower 			MALLOC(nia, struct iso_ifaddr *, sizeof(*nia),
42637469Ssklower 				       M_IFADDR, M_WAITOK);
42737469Ssklower 			if (nia == (struct iso_ifaddr *)0)
42837469Ssklower 				return (ENOBUFS);
42937469Ssklower 			bzero((caddr_t)nia, sizeof(*nia));
43037469Ssklower 			if (ia = iso_ifaddr) {
43137469Ssklower 				for ( ; ia->ia_next; ia = ia->ia_next)
43237469Ssklower 					;
43337469Ssklower 				ia->ia_next = nia;
43437469Ssklower 			} else
43537469Ssklower 				iso_ifaddr = nia;
43637469Ssklower 			ia = nia;
43737469Ssklower 			if (ifa = ifp->if_addrlist) {
43837469Ssklower 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
43937469Ssklower 					;
44037469Ssklower 				ifa->ifa_next = (struct ifaddr *) ia;
44137469Ssklower 			} else
44237469Ssklower 				ifp->if_addrlist = (struct ifaddr *) ia;
44337469Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
44437469Ssklower 			ia->ia_ifa.ifa_dstaddr
44537469Ssklower 					= (struct sockaddr *)&ia->ia_dstaddr;
44637469Ssklower 			ia->ia_ifa.ifa_netmask
44737469Ssklower 					= (struct sockaddr *)&ia->ia_sockmask;
44837469Ssklower 			ia->ia_ifp = ifp;
44937469Ssklower 			if (ifp != &loif)
45037469Ssklower 				iso_interfaces++;
45137469Ssklower 		}
45237469Ssklower 		break;
45336384Ssklower 
45437469Ssklower #define cmdbyte(x)	(((x) >> 8) & 0xff)
45537469Ssklower 	default:
45637469Ssklower 		if (cmdbyte(cmd) == 'a')
45750232Ssklower 			return (snpac_ioctl(so, cmd, data));
45837469Ssklower 		if (ia == (struct iso_ifaddr *)0)
45937469Ssklower 			return (EADDRNOTAVAIL);
46037469Ssklower 		break;
46137469Ssklower 	}
46237469Ssklower 	switch (cmd) {
46336384Ssklower 
46437469Ssklower 	case SIOCGIFADDR_ISO:
46537469Ssklower 		ifr->ifr_Addr = ia->ia_addr;
46637469Ssklower 		break;
46736384Ssklower 
46837469Ssklower 	case SIOCGIFDSTADDR_ISO:
46937469Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
47037469Ssklower 			return (EINVAL);
47137469Ssklower 		ifr->ifr_Addr = ia->ia_dstaddr;
47237469Ssklower 		break;
47336384Ssklower 
47437469Ssklower 	case SIOCGIFNETMASK_ISO:
47537469Ssklower 		ifr->ifr_Addr = ia->ia_sockmask;
47637469Ssklower 		break;
47736384Ssklower 
47837469Ssklower 	case SIOCAIFADDR_ISO:
47943428Ssklower 		maskIsNew = 0; hostIsNew = 1; error = 0;
48037469Ssklower 		if (ia->ia_addr.siso_family == AF_ISO) {
48137469Ssklower 			if (ifra->ifra_addr.siso_len == 0) {
48237469Ssklower 				ifra->ifra_addr = ia->ia_addr;
48337469Ssklower 				hostIsNew = 0;
48437469Ssklower 			} else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
48537469Ssklower 				hostIsNew = 0;
48637469Ssklower 		}
48737469Ssklower 		if (ifra->ifra_mask.siso_len) {
48837469Ssklower 			iso_ifscrub(ifp, ia);
48937469Ssklower 			ia->ia_sockmask = ifra->ifra_mask;
49037469Ssklower 			maskIsNew = 1;
49137469Ssklower 		}
49237469Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
49337469Ssklower 		    (ifra->ifra_dstaddr.siso_family == AF_ISO)) {
49437469Ssklower 			iso_ifscrub(ifp, ia);
49537469Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
49637469Ssklower 			maskIsNew  = 1; /* We lie; but the effect's the same */
49737469Ssklower 		}
49837469Ssklower 		if (ifra->ifra_addr.siso_family == AF_ISO &&
49937469Ssklower 					    (hostIsNew || maskIsNew)) {
50037469Ssklower 			error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0);
50137469Ssklower 		}
50237469Ssklower 		if (ifra->ifra_snpaoffset)
50337469Ssklower 			ia->ia_snpaoffset = ifra->ifra_snpaoffset;
50437469Ssklower 		return (error);
50537469Ssklower 
50637469Ssklower 	case SIOCDIFADDR_ISO:
50737469Ssklower 		iso_ifscrub(ifp, ia);
50837469Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
50937469Ssklower 			ifp->if_addrlist = ifa->ifa_next;
51037469Ssklower 		else {
51137469Ssklower 			while (ifa->ifa_next &&
51237469Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
51337469Ssklower 				    ifa = ifa->ifa_next;
51437469Ssklower 			if (ifa->ifa_next)
51537469Ssklower 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
51637469Ssklower 			else
51737469Ssklower 				printf("Couldn't unlink isoifaddr from ifp\n");
51837469Ssklower 		}
51937469Ssklower 		oia = ia;
52037469Ssklower 		if (oia == (ia = iso_ifaddr)) {
52137469Ssklower 			iso_ifaddr = ia->ia_next;
52237469Ssklower 		} else {
52337469Ssklower 			while (ia->ia_next && (ia->ia_next != oia)) {
52437469Ssklower 				ia = ia->ia_next;
52536384Ssklower 			}
52637469Ssklower 			if (ia->ia_next)
52737469Ssklower 			    ia->ia_next = oia->ia_next;
52837469Ssklower 			else
52937469Ssklower 				printf("Didn't unlink isoifadr from list\n");
53036384Ssklower 		}
53152030Ssklower 		IFAFREE((&oia->ia_ifa));
53237469Ssklower 		break;
53336384Ssklower 
53436384Ssklower 	default:
53536384Ssklower 		if (ifp == 0 || ifp->if_ioctl == 0)
53636384Ssklower 			return (EOPNOTSUPP);
53736384Ssklower 		return ((*ifp->if_ioctl)(ifp, cmd, data));
53836384Ssklower 	}
53937469Ssklower 	return (0);
54036384Ssklower }
54136384Ssklower 
54237469Ssklower /*
54337469Ssklower  * Delete any existing route for an interface.
54437469Ssklower  */
54537469Ssklower iso_ifscrub(ifp, ia)
54637469Ssklower 	register struct ifnet *ifp;
54737469Ssklower 	register struct iso_ifaddr *ia;
54837469Ssklower {
54943333Ssklower 	int nsellength = ia->ia_addr.siso_tlen;
55037469Ssklower 	if ((ia->ia_flags & IFA_ROUTE) == 0)
55137469Ssklower 		return;
55243333Ssklower 	ia->ia_addr.siso_tlen = 0;
55337469Ssklower 	if (ifp->if_flags & IFF_LOOPBACK)
55437469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
55537469Ssklower 	else if (ifp->if_flags & IFF_POINTOPOINT)
55637469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
55737469Ssklower 	else {
55837469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
55937469Ssklower 	}
56043333Ssklower 	ia->ia_addr.siso_tlen = nsellength;
56137469Ssklower 	ia->ia_flags &= ~IFA_ROUTE;
56237469Ssklower }
56337469Ssklower 
56437469Ssklower /*
56537469Ssklower  * Initialize an interface's internet address
56637469Ssklower  * and routing table entry.
56737469Ssklower  */
56837469Ssklower iso_ifinit(ifp, ia, siso, scrub)
56937469Ssklower 	register struct ifnet *ifp;
57037469Ssklower 	register struct iso_ifaddr *ia;
57137469Ssklower 	struct sockaddr_iso *siso;
57237469Ssklower {
57337469Ssklower 	struct sockaddr_iso oldaddr;
57443333Ssklower 	int s = splimp(), error, nsellength;
57537469Ssklower 
57637469Ssklower 	oldaddr = ia->ia_addr;
57737469Ssklower 	ia->ia_addr = *siso;
57837469Ssklower 	/*
57937469Ssklower 	 * Give the interface a chance to initialize
58037469Ssklower 	 * if this is its first address,
58137469Ssklower 	 * and to validate the address if necessary.
58237469Ssklower 	 */
583*54823Ssklower 	if (ifp->if_ioctl &&
584*54823Ssklower 				(error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
58537469Ssklower 		splx(s);
58637469Ssklower 		ia->ia_addr = oldaddr;
58737469Ssklower 		return (error);
58837469Ssklower 	}
58937469Ssklower 	if (scrub) {
59037469Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
59137469Ssklower 		iso_ifscrub(ifp, ia);
59237469Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
59337469Ssklower 	}
59443333Ssklower 	/* XXX -- The following is here temporarily out of laziness
59543333Ssklower 	   in not changing every ethernet driver's if_ioctl routine */
59643333Ssklower 	if (ifp->if_output == ether_output) {
59743333Ssklower 		ia->ia_ifa.ifa_rtrequest = llc_rtrequest;
59843333Ssklower 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
59943333Ssklower 	}
60037469Ssklower 	/*
60137469Ssklower 	 * Add route for the network.
60237469Ssklower 	 */
60343333Ssklower 	nsellength = ia->ia_addr.siso_tlen;
60443333Ssklower 	ia->ia_addr.siso_tlen = 0;
60537469Ssklower 	if (ifp->if_flags & IFF_LOOPBACK) {
60637469Ssklower 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
60740894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
60837469Ssklower 	} else if (ifp->if_flags & IFF_POINTOPOINT &&
60937469Ssklower 		 ia->ia_dstaddr.siso_family == AF_ISO)
61040894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
61137469Ssklower 	else {
61240894Ssklower 		rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
61340894Ssklower 			ia->ia_ifa.ifa_netmask);
61449936Ssklower 		ia->ia_dstaddr.siso_nlen =
61549936Ssklower 			min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6));
61640894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
61737469Ssklower 	}
61843333Ssklower 	ia->ia_addr.siso_tlen = nsellength;
61937469Ssklower 	ia->ia_flags |= IFA_ROUTE;
62037469Ssklower 	splx(s);
62140894Ssklower 	return (error);
62237469Ssklower }
62337469Ssklower #ifdef notdef
62437469Ssklower 
62536384Ssklower struct ifaddr *
62636384Ssklower iso_ifwithidi(addr)
62736384Ssklower 	register struct sockaddr *addr;
62836384Ssklower {
62936384Ssklower 	register struct ifnet *ifp;
63036384Ssklower 	register struct ifaddr *ifa;
63136384Ssklower 	register u_int af = addr->sa_family;
63236384Ssklower 
63336384Ssklower 	if (af != AF_ISO)
63436384Ssklower 		return (0);
63536384Ssklower 	IFDEBUG(D_ROUTE)
63636384Ssklower 		printf(">>> iso_ifwithidi addr\n");
63736384Ssklower 		dump_isoaddr( (struct sockaddr_iso *)(addr));
63836384Ssklower 		printf("\n");
63936384Ssklower 	ENDDEBUG
64036384Ssklower 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
64136384Ssklower 		IFDEBUG(D_ROUTE)
64236384Ssklower 			printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
64336384Ssklower 		ENDDEBUG
64436384Ssklower 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
64536384Ssklower 			IFDEBUG(D_ROUTE)
64636384Ssklower 				printf("iso_ifwithidi address ");
64737469Ssklower 				dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr));
64836384Ssklower 			ENDDEBUG
64937469Ssklower 			if (ifa->ifa_addr->sa_family != addr->sa_family)
65036384Ssklower 				continue;
65136384Ssklower 
65236384Ssklower #define	IFA_SIS(ifa)\
65337469Ssklower 	((struct sockaddr_iso *)((ifa)->ifa_addr))
65436384Ssklower 
65536384Ssklower 			IFDEBUG(D_ROUTE)
65636384Ssklower 				printf(" af same, args to iso_eqtype:\n");
65736384Ssklower 				printf("0x%x ", IFA_SIS(ifa)->siso_addr);
65836384Ssklower 				printf(" 0x%x\n",
65936384Ssklower 				&(((struct sockaddr_iso *)addr)->siso_addr));
66036384Ssklower 			ENDDEBUG
66136384Ssklower 
66236384Ssklower 			if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr),
66336384Ssklower 				&(((struct sockaddr_iso *)addr)->siso_addr))) {
66436384Ssklower 				IFDEBUG(D_ROUTE)
66536384Ssklower 					printf("ifa_ifwithidi: ifa found\n");
66636384Ssklower 				ENDDEBUG
66736384Ssklower 				return (ifa);
66836384Ssklower 			}
66936384Ssklower 			IFDEBUG(D_ROUTE)
67036384Ssklower 				printf(" iso_eqtype failed\n");
67136384Ssklower 			ENDDEBUG
67236384Ssklower 		}
67336384Ssklower 	}
67436384Ssklower 	return ((struct ifaddr *)0);
67536384Ssklower }
67636384Ssklower 
67737469Ssklower #endif notdef
67836384Ssklower /*
67936384Ssklower  * FUNCTION:		iso_ck_addr
68036384Ssklower  *
68136384Ssklower  * PURPOSE:			return true if the iso_addr passed is
68236384Ssklower  *					within the legal size limit for an iso address.
68336384Ssklower  *
68436384Ssklower  * RETURNS:			true or false
68536384Ssklower  *
68636384Ssklower  * SIDE EFFECTS:
68736384Ssklower  *
68836384Ssklower  */
68936384Ssklower iso_ck_addr(isoa)
69036384Ssklower struct iso_addr	*isoa;	/* address to check */
69136384Ssklower {
69236384Ssklower 	return (isoa->isoa_len <= 20);
69336384Ssklower 
69436384Ssklower }
69536384Ssklower 
69637469Ssklower #ifdef notdef
69736384Ssklower /*
69836384Ssklower  * FUNCTION:		iso_eqtype
69936384Ssklower  *
70036384Ssklower  * PURPOSE:			Determine if two iso addresses are of the same type.
70136384Ssklower  *  This is flaky.  Really we should consider all type 47 addrs to be the
70236384Ssklower  *  same - but there do exist different structures for 47 addrs.
70336384Ssklower  *  Gosip adds a 3rd.
70436384Ssklower  *
70536384Ssklower  * RETURNS:			true if the addresses are the same type
70636384Ssklower  *
70736384Ssklower  * SIDE EFFECTS:
70836384Ssklower  *
70936384Ssklower  * NOTES:			By type, I mean rfc986, t37, or osinet
71036384Ssklower  *
71136384Ssklower  *					This will first compare afis. If they match, then
71236384Ssklower  *					if the addr is not t37, the idis must be compared.
71336384Ssklower  */
71436384Ssklower iso_eqtype(isoaa, isoab)
71536384Ssklower struct iso_addr	*isoaa;		/* first addr to check */
71636384Ssklower struct iso_addr	*isoab;		/* other addr to check */
71736384Ssklower {
71836384Ssklower 	if (isoaa->isoa_afi == isoab->isoa_afi) {
71936384Ssklower 		if (isoaa->isoa_afi == AFI_37)
72036384Ssklower 			return(1);
72136384Ssklower 		else
72236384Ssklower 			return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
72336384Ssklower 	}
72436384Ssklower 	return(0);
72536384Ssklower }
72637469Ssklower #endif notdef
72736384Ssklower /*
72837469Ssklower  * FUNCTION:		iso_localifa()
72936384Ssklower  *
73037469Ssklower  * PURPOSE:			Find an interface addresss having a given destination
73137469Ssklower  *					or at least matching the net.
73236384Ssklower  *
73336384Ssklower  * RETURNS:			ptr to an interface address
73436384Ssklower  *
73536384Ssklower  * SIDE EFFECTS:
73636384Ssklower  *
73736384Ssklower  * NOTES:
73836384Ssklower  */
73936384Ssklower struct iso_ifaddr *
74037469Ssklower iso_localifa(siso)
74137469Ssklower 	register struct sockaddr_iso *siso;
74236384Ssklower {
74336384Ssklower 	register struct iso_ifaddr *ia;
74437469Ssklower 	register char *cp1, *cp2, *cp3;
74537469Ssklower 	register struct ifnet *ifp;
74637469Ssklower 	struct iso_ifaddr *ia_maybe = 0;
74737469Ssklower 	/*
74837469Ssklower 	 * We make one pass looking for both net matches and an exact
74937469Ssklower 	 * dst addr.
75037469Ssklower 	 */
75137469Ssklower 	for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
75237469Ssklower 		if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
75337469Ssklower 			continue;
75437469Ssklower 		if (ifp->if_flags & IFF_POINTOPOINT) {
75537469Ssklower 			if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
75637469Ssklower 				SAME_ISOADDR(&ia->ia_dstaddr, siso))
75737469Ssklower 				return (ia);
75837469Ssklower 			else
75937469Ssklower 				if (SAME_ISOADDR(&ia->ia_addr, siso))
76037469Ssklower 					ia_maybe = ia;
76137469Ssklower 			continue;
76237469Ssklower 		}
76337469Ssklower 		if (ia->ia_sockmask.siso_len) {
76437469Ssklower 			char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask;
76537469Ssklower 			cp1 = ia->ia_sockmask.siso_data;
76637469Ssklower 			cp2 = siso->siso_data;
76737469Ssklower 			cp3 = ia->ia_addr.siso_data;
76839936Ssklower 			while (cp1 < cplim)
76937469Ssklower 				if (*cp1++ & (*cp2++ ^ *cp3++))
77037469Ssklower 					goto next;
77137469Ssklower 			ia_maybe = ia;
77237469Ssklower 		}
77337469Ssklower 		if (SAME_ISOADDR(&ia->ia_addr, siso))
77437469Ssklower 			return ia;
77537469Ssklower 	next:;
77637469Ssklower 	}
77737469Ssklower 	return ia_maybe;
77836384Ssklower }
77936384Ssklower 
78047272Ssklower #ifdef	TPCONS
78136384Ssklower #include "cons.h"
78247272Ssklower #endif	TPCONS
78336384Ssklower /*
78436384Ssklower  * FUNCTION:		iso_nlctloutput
78536384Ssklower  *
78636384Ssklower  * PURPOSE:			Set options at the network level
78736384Ssklower  *
78836384Ssklower  * RETURNS:			E*
78936384Ssklower  *
79036384Ssklower  * SIDE EFFECTS:
79136384Ssklower  *
79236384Ssklower  * NOTES:			This could embody some of the functions of
79336384Ssklower  *					rclnp_ctloutput and cons_ctloutput.
79436384Ssklower  */
79536384Ssklower iso_nlctloutput(cmd, optname, pcb, m)
79636384Ssklower int			cmd;		/* command:set or get */
79736384Ssklower int			optname;	/* option of interest */
79836384Ssklower caddr_t		pcb;		/* nl pcb */
79936384Ssklower struct mbuf	*m;			/* data for set, buffer for get */
80036384Ssklower {
80136384Ssklower 	struct isopcb	*isop = (struct isopcb *)pcb;
80236384Ssklower 	int				error = 0;	/* return value */
80336384Ssklower 	caddr_t			data;		/* data for option */
80436384Ssklower 	int				data_len;	/* data's length */
80536384Ssklower 
80636384Ssklower 	IFDEBUG(D_ISO)
80736384Ssklower 		printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n",
80836384Ssklower 			cmd, optname, pcb, m);
80936384Ssklower 	ENDDEBUG
81036384Ssklower 
81136384Ssklower 	if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
81236384Ssklower 		return(EOPNOTSUPP);
81336384Ssklower 
81436384Ssklower 	data = mtod(m, caddr_t);
81536384Ssklower 	data_len = (m)->m_len;
81636384Ssklower 
81736384Ssklower 	IFDEBUG(D_ISO)
81836384Ssklower 		printf("iso_nlctloutput: data is:\n");
81936384Ssklower 		dump_buf(data, data_len);
82036384Ssklower 	ENDDEBUG
82136384Ssklower 
82236384Ssklower 	switch (optname) {
82336384Ssklower 
82447272Ssklower #ifdef	TPCONS
82536384Ssklower 		case CONSOPT_X25CRUD:
82636384Ssklower 			if (cmd == PRCO_GETOPT) {
82736384Ssklower 				error = EOPNOTSUPP;
82836384Ssklower 				break;
82936384Ssklower 			}
83036384Ssklower 
83136384Ssklower 			if (data_len > MAXX25CRUDLEN) {
83236384Ssklower 				error = EINVAL;
83336384Ssklower 				break;
83436384Ssklower 			}
83536384Ssklower 
83636384Ssklower 			IFDEBUG(D_ISO)
83736384Ssklower 				printf("iso_nlctloutput: setting x25 crud\n");
83836384Ssklower 			ENDDEBUG
83936384Ssklower 
84037469Ssklower 			bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len);
84136384Ssklower 			isop->isop_x25crud_len = data_len;
84236384Ssklower 			break;
84347272Ssklower #endif	TPCONS
84436384Ssklower 
84536384Ssklower 		default:
84636384Ssklower 			error = EOPNOTSUPP;
84736384Ssklower 	}
84850972Ssklower 	if (cmd == PRCO_SETOPT)
84950972Ssklower 		m_freem(m);
85036384Ssklower 	return error;
85136384Ssklower }
85236384Ssklower #endif ISO
85336384Ssklower 
85436384Ssklower #ifdef ARGO_DEBUG
85536384Ssklower 
85636384Ssklower /*
85736384Ssklower  * FUNCTION:		dump_isoaddr
85836384Ssklower  *
85936384Ssklower  * PURPOSE:			debugging
86036384Ssklower  *
86136384Ssklower  * RETURNS:			nada
86236384Ssklower  *
86336384Ssklower  */
86436384Ssklower dump_isoaddr(s)
86536384Ssklower 	struct sockaddr_iso *s;
86636384Ssklower {
86737469Ssklower 	char *clnp_saddr_isop();
86836384Ssklower 	register int i;
86936384Ssklower 
87036384Ssklower 	if( s->siso_family == AF_ISO) {
87137469Ssklower 		printf("ISO address: suffixlen %d, %s\n",
87238841Ssklower 			s->siso_tlen, clnp_saddr_isop(s));
87336384Ssklower 	} else if( s->siso_family == AF_INET) {
87436384Ssklower 		/* hack */
87536384Ssklower 		struct sockaddr_in *sin = (struct sockaddr_in *)s;
87636384Ssklower 
87736384Ssklower 		printf("%d.%d.%d.%d: %d",
87836384Ssklower 			(sin->sin_addr.s_addr>>24)&0xff,
87936384Ssklower 			(sin->sin_addr.s_addr>>16)&0xff,
88036384Ssklower 			(sin->sin_addr.s_addr>>8)&0xff,
88136384Ssklower 			(sin->sin_addr.s_addr)&0xff,
88236384Ssklower 			sin->sin_port);
88336384Ssklower 	}
88436384Ssklower }
88536384Ssklower 
88636384Ssklower #endif ARGO_DEBUG
887