xref: /csrg-svn/sys/netiso/iso.c (revision 50692)
149268Sbostic /*-
249268Sbostic  * Copyright (c) 1991 The Regents of the University of California.
349268Sbostic  * All rights reserved.
449268Sbostic  *
549268Sbostic  * %sccs.include.redist.c%
649268Sbostic  *
7*50692Ssklower  *	@(#)iso.c	7.15 (Berkeley) 07/30/91
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 */
6843333Ssklower int ether_output(), llc_rtrequest();
6936384Ssklower 
7036384Ssklower 
7136384Ssklower /*
7236384Ssklower  * FUNCTION:		iso_init
7336384Ssklower  *
7436384Ssklower  * PURPOSE:			initialize the iso address family
7536384Ssklower  *
7636384Ssklower  * RETURNS:			nothing
7736384Ssklower  *
7849936Ssklower  * SIDE EFFECTS:	1) initializes the routing table.
7936384Ssklower  *
8049936Ssklower  *
8136384Ssklower  * NOTES:
8236384Ssklower  */
8336384Ssklower iso_init()
8436384Ssklower {
85*50692Ssklower 	if (rt_tables[AF_ISO] == 0) {
86*50692Ssklower 		rn_inithead(rt_tables + AF_ISO, 48);
8737469Ssklower 	}
8836384Ssklower }
8936384Ssklower 
9036384Ssklower /*
9136384Ssklower  * FUNCTION:		iso_addrmatch1
9236384Ssklower  *
9336384Ssklower  * PURPOSE:			decide if the two iso_addrs passed are equal
9436384Ssklower  *
9536384Ssklower  * RETURNS:			true if the addrs match, false if they do not
9636384Ssklower  *
9736384Ssklower  * SIDE EFFECTS:
9836384Ssklower  *
9936384Ssklower  * NOTES:
10036384Ssklower  */
10136384Ssklower iso_addrmatch1(isoaa, isoab)
10237469Ssklower register struct iso_addr *isoaa, *isoab;		/* addresses to check */
10336384Ssklower {
10437469Ssklower 	u_int	compare_len;
10536384Ssklower 
10636384Ssklower 	IFDEBUG(D_ROUTE)
10736384Ssklower 		printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len,
10836384Ssklower 			isoab->isoa_len);
10936384Ssklower 		printf("a:\n");
11037469Ssklower 		dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len);
11136384Ssklower 		printf("b:\n");
11237469Ssklower 		dump_buf(isoab->isoa_genaddr, isoab->isoa_len);
11336384Ssklower 	ENDDEBUG
11436384Ssklower 
11536384Ssklower 	if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) {
11636384Ssklower 		IFDEBUG(D_ROUTE)
11736384Ssklower 			printf("iso_addrmatch1: returning false because of lengths\n");
11836384Ssklower 		ENDDEBUG
11936384Ssklower 		return 0;
12036384Ssklower 	}
12136384Ssklower 
12237469Ssklower #ifdef notdef
12336384Ssklower 	/* TODO : generalize this to all afis with masks */
12436384Ssklower 	if(	isoaa->isoa_afi == AFI_37 ) {
12536384Ssklower 		/* must not compare 2 least significant digits, or for
12636384Ssklower 		 * that matter, the DSP
12736384Ssklower 		 */
12836384Ssklower 		compare_len = ADDR37_IDI_LEN - 1;
12936384Ssklower 	}
13037469Ssklower #endif
13136384Ssklower 
13236384Ssklower 	IFDEBUG(D_ROUTE)
13336384Ssklower 		int i;
13436384Ssklower 		char *a, *b;
13536384Ssklower 
13637469Ssklower 		a = isoaa->isoa_genaddr;
13737469Ssklower 		b = isoab->isoa_genaddr;
13836384Ssklower 
13936384Ssklower 		for (i=0; i<compare_len; i++) {
14036384Ssklower 			printf("<%x=%x>", a[i]&0xff, b[i]&0xff);
14136384Ssklower 			if (a[i] != b[i]) {
14236384Ssklower 				printf("\naddrs are not equal at byte %d\n", i);
14336384Ssklower 				return(0);
14436384Ssklower 			}
14536384Ssklower 		}
14636384Ssklower 		printf("\n");
14736384Ssklower 		printf("addrs are equal\n");
14836384Ssklower 		return (1);
14936384Ssklower 	ENDDEBUG
15037469Ssklower 	return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len));
15136384Ssklower }
15236384Ssklower 
15336384Ssklower /*
15436384Ssklower  * FUNCTION:		iso_addrmatch
15536384Ssklower  *
15636384Ssklower  * PURPOSE:			decide if the two sockadrr_isos passed are equal
15736384Ssklower  *
15836384Ssklower  * RETURNS:			true if the addrs match, false if they do not
15936384Ssklower  *
16036384Ssklower  * SIDE EFFECTS:
16136384Ssklower  *
16236384Ssklower  * NOTES:
16336384Ssklower  */
16436384Ssklower iso_addrmatch(sisoa, sisob)
16536384Ssklower struct sockaddr_iso	*sisoa, *sisob;		/* addresses to check */
16636384Ssklower {
16736384Ssklower 	return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr));
16836384Ssklower }
16937469Ssklower #ifdef notdef
17036384Ssklower /*
17136384Ssklower  * FUNCTION:		iso_netmatch
17236384Ssklower  *
17336384Ssklower  * PURPOSE:			similar to iso_addrmatch but takes sockaddr_iso
17436384Ssklower  *					as argument.
17536384Ssklower  *
17636384Ssklower  * RETURNS:			true if same net, false if not
17736384Ssklower  *
17836384Ssklower  * SIDE EFFECTS:
17936384Ssklower  *
18036384Ssklower  * NOTES:
18136384Ssklower  */
18236384Ssklower iso_netmatch(sisoa, sisob)
18336384Ssklower struct sockaddr_iso *sisoa, *sisob;
18436384Ssklower {
18536384Ssklower 	u_char			bufa[sizeof(struct sockaddr_iso)];
18636384Ssklower 	u_char			bufb[sizeof(struct sockaddr_iso)];
18736384Ssklower 	register int	lena, lenb;
18836384Ssklower 
18936384Ssklower 	lena = iso_netof(&sisoa->siso_addr, bufa);
19036384Ssklower 	lenb = iso_netof(&sisob->siso_addr, bufb);
19136384Ssklower 
19236384Ssklower 	IFDEBUG(D_ROUTE)
19336384Ssklower 		printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb);
19436384Ssklower 		printf("a:\n");
19536384Ssklower 		dump_buf(bufa, lena);
19636384Ssklower 		printf("b:\n");
19736384Ssklower 		dump_buf(bufb, lenb);
19836384Ssklower 	ENDDEBUG
19936384Ssklower 
20036384Ssklower 	return ((lena == lenb) && (!bcmp(bufa, bufb, lena)));
20136384Ssklower }
20237469Ssklower #endif notdef
20336384Ssklower 
20436384Ssklower /*
20536384Ssklower  * FUNCTION:		iso_hashchar
20636384Ssklower  *
20736384Ssklower  * PURPOSE:			Hash all character in the buffer specified into
20836384Ssklower  *					a long. Return the long.
20936384Ssklower  *
21036384Ssklower  * RETURNS:			The hash value.
21136384Ssklower  *
21236384Ssklower  * SIDE EFFECTS:
21336384Ssklower  *
21436384Ssklower  * NOTES:			The hash is achieved by exclusive ORing 4 byte
21536384Ssklower  *					quantities.
21636384Ssklower  */
21736384Ssklower u_long
21836384Ssklower iso_hashchar(buf, len)
21936384Ssklower register caddr_t	buf;		/* buffer to pack from */
22036384Ssklower register int		len;		/* length of buffer */
22136384Ssklower {
22236384Ssklower 	register u_long	h = 0;
22336384Ssklower 	register int	i;
22436384Ssklower 
22536384Ssklower 	for (i=0; i<len; i+=4) {
22636384Ssklower 		register u_long	l = 0;
22736384Ssklower 
22836384Ssklower 		if ((len - i) < 4) {
22936384Ssklower 			/* buffer not multiple of 4 */
23036384Ssklower 			switch (len - i) {
23136384Ssklower 				case 3:
23236384Ssklower 					l |= buf[i+2] << 8;
23336384Ssklower 				case 2:
23436384Ssklower 					l |= buf[i+1] << 16;
23536384Ssklower 				case 1:
23636384Ssklower 					l |= buf[i] << 24;
23736384Ssklower 					break;
23836384Ssklower 				default:
23936384Ssklower 					printf("iso_hashchar: unexpected value x%x\n", len - i);
24036384Ssklower 					break;
24136384Ssklower 			}
24236384Ssklower 		} else {
24336384Ssklower 			l |= buf[i] << 24;
24436384Ssklower 			l |= buf[i+1] << 16;
24536384Ssklower 			l |= buf[i+2] << 8;
24636384Ssklower 			l |= buf[i+3];
24736384Ssklower 		}
24836384Ssklower 
24936384Ssklower 		h ^= l;
25036384Ssklower 	}
25136384Ssklower 
25236384Ssklower 	h ^= (u_long) (len % 4);
25336384Ssklower 
25436384Ssklower 	return(h);
25536384Ssklower }
25637469Ssklower #ifdef notdef
25736384Ssklower /*
25836384Ssklower  * FUNCTION:		iso_hash
25936384Ssklower  *
26036384Ssklower  * PURPOSE:			Fill in fields of afhash structure based upon addr passed.
26136384Ssklower  *
26236384Ssklower  * RETURNS:			none
26336384Ssklower  *
26436384Ssklower  * SIDE EFFECTS:
26536384Ssklower  *
26636384Ssklower  * NOTES:
26736384Ssklower  */
26836384Ssklower iso_hash(siso, hp)
26936384Ssklower struct sockaddr_iso	*siso;		/* address to perform hash on */
27036384Ssklower struct afhash		*hp;		/* RETURN: hash info here */
27136384Ssklower {
27236384Ssklower 	u_long			buf[sizeof(struct sockaddr_iso)+1/4];
27336384Ssklower 	register int	bufsize;
27436384Ssklower 
27536384Ssklower 
27636384Ssklower 	bzero(buf, sizeof(buf));
27736384Ssklower 
27836384Ssklower 	bufsize = iso_netof(&siso->siso_addr, buf);
27936384Ssklower 	hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize);
28036384Ssklower 
28136384Ssklower 	IFDEBUG(D_ROUTE)
28236384Ssklower 		printf("iso_hash: iso_netof: bufsize = %d\n", bufsize);
28336384Ssklower 	ENDDEBUG
28436384Ssklower 
28536384Ssklower 	hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr,
28636384Ssklower 		siso->siso_addr.isoa_len);
28736384Ssklower 
28836384Ssklower 	IFDEBUG(D_ROUTE)
28936384Ssklower 		printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n",
29036384Ssklower 			clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash,
29136384Ssklower 			hp->afh_hosthash);
29236384Ssklower 	ENDDEBUG
29336384Ssklower }
29436384Ssklower /*
29536384Ssklower  * FUNCTION:		iso_netof
29636384Ssklower  *
29736384Ssklower  * PURPOSE:			Extract the network portion of the iso address.
29836384Ssklower  *					The network portion of the iso address varies depending
29936384Ssklower  *					on the type of address. The network portion of the
30036384Ssklower  *					address will include the IDP. The network portion is:
30136384Ssklower  *
30236384Ssklower  *						TYPE			DESC
30336384Ssklower  *					t37					The AFI and x.121 (IDI)
30436384Ssklower  *					osinet				The AFI, orgid, snetid
30536384Ssklower  *					rfc986				The AFI, vers and network part of
30636384Ssklower  *										internet address.
30736384Ssklower  *
30836384Ssklower  * RETURNS:			number of bytes placed into buf.
30936384Ssklower  *
31036384Ssklower  * SIDE EFFECTS:
31136384Ssklower  *
31236384Ssklower  * NOTES:			Buf is assumed to be big enough
31336384Ssklower  */
31436384Ssklower iso_netof(isoa, buf)
31536384Ssklower struct iso_addr	*isoa;		/* address */
31636384Ssklower caddr_t			buf;		/* RESULT: network portion of address here */
31736384Ssklower {
31836384Ssklower 	u_int		len = 1;	/* length of afi */
31936384Ssklower 
32036384Ssklower 	switch (isoa->isoa_afi) {
32136384Ssklower 		case AFI_37:
32236384Ssklower 			/*
32336384Ssklower 			 * Due to classic x.25 tunnel vision, there is no
32436384Ssklower 			 * net portion of an x.121 address.  For our purposes
32536384Ssklower 			 * the AFI will do, so that all x.25 -type addresses
32636384Ssklower 			 * map to the single x.25 SNPA. (Cannot have more than
32736384Ssklower 			 * one, obviously).
32836384Ssklower 			 */
32936384Ssklower 
33036384Ssklower 			break;
33136384Ssklower 
33236384Ssklower /* 		case AFI_OSINET:*/
33336384Ssklower 		case AFI_RFC986: {
33436384Ssklower 			u_short	idi;	/* value of idi */
33536384Ssklower 
33636384Ssklower 			/* osinet and rfc986 have idi in the same place */
33736384Ssklower 			CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi);
33836384Ssklower 
33936384Ssklower 			if (idi == IDI_OSINET)
34036384Ssklower /*
34136384Ssklower  *	Network portion of OSINET address can only be the IDI. Clearly,
34236384Ssklower  *	with one x25 interface, one could get to several orgids, and
34336384Ssklower  *	several snetids.
34436384Ssklower 				len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN +
34536384Ssklower 						OVLOSINET_SNETID_LEN);
34636384Ssklower  */
34736384Ssklower 				len += ADDROSINET_IDI_LEN;
34836384Ssklower 			else if (idi == IDI_RFC986) {
34936384Ssklower 				u_long				inetaddr;
35036384Ssklower 				struct ovl_rfc986	*o986 = (struct ovl_rfc986 *)isoa;
35136384Ssklower 
35236384Ssklower 				/* bump len to include idi and version (1 byte) */
35336384Ssklower 				len += ADDRRFC986_IDI_LEN + 1;
35436384Ssklower 
35536384Ssklower 				/* get inet addr long aligned */
35636384Ssklower 				bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr));
35736384Ssklower 				inetaddr = ntohl(inetaddr);	/* convert to host byte order */
35836384Ssklower 
35936384Ssklower 				IFDEBUG(D_ROUTE)
36036384Ssklower 					printf("iso_netof: isoa ");
36136384Ssklower 					dump_buf(isoa, sizeof(*isoa));
36236384Ssklower 					printf("iso_netof: inetaddr 0x%x ", inetaddr);
36336384Ssklower 				ENDDEBUG
36436384Ssklower 
36536384Ssklower 				/* bump len by size of network portion of inet address */
36636384Ssklower 				if (IN_CLASSA(inetaddr)) {
36736384Ssklower 					len += 4-IN_CLASSA_NSHIFT/8;
36836384Ssklower 					IFDEBUG(D_ROUTE)
36936384Ssklower 						printf("iso_netof: class A net len is now %d\n", len);
37036384Ssklower 					ENDDEBUG
37136384Ssklower 				} else if (IN_CLASSB(inetaddr)) {
37236384Ssklower 					len += 4-IN_CLASSB_NSHIFT/8;
37336384Ssklower 					IFDEBUG(D_ROUTE)
37436384Ssklower 						printf("iso_netof: class B net len is now %d\n", len);
37536384Ssklower 					ENDDEBUG
37636384Ssklower 				} else {
37736384Ssklower 					len += 4-IN_CLASSC_NSHIFT/8;
37836384Ssklower 					IFDEBUG(D_ROUTE)
37936384Ssklower 						printf("iso_netof: class C net len is now %d\n", len);
38036384Ssklower 					ENDDEBUG
38136384Ssklower 				}
38236384Ssklower 			} else
38336384Ssklower 				len = 0;
38436384Ssklower 		} break;
38536384Ssklower 
38636384Ssklower 		default:
38736384Ssklower 			len = 0;
38836384Ssklower 	}
38936384Ssklower 
39036384Ssklower 	bcopy((caddr_t)isoa, buf, len);
39136384Ssklower 	IFDEBUG(D_ROUTE)
39236384Ssklower 		printf("in_netof: isoa ");
39336384Ssklower 		dump_buf(isoa, len);
39436384Ssklower 		printf("in_netof: net ");
39536384Ssklower 		dump_buf(buf, len);
39636384Ssklower 	ENDDEBUG
39736384Ssklower 	return len;
39836384Ssklower }
39937469Ssklower #endif notdef
40036384Ssklower /*
40137469Ssklower  * Generic iso control operations (ioctl's).
40237469Ssklower  * Ifp is 0 if not an interface-specific ioctl.
40336384Ssklower  */
40437469Ssklower /* ARGSUSED */
40536384Ssklower iso_control(so, cmd, data, ifp)
40637469Ssklower 	struct socket *so;
40737469Ssklower 	int cmd;
40837469Ssklower 	caddr_t data;
40937469Ssklower 	register struct ifnet *ifp;
41036384Ssklower {
41137469Ssklower 	register struct iso_ifreq *ifr = (struct iso_ifreq *)data;
41237469Ssklower 	register struct iso_ifaddr *ia = 0;
41337469Ssklower 	register struct ifaddr *ifa;
41437469Ssklower 	struct iso_ifaddr *oia;
41537469Ssklower 	struct iso_aliasreq *ifra = (struct iso_aliasreq *)data;
41637469Ssklower 	int error, hostIsNew, maskIsNew;
41736384Ssklower 
41837469Ssklower 	/*
41937469Ssklower 	 * Find address for this interface, if it exists.
42037469Ssklower 	 */
42137469Ssklower 	if (ifp)
42237469Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
42337469Ssklower 			if (ia->ia_ifp == ifp)
42437469Ssklower 				break;
42536384Ssklower 
42636384Ssklower 	switch (cmd) {
42737469Ssklower 
42837469Ssklower 	case SIOCAIFADDR_ISO:
42937469Ssklower 	case SIOCDIFADDR_ISO:
43037469Ssklower 		if (ifra->ifra_addr.siso_family == AF_ISO)
43137469Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
43237469Ssklower 			if (ia->ia_ifp == ifp  &&
43337469Ssklower 			    SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
43437469Ssklower 				break;
43537469Ssklower 		}
43650232Ssklower 		if ((so->so_state & SS_PRIV) == 0)
43750232Ssklower 			return (EPERM);
43836384Ssklower 		if (ifp == 0)
43937469Ssklower 			panic("iso_control");
44037469Ssklower 		if (ia == (struct iso_ifaddr *)0) {
44137469Ssklower 			struct iso_ifaddr *nia;
44237469Ssklower 			if (cmd == SIOCDIFADDR_ISO)
44337469Ssklower 				return (EADDRNOTAVAIL);
44437469Ssklower 			MALLOC(nia, struct iso_ifaddr *, sizeof(*nia),
44537469Ssklower 				       M_IFADDR, M_WAITOK);
44637469Ssklower 			if (nia == (struct iso_ifaddr *)0)
44737469Ssklower 				return (ENOBUFS);
44837469Ssklower 			bzero((caddr_t)nia, sizeof(*nia));
44937469Ssklower 			if (ia = iso_ifaddr) {
45037469Ssklower 				for ( ; ia->ia_next; ia = ia->ia_next)
45137469Ssklower 					;
45237469Ssklower 				ia->ia_next = nia;
45337469Ssklower 			} else
45437469Ssklower 				iso_ifaddr = nia;
45537469Ssklower 			ia = nia;
45637469Ssklower 			if (ifa = ifp->if_addrlist) {
45737469Ssklower 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
45837469Ssklower 					;
45937469Ssklower 				ifa->ifa_next = (struct ifaddr *) ia;
46037469Ssklower 			} else
46137469Ssklower 				ifp->if_addrlist = (struct ifaddr *) ia;
46237469Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
46337469Ssklower 			ia->ia_ifa.ifa_dstaddr
46437469Ssklower 					= (struct sockaddr *)&ia->ia_dstaddr;
46537469Ssklower 			ia->ia_ifa.ifa_netmask
46637469Ssklower 					= (struct sockaddr *)&ia->ia_sockmask;
46737469Ssklower 			ia->ia_ifp = ifp;
46837469Ssklower 			if (ifp != &loif)
46937469Ssklower 				iso_interfaces++;
47037469Ssklower 		}
47137469Ssklower 		break;
47236384Ssklower 
47337469Ssklower #define cmdbyte(x)	(((x) >> 8) & 0xff)
47437469Ssklower 	default:
47537469Ssklower 		if (cmdbyte(cmd) == 'a')
47650232Ssklower 			return (snpac_ioctl(so, cmd, data));
47737469Ssklower 		if (ia == (struct iso_ifaddr *)0)
47837469Ssklower 			return (EADDRNOTAVAIL);
47937469Ssklower 		break;
48037469Ssklower 	}
48137469Ssklower 	switch (cmd) {
48236384Ssklower 
48337469Ssklower 	case SIOCGIFADDR_ISO:
48437469Ssklower 		ifr->ifr_Addr = ia->ia_addr;
48537469Ssklower 		break;
48636384Ssklower 
48737469Ssklower 	case SIOCGIFDSTADDR_ISO:
48837469Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
48937469Ssklower 			return (EINVAL);
49037469Ssklower 		ifr->ifr_Addr = ia->ia_dstaddr;
49137469Ssklower 		break;
49236384Ssklower 
49337469Ssklower 	case SIOCGIFNETMASK_ISO:
49437469Ssklower 		ifr->ifr_Addr = ia->ia_sockmask;
49537469Ssklower 		break;
49636384Ssklower 
49737469Ssklower 	case SIOCAIFADDR_ISO:
49843428Ssklower 		maskIsNew = 0; hostIsNew = 1; error = 0;
49937469Ssklower 		if (ia->ia_addr.siso_family == AF_ISO) {
50037469Ssklower 			if (ifra->ifra_addr.siso_len == 0) {
50137469Ssklower 				ifra->ifra_addr = ia->ia_addr;
50237469Ssklower 				hostIsNew = 0;
50337469Ssklower 			} else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
50437469Ssklower 				hostIsNew = 0;
50537469Ssklower 		}
50637469Ssklower 		if (ifra->ifra_mask.siso_len) {
50737469Ssklower 			iso_ifscrub(ifp, ia);
50837469Ssklower 			ia->ia_sockmask = ifra->ifra_mask;
50937469Ssklower 			maskIsNew = 1;
51037469Ssklower 		}
51137469Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
51237469Ssklower 		    (ifra->ifra_dstaddr.siso_family == AF_ISO)) {
51337469Ssklower 			iso_ifscrub(ifp, ia);
51437469Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
51537469Ssklower 			maskIsNew  = 1; /* We lie; but the effect's the same */
51637469Ssklower 		}
51737469Ssklower 		if (ifra->ifra_addr.siso_family == AF_ISO &&
51837469Ssklower 					    (hostIsNew || maskIsNew)) {
51937469Ssklower 			error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0);
52037469Ssklower 		}
52137469Ssklower 		if (ifra->ifra_snpaoffset)
52237469Ssklower 			ia->ia_snpaoffset = ifra->ifra_snpaoffset;
52337469Ssklower 		return (error);
52437469Ssklower 
52537469Ssklower 	case SIOCDIFADDR_ISO:
52637469Ssklower 		iso_ifscrub(ifp, ia);
52737469Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
52837469Ssklower 			ifp->if_addrlist = ifa->ifa_next;
52937469Ssklower 		else {
53037469Ssklower 			while (ifa->ifa_next &&
53137469Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
53237469Ssklower 				    ifa = ifa->ifa_next;
53337469Ssklower 			if (ifa->ifa_next)
53437469Ssklower 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
53537469Ssklower 			else
53637469Ssklower 				printf("Couldn't unlink isoifaddr from ifp\n");
53737469Ssklower 		}
53837469Ssklower 		oia = ia;
53937469Ssklower 		if (oia == (ia = iso_ifaddr)) {
54037469Ssklower 			iso_ifaddr = ia->ia_next;
54137469Ssklower 		} else {
54237469Ssklower 			while (ia->ia_next && (ia->ia_next != oia)) {
54337469Ssklower 				ia = ia->ia_next;
54436384Ssklower 			}
54537469Ssklower 			if (ia->ia_next)
54637469Ssklower 			    ia->ia_next = oia->ia_next;
54737469Ssklower 			else
54837469Ssklower 				printf("Didn't unlink isoifadr from list\n");
54936384Ssklower 		}
55037469Ssklower 		free((caddr_t)oia, M_IFADDR);
55137469Ssklower 		break;
55236384Ssklower 
55336384Ssklower 	default:
55436384Ssklower 		if (ifp == 0 || ifp->if_ioctl == 0)
55536384Ssklower 			return (EOPNOTSUPP);
55636384Ssklower 		return ((*ifp->if_ioctl)(ifp, cmd, data));
55736384Ssklower 	}
55837469Ssklower 	return (0);
55936384Ssklower }
56036384Ssklower 
56137469Ssklower /*
56237469Ssklower  * Delete any existing route for an interface.
56337469Ssklower  */
56437469Ssklower iso_ifscrub(ifp, ia)
56537469Ssklower 	register struct ifnet *ifp;
56637469Ssklower 	register struct iso_ifaddr *ia;
56737469Ssklower {
56843333Ssklower 	int nsellength = ia->ia_addr.siso_tlen;
56937469Ssklower 	if ((ia->ia_flags & IFA_ROUTE) == 0)
57037469Ssklower 		return;
57143333Ssklower 	ia->ia_addr.siso_tlen = 0;
57237469Ssklower 	if (ifp->if_flags & IFF_LOOPBACK)
57337469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
57437469Ssklower 	else if (ifp->if_flags & IFF_POINTOPOINT)
57537469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
57637469Ssklower 	else {
57737469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
57837469Ssklower 	}
57943333Ssklower 	ia->ia_addr.siso_tlen = nsellength;
58037469Ssklower 	ia->ia_flags &= ~IFA_ROUTE;
58137469Ssklower }
58237469Ssklower 
58337469Ssklower /*
58437469Ssklower  * Initialize an interface's internet address
58537469Ssklower  * and routing table entry.
58637469Ssklower  */
58737469Ssklower iso_ifinit(ifp, ia, siso, scrub)
58837469Ssklower 	register struct ifnet *ifp;
58937469Ssklower 	register struct iso_ifaddr *ia;
59037469Ssklower 	struct sockaddr_iso *siso;
59137469Ssklower {
59237469Ssklower 	struct sockaddr_iso oldaddr;
59343333Ssklower 	int s = splimp(), error, nsellength;
59437469Ssklower 
59537469Ssklower 	oldaddr = ia->ia_addr;
59637469Ssklower 	ia->ia_addr = *siso;
59737469Ssklower 	/*
59837469Ssklower 	 * Give the interface a chance to initialize
59937469Ssklower 	 * if this is its first address,
60037469Ssklower 	 * and to validate the address if necessary.
60137469Ssklower 	 */
60237469Ssklower 	if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
60337469Ssklower 		splx(s);
60437469Ssklower 		ia->ia_addr = oldaddr;
60537469Ssklower 		return (error);
60637469Ssklower 	}
60737469Ssklower 	if (scrub) {
60837469Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
60937469Ssklower 		iso_ifscrub(ifp, ia);
61037469Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
61137469Ssklower 	}
61243333Ssklower 	/* XXX -- The following is here temporarily out of laziness
61343333Ssklower 	   in not changing every ethernet driver's if_ioctl routine */
61443333Ssklower 	if (ifp->if_output == ether_output) {
61543333Ssklower 		ia->ia_ifa.ifa_rtrequest = llc_rtrequest;
61643333Ssklower 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
61743333Ssklower 		ia->ia_ifa.ifa_llinfolen = sizeof(struct llinfo_llc);
61843333Ssklower 	}
61937469Ssklower 	/*
62037469Ssklower 	 * Add route for the network.
62137469Ssklower 	 */
62243333Ssklower 	nsellength = ia->ia_addr.siso_tlen;
62343333Ssklower 	ia->ia_addr.siso_tlen = 0;
62437469Ssklower 	if (ifp->if_flags & IFF_LOOPBACK) {
62537469Ssklower 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
62640894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
62737469Ssklower 	} else if (ifp->if_flags & IFF_POINTOPOINT &&
62837469Ssklower 		 ia->ia_dstaddr.siso_family == AF_ISO)
62940894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
63037469Ssklower 	else {
63140894Ssklower 		rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
63240894Ssklower 			ia->ia_ifa.ifa_netmask);
63349936Ssklower 		ia->ia_dstaddr.siso_nlen =
63449936Ssklower 			min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6));
63540894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
63637469Ssklower 	}
63743333Ssklower 	ia->ia_addr.siso_tlen = nsellength;
63837469Ssklower 	ia->ia_flags |= IFA_ROUTE;
63937469Ssklower 	splx(s);
64040894Ssklower 	return (error);
64137469Ssklower }
64237469Ssklower #ifdef notdef
64337469Ssklower 
64436384Ssklower struct ifaddr *
64536384Ssklower iso_ifwithidi(addr)
64636384Ssklower 	register struct sockaddr *addr;
64736384Ssklower {
64836384Ssklower 	register struct ifnet *ifp;
64936384Ssklower 	register struct ifaddr *ifa;
65036384Ssklower 	register u_int af = addr->sa_family;
65136384Ssklower 
65236384Ssklower 	if (af != AF_ISO)
65336384Ssklower 		return (0);
65436384Ssklower 	IFDEBUG(D_ROUTE)
65536384Ssklower 		printf(">>> iso_ifwithidi addr\n");
65636384Ssklower 		dump_isoaddr( (struct sockaddr_iso *)(addr));
65736384Ssklower 		printf("\n");
65836384Ssklower 	ENDDEBUG
65936384Ssklower 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
66036384Ssklower 		IFDEBUG(D_ROUTE)
66136384Ssklower 			printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
66236384Ssklower 		ENDDEBUG
66336384Ssklower 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
66436384Ssklower 			IFDEBUG(D_ROUTE)
66536384Ssklower 				printf("iso_ifwithidi address ");
66637469Ssklower 				dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr));
66736384Ssklower 			ENDDEBUG
66837469Ssklower 			if (ifa->ifa_addr->sa_family != addr->sa_family)
66936384Ssklower 				continue;
67036384Ssklower 
67136384Ssklower #define	IFA_SIS(ifa)\
67237469Ssklower 	((struct sockaddr_iso *)((ifa)->ifa_addr))
67336384Ssklower 
67436384Ssklower 			IFDEBUG(D_ROUTE)
67536384Ssklower 				printf(" af same, args to iso_eqtype:\n");
67636384Ssklower 				printf("0x%x ", IFA_SIS(ifa)->siso_addr);
67736384Ssklower 				printf(" 0x%x\n",
67836384Ssklower 				&(((struct sockaddr_iso *)addr)->siso_addr));
67936384Ssklower 			ENDDEBUG
68036384Ssklower 
68136384Ssklower 			if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr),
68236384Ssklower 				&(((struct sockaddr_iso *)addr)->siso_addr))) {
68336384Ssklower 				IFDEBUG(D_ROUTE)
68436384Ssklower 					printf("ifa_ifwithidi: ifa found\n");
68536384Ssklower 				ENDDEBUG
68636384Ssklower 				return (ifa);
68736384Ssklower 			}
68836384Ssklower 			IFDEBUG(D_ROUTE)
68936384Ssklower 				printf(" iso_eqtype failed\n");
69036384Ssklower 			ENDDEBUG
69136384Ssklower 		}
69236384Ssklower 	}
69336384Ssklower 	return ((struct ifaddr *)0);
69436384Ssklower }
69536384Ssklower 
69637469Ssklower #endif notdef
69736384Ssklower /*
69836384Ssklower  * FUNCTION:		iso_ck_addr
69936384Ssklower  *
70036384Ssklower  * PURPOSE:			return true if the iso_addr passed is
70136384Ssklower  *					within the legal size limit for an iso address.
70236384Ssklower  *
70336384Ssklower  * RETURNS:			true or false
70436384Ssklower  *
70536384Ssklower  * SIDE EFFECTS:
70636384Ssklower  *
70736384Ssklower  */
70836384Ssklower iso_ck_addr(isoa)
70936384Ssklower struct iso_addr	*isoa;	/* address to check */
71036384Ssklower {
71136384Ssklower 	return (isoa->isoa_len <= 20);
71236384Ssklower 
71336384Ssklower }
71436384Ssklower 
71537469Ssklower #ifdef notdef
71636384Ssklower /*
71736384Ssklower  * FUNCTION:		iso_eqtype
71836384Ssklower  *
71936384Ssklower  * PURPOSE:			Determine if two iso addresses are of the same type.
72036384Ssklower  *  This is flaky.  Really we should consider all type 47 addrs to be the
72136384Ssklower  *  same - but there do exist different structures for 47 addrs.
72236384Ssklower  *  Gosip adds a 3rd.
72336384Ssklower  *
72436384Ssklower  * RETURNS:			true if the addresses are the same type
72536384Ssklower  *
72636384Ssklower  * SIDE EFFECTS:
72736384Ssklower  *
72836384Ssklower  * NOTES:			By type, I mean rfc986, t37, or osinet
72936384Ssklower  *
73036384Ssklower  *					This will first compare afis. If they match, then
73136384Ssklower  *					if the addr is not t37, the idis must be compared.
73236384Ssklower  */
73336384Ssklower iso_eqtype(isoaa, isoab)
73436384Ssklower struct iso_addr	*isoaa;		/* first addr to check */
73536384Ssklower struct iso_addr	*isoab;		/* other addr to check */
73636384Ssklower {
73736384Ssklower 	if (isoaa->isoa_afi == isoab->isoa_afi) {
73836384Ssklower 		if (isoaa->isoa_afi == AFI_37)
73936384Ssklower 			return(1);
74036384Ssklower 		else
74136384Ssklower 			return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
74236384Ssklower 	}
74336384Ssklower 	return(0);
74436384Ssklower }
74537469Ssklower #endif notdef
74636384Ssklower /*
74737469Ssklower  * FUNCTION:		iso_localifa()
74836384Ssklower  *
74937469Ssklower  * PURPOSE:			Find an interface addresss having a given destination
75037469Ssklower  *					or at least matching the net.
75136384Ssklower  *
75236384Ssklower  * RETURNS:			ptr to an interface address
75336384Ssklower  *
75436384Ssklower  * SIDE EFFECTS:
75536384Ssklower  *
75636384Ssklower  * NOTES:
75736384Ssklower  */
75836384Ssklower struct iso_ifaddr *
75937469Ssklower iso_localifa(siso)
76037469Ssklower 	register struct sockaddr_iso *siso;
76136384Ssklower {
76236384Ssklower 	register struct iso_ifaddr *ia;
76337469Ssklower 	register char *cp1, *cp2, *cp3;
76437469Ssklower 	register struct ifnet *ifp;
76537469Ssklower 	struct iso_ifaddr *ia_maybe = 0;
76637469Ssklower 	/*
76737469Ssklower 	 * We make one pass looking for both net matches and an exact
76837469Ssklower 	 * dst addr.
76937469Ssklower 	 */
77037469Ssklower 	for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
77137469Ssklower 		if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
77237469Ssklower 			continue;
77337469Ssklower 		if (ifp->if_flags & IFF_POINTOPOINT) {
77437469Ssklower 			if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
77537469Ssklower 				SAME_ISOADDR(&ia->ia_dstaddr, siso))
77637469Ssklower 				return (ia);
77737469Ssklower 			else
77837469Ssklower 				if (SAME_ISOADDR(&ia->ia_addr, siso))
77937469Ssklower 					ia_maybe = ia;
78037469Ssklower 			continue;
78137469Ssklower 		}
78237469Ssklower 		if (ia->ia_sockmask.siso_len) {
78337469Ssklower 			char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask;
78437469Ssklower 			cp1 = ia->ia_sockmask.siso_data;
78537469Ssklower 			cp2 = siso->siso_data;
78637469Ssklower 			cp3 = ia->ia_addr.siso_data;
78739936Ssklower 			while (cp1 < cplim)
78837469Ssklower 				if (*cp1++ & (*cp2++ ^ *cp3++))
78937469Ssklower 					goto next;
79037469Ssklower 			ia_maybe = ia;
79137469Ssklower 		}
79237469Ssklower 		if (SAME_ISOADDR(&ia->ia_addr, siso))
79337469Ssklower 			return ia;
79437469Ssklower 	next:;
79537469Ssklower 	}
79637469Ssklower 	return ia_maybe;
79736384Ssklower }
79836384Ssklower 
79947272Ssklower #ifdef	TPCONS
80036384Ssklower #include "cons.h"
80147272Ssklower #endif	TPCONS
80236384Ssklower /*
80336384Ssklower  * FUNCTION:		iso_nlctloutput
80436384Ssklower  *
80536384Ssklower  * PURPOSE:			Set options at the network level
80636384Ssklower  *
80736384Ssklower  * RETURNS:			E*
80836384Ssklower  *
80936384Ssklower  * SIDE EFFECTS:
81036384Ssklower  *
81136384Ssklower  * NOTES:			This could embody some of the functions of
81236384Ssklower  *					rclnp_ctloutput and cons_ctloutput.
81336384Ssklower  */
81436384Ssklower iso_nlctloutput(cmd, optname, pcb, m)
81536384Ssklower int			cmd;		/* command:set or get */
81636384Ssklower int			optname;	/* option of interest */
81736384Ssklower caddr_t		pcb;		/* nl pcb */
81836384Ssklower struct mbuf	*m;			/* data for set, buffer for get */
81936384Ssklower {
82036384Ssklower 	struct isopcb	*isop = (struct isopcb *)pcb;
82136384Ssklower 	int				error = 0;	/* return value */
82236384Ssklower 	caddr_t			data;		/* data for option */
82336384Ssklower 	int				data_len;	/* data's length */
82436384Ssklower 
82536384Ssklower 	IFDEBUG(D_ISO)
82636384Ssklower 		printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n",
82736384Ssklower 			cmd, optname, pcb, m);
82836384Ssklower 	ENDDEBUG
82936384Ssklower 
83036384Ssklower 	if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
83136384Ssklower 		return(EOPNOTSUPP);
83236384Ssklower 
83336384Ssklower 	data = mtod(m, caddr_t);
83436384Ssklower 	data_len = (m)->m_len;
83536384Ssklower 
83636384Ssklower 	IFDEBUG(D_ISO)
83736384Ssklower 		printf("iso_nlctloutput: data is:\n");
83836384Ssklower 		dump_buf(data, data_len);
83936384Ssklower 	ENDDEBUG
84036384Ssklower 
84136384Ssklower 	switch (optname) {
84236384Ssklower 
84347272Ssklower #ifdef	TPCONS
84436384Ssklower 		case CONSOPT_X25CRUD:
84536384Ssklower 			if (cmd == PRCO_GETOPT) {
84636384Ssklower 				error = EOPNOTSUPP;
84736384Ssklower 				break;
84836384Ssklower 			}
84936384Ssklower 
85036384Ssklower 			if (data_len > MAXX25CRUDLEN) {
85136384Ssklower 				error = EINVAL;
85236384Ssklower 				break;
85336384Ssklower 			}
85436384Ssklower 
85536384Ssklower 			IFDEBUG(D_ISO)
85636384Ssklower 				printf("iso_nlctloutput: setting x25 crud\n");
85736384Ssklower 			ENDDEBUG
85836384Ssklower 
85937469Ssklower 			bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len);
86036384Ssklower 			isop->isop_x25crud_len = data_len;
86136384Ssklower 			break;
86247272Ssklower #endif	TPCONS
86336384Ssklower 
86436384Ssklower 		default:
86536384Ssklower 			error = EOPNOTSUPP;
86636384Ssklower 	}
86736384Ssklower 
86836384Ssklower 	return error;
86936384Ssklower }
87036384Ssklower #endif ISO
87136384Ssklower 
87236384Ssklower #ifdef ARGO_DEBUG
87336384Ssklower 
87436384Ssklower /*
87536384Ssklower  * FUNCTION:		dump_isoaddr
87636384Ssklower  *
87736384Ssklower  * PURPOSE:			debugging
87836384Ssklower  *
87936384Ssklower  * RETURNS:			nada
88036384Ssklower  *
88136384Ssklower  */
88236384Ssklower dump_isoaddr(s)
88336384Ssklower 	struct sockaddr_iso *s;
88436384Ssklower {
88537469Ssklower 	char *clnp_saddr_isop();
88636384Ssklower 	register int i;
88736384Ssklower 
88836384Ssklower 	if( s->siso_family == AF_ISO) {
88937469Ssklower 		printf("ISO address: suffixlen %d, %s\n",
89038841Ssklower 			s->siso_tlen, clnp_saddr_isop(s));
89136384Ssklower 	} else if( s->siso_family == AF_INET) {
89236384Ssklower 		/* hack */
89336384Ssklower 		struct sockaddr_in *sin = (struct sockaddr_in *)s;
89436384Ssklower 
89536384Ssklower 		printf("%d.%d.%d.%d: %d",
89636384Ssklower 			(sin->sin_addr.s_addr>>24)&0xff,
89736384Ssklower 			(sin->sin_addr.s_addr>>16)&0xff,
89836384Ssklower 			(sin->sin_addr.s_addr>>8)&0xff,
89936384Ssklower 			(sin->sin_addr.s_addr)&0xff,
90036384Ssklower 			sin->sin_port);
90136384Ssklower 	}
90236384Ssklower }
90336384Ssklower 
90436384Ssklower #endif ARGO_DEBUG
905