xref: /csrg-svn/sys/netiso/iso.c (revision 50232)
149268Sbostic /*-
249268Sbostic  * Copyright (c) 1991 The Regents of the University of California.
349268Sbostic  * All rights reserved.
449268Sbostic  *
549268Sbostic  * %sccs.include.redist.c%
649268Sbostic  *
7*50232Ssklower  *	@(#)iso.c	7.14 (Berkeley) 06/27/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  */
8337469Ssklower struct radix_node_head *iso_rnhead;
8436384Ssklower iso_init()
8536384Ssklower {
8637469Ssklower 	static iso_init_done;
8736384Ssklower 
8837469Ssklower 	if (iso_init_done == 0) {
8937469Ssklower 		iso_init_done++;
9049936Ssklower 		rn_inithead(&iso_rnhead, 48, AF_ISO);
9137469Ssklower 	}
9236384Ssklower }
9336384Ssklower 
9436384Ssklower /*
9536384Ssklower  * FUNCTION:		iso_addrmatch1
9636384Ssklower  *
9736384Ssklower  * PURPOSE:			decide if the two iso_addrs passed are equal
9836384Ssklower  *
9936384Ssklower  * RETURNS:			true if the addrs match, false if they do not
10036384Ssklower  *
10136384Ssklower  * SIDE EFFECTS:
10236384Ssklower  *
10336384Ssklower  * NOTES:
10436384Ssklower  */
10536384Ssklower iso_addrmatch1(isoaa, isoab)
10637469Ssklower register struct iso_addr *isoaa, *isoab;		/* addresses to check */
10736384Ssklower {
10837469Ssklower 	u_int	compare_len;
10936384Ssklower 
11036384Ssklower 	IFDEBUG(D_ROUTE)
11136384Ssklower 		printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len,
11236384Ssklower 			isoab->isoa_len);
11336384Ssklower 		printf("a:\n");
11437469Ssklower 		dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len);
11536384Ssklower 		printf("b:\n");
11637469Ssklower 		dump_buf(isoab->isoa_genaddr, isoab->isoa_len);
11736384Ssklower 	ENDDEBUG
11836384Ssklower 
11936384Ssklower 	if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) {
12036384Ssklower 		IFDEBUG(D_ROUTE)
12136384Ssklower 			printf("iso_addrmatch1: returning false because of lengths\n");
12236384Ssklower 		ENDDEBUG
12336384Ssklower 		return 0;
12436384Ssklower 	}
12536384Ssklower 
12637469Ssklower #ifdef notdef
12736384Ssklower 	/* TODO : generalize this to all afis with masks */
12836384Ssklower 	if(	isoaa->isoa_afi == AFI_37 ) {
12936384Ssklower 		/* must not compare 2 least significant digits, or for
13036384Ssklower 		 * that matter, the DSP
13136384Ssklower 		 */
13236384Ssklower 		compare_len = ADDR37_IDI_LEN - 1;
13336384Ssklower 	}
13437469Ssklower #endif
13536384Ssklower 
13636384Ssklower 	IFDEBUG(D_ROUTE)
13736384Ssklower 		int i;
13836384Ssklower 		char *a, *b;
13936384Ssklower 
14037469Ssklower 		a = isoaa->isoa_genaddr;
14137469Ssklower 		b = isoab->isoa_genaddr;
14236384Ssklower 
14336384Ssklower 		for (i=0; i<compare_len; i++) {
14436384Ssklower 			printf("<%x=%x>", a[i]&0xff, b[i]&0xff);
14536384Ssklower 			if (a[i] != b[i]) {
14636384Ssklower 				printf("\naddrs are not equal at byte %d\n", i);
14736384Ssklower 				return(0);
14836384Ssklower 			}
14936384Ssklower 		}
15036384Ssklower 		printf("\n");
15136384Ssklower 		printf("addrs are equal\n");
15236384Ssklower 		return (1);
15336384Ssklower 	ENDDEBUG
15437469Ssklower 	return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len));
15536384Ssklower }
15636384Ssklower 
15736384Ssklower /*
15836384Ssklower  * FUNCTION:		iso_addrmatch
15936384Ssklower  *
16036384Ssklower  * PURPOSE:			decide if the two sockadrr_isos passed are equal
16136384Ssklower  *
16236384Ssklower  * RETURNS:			true if the addrs match, false if they do not
16336384Ssklower  *
16436384Ssklower  * SIDE EFFECTS:
16536384Ssklower  *
16636384Ssklower  * NOTES:
16736384Ssklower  */
16836384Ssklower iso_addrmatch(sisoa, sisob)
16936384Ssklower struct sockaddr_iso	*sisoa, *sisob;		/* addresses to check */
17036384Ssklower {
17136384Ssklower 	return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr));
17236384Ssklower }
17337469Ssklower #ifdef notdef
17436384Ssklower /*
17536384Ssklower  * FUNCTION:		iso_netmatch
17636384Ssklower  *
17736384Ssklower  * PURPOSE:			similar to iso_addrmatch but takes sockaddr_iso
17836384Ssklower  *					as argument.
17936384Ssklower  *
18036384Ssklower  * RETURNS:			true if same net, false if not
18136384Ssklower  *
18236384Ssklower  * SIDE EFFECTS:
18336384Ssklower  *
18436384Ssklower  * NOTES:
18536384Ssklower  */
18636384Ssklower iso_netmatch(sisoa, sisob)
18736384Ssklower struct sockaddr_iso *sisoa, *sisob;
18836384Ssklower {
18936384Ssklower 	u_char			bufa[sizeof(struct sockaddr_iso)];
19036384Ssklower 	u_char			bufb[sizeof(struct sockaddr_iso)];
19136384Ssklower 	register int	lena, lenb;
19236384Ssklower 
19336384Ssklower 	lena = iso_netof(&sisoa->siso_addr, bufa);
19436384Ssklower 	lenb = iso_netof(&sisob->siso_addr, bufb);
19536384Ssklower 
19636384Ssklower 	IFDEBUG(D_ROUTE)
19736384Ssklower 		printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb);
19836384Ssklower 		printf("a:\n");
19936384Ssklower 		dump_buf(bufa, lena);
20036384Ssklower 		printf("b:\n");
20136384Ssklower 		dump_buf(bufb, lenb);
20236384Ssklower 	ENDDEBUG
20336384Ssklower 
20436384Ssklower 	return ((lena == lenb) && (!bcmp(bufa, bufb, lena)));
20536384Ssklower }
20637469Ssklower #endif notdef
20736384Ssklower 
20836384Ssklower /*
20936384Ssklower  * FUNCTION:		iso_hashchar
21036384Ssklower  *
21136384Ssklower  * PURPOSE:			Hash all character in the buffer specified into
21236384Ssklower  *					a long. Return the long.
21336384Ssklower  *
21436384Ssklower  * RETURNS:			The hash value.
21536384Ssklower  *
21636384Ssklower  * SIDE EFFECTS:
21736384Ssklower  *
21836384Ssklower  * NOTES:			The hash is achieved by exclusive ORing 4 byte
21936384Ssklower  *					quantities.
22036384Ssklower  */
22136384Ssklower u_long
22236384Ssklower iso_hashchar(buf, len)
22336384Ssklower register caddr_t	buf;		/* buffer to pack from */
22436384Ssklower register int		len;		/* length of buffer */
22536384Ssklower {
22636384Ssklower 	register u_long	h = 0;
22736384Ssklower 	register int	i;
22836384Ssklower 
22936384Ssklower 	for (i=0; i<len; i+=4) {
23036384Ssklower 		register u_long	l = 0;
23136384Ssklower 
23236384Ssklower 		if ((len - i) < 4) {
23336384Ssklower 			/* buffer not multiple of 4 */
23436384Ssklower 			switch (len - i) {
23536384Ssklower 				case 3:
23636384Ssklower 					l |= buf[i+2] << 8;
23736384Ssklower 				case 2:
23836384Ssklower 					l |= buf[i+1] << 16;
23936384Ssklower 				case 1:
24036384Ssklower 					l |= buf[i] << 24;
24136384Ssklower 					break;
24236384Ssklower 				default:
24336384Ssklower 					printf("iso_hashchar: unexpected value x%x\n", len - i);
24436384Ssklower 					break;
24536384Ssklower 			}
24636384Ssklower 		} else {
24736384Ssklower 			l |= buf[i] << 24;
24836384Ssklower 			l |= buf[i+1] << 16;
24936384Ssklower 			l |= buf[i+2] << 8;
25036384Ssklower 			l |= buf[i+3];
25136384Ssklower 		}
25236384Ssklower 
25336384Ssklower 		h ^= l;
25436384Ssklower 	}
25536384Ssklower 
25636384Ssklower 	h ^= (u_long) (len % 4);
25736384Ssklower 
25836384Ssklower 	return(h);
25936384Ssklower }
26037469Ssklower #ifdef notdef
26136384Ssklower /*
26236384Ssklower  * FUNCTION:		iso_hash
26336384Ssklower  *
26436384Ssklower  * PURPOSE:			Fill in fields of afhash structure based upon addr passed.
26536384Ssklower  *
26636384Ssklower  * RETURNS:			none
26736384Ssklower  *
26836384Ssklower  * SIDE EFFECTS:
26936384Ssklower  *
27036384Ssklower  * NOTES:
27136384Ssklower  */
27236384Ssklower iso_hash(siso, hp)
27336384Ssklower struct sockaddr_iso	*siso;		/* address to perform hash on */
27436384Ssklower struct afhash		*hp;		/* RETURN: hash info here */
27536384Ssklower {
27636384Ssklower 	u_long			buf[sizeof(struct sockaddr_iso)+1/4];
27736384Ssklower 	register int	bufsize;
27836384Ssklower 
27936384Ssklower 
28036384Ssklower 	bzero(buf, sizeof(buf));
28136384Ssklower 
28236384Ssklower 	bufsize = iso_netof(&siso->siso_addr, buf);
28336384Ssklower 	hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize);
28436384Ssklower 
28536384Ssklower 	IFDEBUG(D_ROUTE)
28636384Ssklower 		printf("iso_hash: iso_netof: bufsize = %d\n", bufsize);
28736384Ssklower 	ENDDEBUG
28836384Ssklower 
28936384Ssklower 	hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr,
29036384Ssklower 		siso->siso_addr.isoa_len);
29136384Ssklower 
29236384Ssklower 	IFDEBUG(D_ROUTE)
29336384Ssklower 		printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n",
29436384Ssklower 			clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash,
29536384Ssklower 			hp->afh_hosthash);
29636384Ssklower 	ENDDEBUG
29736384Ssklower }
29836384Ssklower /*
29936384Ssklower  * FUNCTION:		iso_netof
30036384Ssklower  *
30136384Ssklower  * PURPOSE:			Extract the network portion of the iso address.
30236384Ssklower  *					The network portion of the iso address varies depending
30336384Ssklower  *					on the type of address. The network portion of the
30436384Ssklower  *					address will include the IDP. The network portion is:
30536384Ssklower  *
30636384Ssklower  *						TYPE			DESC
30736384Ssklower  *					t37					The AFI and x.121 (IDI)
30836384Ssklower  *					osinet				The AFI, orgid, snetid
30936384Ssklower  *					rfc986				The AFI, vers and network part of
31036384Ssklower  *										internet address.
31136384Ssklower  *
31236384Ssklower  * RETURNS:			number of bytes placed into buf.
31336384Ssklower  *
31436384Ssklower  * SIDE EFFECTS:
31536384Ssklower  *
31636384Ssklower  * NOTES:			Buf is assumed to be big enough
31736384Ssklower  */
31836384Ssklower iso_netof(isoa, buf)
31936384Ssklower struct iso_addr	*isoa;		/* address */
32036384Ssklower caddr_t			buf;		/* RESULT: network portion of address here */
32136384Ssklower {
32236384Ssklower 	u_int		len = 1;	/* length of afi */
32336384Ssklower 
32436384Ssklower 	switch (isoa->isoa_afi) {
32536384Ssklower 		case AFI_37:
32636384Ssklower 			/*
32736384Ssklower 			 * Due to classic x.25 tunnel vision, there is no
32836384Ssklower 			 * net portion of an x.121 address.  For our purposes
32936384Ssklower 			 * the AFI will do, so that all x.25 -type addresses
33036384Ssklower 			 * map to the single x.25 SNPA. (Cannot have more than
33136384Ssklower 			 * one, obviously).
33236384Ssklower 			 */
33336384Ssklower 
33436384Ssklower 			break;
33536384Ssklower 
33636384Ssklower /* 		case AFI_OSINET:*/
33736384Ssklower 		case AFI_RFC986: {
33836384Ssklower 			u_short	idi;	/* value of idi */
33936384Ssklower 
34036384Ssklower 			/* osinet and rfc986 have idi in the same place */
34136384Ssklower 			CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi);
34236384Ssklower 
34336384Ssklower 			if (idi == IDI_OSINET)
34436384Ssklower /*
34536384Ssklower  *	Network portion of OSINET address can only be the IDI. Clearly,
34636384Ssklower  *	with one x25 interface, one could get to several orgids, and
34736384Ssklower  *	several snetids.
34836384Ssklower 				len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN +
34936384Ssklower 						OVLOSINET_SNETID_LEN);
35036384Ssklower  */
35136384Ssklower 				len += ADDROSINET_IDI_LEN;
35236384Ssklower 			else if (idi == IDI_RFC986) {
35336384Ssklower 				u_long				inetaddr;
35436384Ssklower 				struct ovl_rfc986	*o986 = (struct ovl_rfc986 *)isoa;
35536384Ssklower 
35636384Ssklower 				/* bump len to include idi and version (1 byte) */
35736384Ssklower 				len += ADDRRFC986_IDI_LEN + 1;
35836384Ssklower 
35936384Ssklower 				/* get inet addr long aligned */
36036384Ssklower 				bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr));
36136384Ssklower 				inetaddr = ntohl(inetaddr);	/* convert to host byte order */
36236384Ssklower 
36336384Ssklower 				IFDEBUG(D_ROUTE)
36436384Ssklower 					printf("iso_netof: isoa ");
36536384Ssklower 					dump_buf(isoa, sizeof(*isoa));
36636384Ssklower 					printf("iso_netof: inetaddr 0x%x ", inetaddr);
36736384Ssklower 				ENDDEBUG
36836384Ssklower 
36936384Ssklower 				/* bump len by size of network portion of inet address */
37036384Ssklower 				if (IN_CLASSA(inetaddr)) {
37136384Ssklower 					len += 4-IN_CLASSA_NSHIFT/8;
37236384Ssklower 					IFDEBUG(D_ROUTE)
37336384Ssklower 						printf("iso_netof: class A net len is now %d\n", len);
37436384Ssklower 					ENDDEBUG
37536384Ssklower 				} else if (IN_CLASSB(inetaddr)) {
37636384Ssklower 					len += 4-IN_CLASSB_NSHIFT/8;
37736384Ssklower 					IFDEBUG(D_ROUTE)
37836384Ssklower 						printf("iso_netof: class B net len is now %d\n", len);
37936384Ssklower 					ENDDEBUG
38036384Ssklower 				} else {
38136384Ssklower 					len += 4-IN_CLASSC_NSHIFT/8;
38236384Ssklower 					IFDEBUG(D_ROUTE)
38336384Ssklower 						printf("iso_netof: class C net len is now %d\n", len);
38436384Ssklower 					ENDDEBUG
38536384Ssklower 				}
38636384Ssklower 			} else
38736384Ssklower 				len = 0;
38836384Ssklower 		} break;
38936384Ssklower 
39036384Ssklower 		default:
39136384Ssklower 			len = 0;
39236384Ssklower 	}
39336384Ssklower 
39436384Ssklower 	bcopy((caddr_t)isoa, buf, len);
39536384Ssklower 	IFDEBUG(D_ROUTE)
39636384Ssklower 		printf("in_netof: isoa ");
39736384Ssklower 		dump_buf(isoa, len);
39836384Ssklower 		printf("in_netof: net ");
39936384Ssklower 		dump_buf(buf, len);
40036384Ssklower 	ENDDEBUG
40136384Ssklower 	return len;
40236384Ssklower }
40337469Ssklower #endif notdef
40436384Ssklower /*
40537469Ssklower  * Generic iso control operations (ioctl's).
40637469Ssklower  * Ifp is 0 if not an interface-specific ioctl.
40736384Ssklower  */
40837469Ssklower /* ARGSUSED */
40936384Ssklower iso_control(so, cmd, data, ifp)
41037469Ssklower 	struct socket *so;
41137469Ssklower 	int cmd;
41237469Ssklower 	caddr_t data;
41337469Ssklower 	register struct ifnet *ifp;
41436384Ssklower {
41537469Ssklower 	register struct iso_ifreq *ifr = (struct iso_ifreq *)data;
41637469Ssklower 	register struct iso_ifaddr *ia = 0;
41737469Ssklower 	register struct ifaddr *ifa;
41837469Ssklower 	struct iso_ifaddr *oia;
41937469Ssklower 	struct iso_aliasreq *ifra = (struct iso_aliasreq *)data;
42037469Ssklower 	int error, hostIsNew, maskIsNew;
42136384Ssklower 
42237469Ssklower 	/*
42337469Ssklower 	 * Find address for this interface, if it exists.
42437469Ssklower 	 */
42537469Ssklower 	if (ifp)
42637469Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
42737469Ssklower 			if (ia->ia_ifp == ifp)
42837469Ssklower 				break;
42936384Ssklower 
43036384Ssklower 	switch (cmd) {
43137469Ssklower 
43237469Ssklower 	case SIOCAIFADDR_ISO:
43337469Ssklower 	case SIOCDIFADDR_ISO:
43437469Ssklower 		if (ifra->ifra_addr.siso_family == AF_ISO)
43537469Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
43637469Ssklower 			if (ia->ia_ifp == ifp  &&
43737469Ssklower 			    SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
43837469Ssklower 				break;
43937469Ssklower 		}
440*50232Ssklower 		if ((so->so_state & SS_PRIV) == 0)
441*50232Ssklower 			return (EPERM);
44236384Ssklower 		if (ifp == 0)
44337469Ssklower 			panic("iso_control");
44437469Ssklower 		if (ia == (struct iso_ifaddr *)0) {
44537469Ssklower 			struct iso_ifaddr *nia;
44637469Ssklower 			if (cmd == SIOCDIFADDR_ISO)
44737469Ssklower 				return (EADDRNOTAVAIL);
44837469Ssklower 			MALLOC(nia, struct iso_ifaddr *, sizeof(*nia),
44937469Ssklower 				       M_IFADDR, M_WAITOK);
45037469Ssklower 			if (nia == (struct iso_ifaddr *)0)
45137469Ssklower 				return (ENOBUFS);
45237469Ssklower 			bzero((caddr_t)nia, sizeof(*nia));
45337469Ssklower 			if (ia = iso_ifaddr) {
45437469Ssklower 				for ( ; ia->ia_next; ia = ia->ia_next)
45537469Ssklower 					;
45637469Ssklower 				ia->ia_next = nia;
45737469Ssklower 			} else
45837469Ssklower 				iso_ifaddr = nia;
45937469Ssklower 			ia = nia;
46037469Ssklower 			if (ifa = ifp->if_addrlist) {
46137469Ssklower 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
46237469Ssklower 					;
46337469Ssklower 				ifa->ifa_next = (struct ifaddr *) ia;
46437469Ssklower 			} else
46537469Ssklower 				ifp->if_addrlist = (struct ifaddr *) ia;
46637469Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
46737469Ssklower 			ia->ia_ifa.ifa_dstaddr
46837469Ssklower 					= (struct sockaddr *)&ia->ia_dstaddr;
46937469Ssklower 			ia->ia_ifa.ifa_netmask
47037469Ssklower 					= (struct sockaddr *)&ia->ia_sockmask;
47137469Ssklower 			ia->ia_ifp = ifp;
47237469Ssklower 			if (ifp != &loif)
47337469Ssklower 				iso_interfaces++;
47437469Ssklower 		}
47537469Ssklower 		break;
47636384Ssklower 
47737469Ssklower #define cmdbyte(x)	(((x) >> 8) & 0xff)
47837469Ssklower 	default:
47937469Ssklower 		if (cmdbyte(cmd) == 'a')
480*50232Ssklower 			return (snpac_ioctl(so, cmd, data));
48137469Ssklower 		if (ia == (struct iso_ifaddr *)0)
48237469Ssklower 			return (EADDRNOTAVAIL);
48337469Ssklower 		break;
48437469Ssklower 	}
48537469Ssklower 	switch (cmd) {
48636384Ssklower 
48737469Ssklower 	case SIOCGIFADDR_ISO:
48837469Ssklower 		ifr->ifr_Addr = ia->ia_addr;
48937469Ssklower 		break;
49036384Ssklower 
49137469Ssklower 	case SIOCGIFDSTADDR_ISO:
49237469Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
49337469Ssklower 			return (EINVAL);
49437469Ssklower 		ifr->ifr_Addr = ia->ia_dstaddr;
49537469Ssklower 		break;
49636384Ssklower 
49737469Ssklower 	case SIOCGIFNETMASK_ISO:
49837469Ssklower 		ifr->ifr_Addr = ia->ia_sockmask;
49937469Ssklower 		break;
50036384Ssklower 
50137469Ssklower 	case SIOCAIFADDR_ISO:
50243428Ssklower 		maskIsNew = 0; hostIsNew = 1; error = 0;
50337469Ssklower 		if (ia->ia_addr.siso_family == AF_ISO) {
50437469Ssklower 			if (ifra->ifra_addr.siso_len == 0) {
50537469Ssklower 				ifra->ifra_addr = ia->ia_addr;
50637469Ssklower 				hostIsNew = 0;
50737469Ssklower 			} else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
50837469Ssklower 				hostIsNew = 0;
50937469Ssklower 		}
51037469Ssklower 		if (ifra->ifra_mask.siso_len) {
51137469Ssklower 			iso_ifscrub(ifp, ia);
51237469Ssklower 			ia->ia_sockmask = ifra->ifra_mask;
51337469Ssklower 			maskIsNew = 1;
51437469Ssklower 		}
51537469Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
51637469Ssklower 		    (ifra->ifra_dstaddr.siso_family == AF_ISO)) {
51737469Ssklower 			iso_ifscrub(ifp, ia);
51837469Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
51937469Ssklower 			maskIsNew  = 1; /* We lie; but the effect's the same */
52037469Ssklower 		}
52137469Ssklower 		if (ifra->ifra_addr.siso_family == AF_ISO &&
52237469Ssklower 					    (hostIsNew || maskIsNew)) {
52337469Ssklower 			error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0);
52437469Ssklower 		}
52537469Ssklower 		if (ifra->ifra_snpaoffset)
52637469Ssklower 			ia->ia_snpaoffset = ifra->ifra_snpaoffset;
52737469Ssklower 		return (error);
52837469Ssklower 
52937469Ssklower 	case SIOCDIFADDR_ISO:
53037469Ssklower 		iso_ifscrub(ifp, ia);
53137469Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
53237469Ssklower 			ifp->if_addrlist = ifa->ifa_next;
53337469Ssklower 		else {
53437469Ssklower 			while (ifa->ifa_next &&
53537469Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
53637469Ssklower 				    ifa = ifa->ifa_next;
53737469Ssklower 			if (ifa->ifa_next)
53837469Ssklower 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
53937469Ssklower 			else
54037469Ssklower 				printf("Couldn't unlink isoifaddr from ifp\n");
54137469Ssklower 		}
54237469Ssklower 		oia = ia;
54337469Ssklower 		if (oia == (ia = iso_ifaddr)) {
54437469Ssklower 			iso_ifaddr = ia->ia_next;
54537469Ssklower 		} else {
54637469Ssklower 			while (ia->ia_next && (ia->ia_next != oia)) {
54737469Ssklower 				ia = ia->ia_next;
54836384Ssklower 			}
54937469Ssklower 			if (ia->ia_next)
55037469Ssklower 			    ia->ia_next = oia->ia_next;
55137469Ssklower 			else
55237469Ssklower 				printf("Didn't unlink isoifadr from list\n");
55336384Ssklower 		}
55437469Ssklower 		free((caddr_t)oia, M_IFADDR);
55537469Ssklower 		break;
55636384Ssklower 
55736384Ssklower 	default:
55836384Ssklower 		if (ifp == 0 || ifp->if_ioctl == 0)
55936384Ssklower 			return (EOPNOTSUPP);
56036384Ssklower 		return ((*ifp->if_ioctl)(ifp, cmd, data));
56136384Ssklower 	}
56237469Ssklower 	return (0);
56336384Ssklower }
56436384Ssklower 
56537469Ssklower /*
56637469Ssklower  * Delete any existing route for an interface.
56737469Ssklower  */
56837469Ssklower iso_ifscrub(ifp, ia)
56937469Ssklower 	register struct ifnet *ifp;
57037469Ssklower 	register struct iso_ifaddr *ia;
57137469Ssklower {
57243333Ssklower 	int nsellength = ia->ia_addr.siso_tlen;
57337469Ssklower 	if ((ia->ia_flags & IFA_ROUTE) == 0)
57437469Ssklower 		return;
57543333Ssklower 	ia->ia_addr.siso_tlen = 0;
57637469Ssklower 	if (ifp->if_flags & IFF_LOOPBACK)
57737469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
57837469Ssklower 	else if (ifp->if_flags & IFF_POINTOPOINT)
57937469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
58037469Ssklower 	else {
58137469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
58237469Ssklower 	}
58343333Ssklower 	ia->ia_addr.siso_tlen = nsellength;
58437469Ssklower 	ia->ia_flags &= ~IFA_ROUTE;
58537469Ssklower }
58637469Ssklower 
58737469Ssklower /*
58837469Ssklower  * Initialize an interface's internet address
58937469Ssklower  * and routing table entry.
59037469Ssklower  */
59137469Ssklower iso_ifinit(ifp, ia, siso, scrub)
59237469Ssklower 	register struct ifnet *ifp;
59337469Ssklower 	register struct iso_ifaddr *ia;
59437469Ssklower 	struct sockaddr_iso *siso;
59537469Ssklower {
59637469Ssklower 	struct sockaddr_iso oldaddr;
59743333Ssklower 	int s = splimp(), error, nsellength;
59837469Ssklower 
59937469Ssklower 	oldaddr = ia->ia_addr;
60037469Ssklower 	ia->ia_addr = *siso;
60137469Ssklower 	/*
60237469Ssklower 	 * Give the interface a chance to initialize
60337469Ssklower 	 * if this is its first address,
60437469Ssklower 	 * and to validate the address if necessary.
60537469Ssklower 	 */
60637469Ssklower 	if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
60737469Ssklower 		splx(s);
60837469Ssklower 		ia->ia_addr = oldaddr;
60937469Ssklower 		return (error);
61037469Ssklower 	}
61137469Ssklower 	if (scrub) {
61237469Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
61337469Ssklower 		iso_ifscrub(ifp, ia);
61437469Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
61537469Ssklower 	}
61643333Ssklower 	/* XXX -- The following is here temporarily out of laziness
61743333Ssklower 	   in not changing every ethernet driver's if_ioctl routine */
61843333Ssklower 	if (ifp->if_output == ether_output) {
61943333Ssklower 		ia->ia_ifa.ifa_rtrequest = llc_rtrequest;
62043333Ssklower 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
62143333Ssklower 		ia->ia_ifa.ifa_llinfolen = sizeof(struct llinfo_llc);
62243333Ssklower 	}
62337469Ssklower 	/*
62437469Ssklower 	 * Add route for the network.
62537469Ssklower 	 */
62643333Ssklower 	nsellength = ia->ia_addr.siso_tlen;
62743333Ssklower 	ia->ia_addr.siso_tlen = 0;
62837469Ssklower 	if (ifp->if_flags & IFF_LOOPBACK) {
62937469Ssklower 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
63040894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
63137469Ssklower 	} else if (ifp->if_flags & IFF_POINTOPOINT &&
63237469Ssklower 		 ia->ia_dstaddr.siso_family == AF_ISO)
63340894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
63437469Ssklower 	else {
63540894Ssklower 		rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
63640894Ssklower 			ia->ia_ifa.ifa_netmask);
63749936Ssklower 		ia->ia_dstaddr.siso_nlen =
63849936Ssklower 			min(ia->ia_addr.siso_nlen, (ia->ia_sockmask.siso_len - 6));
63940894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
64037469Ssklower 	}
64143333Ssklower 	ia->ia_addr.siso_tlen = nsellength;
64237469Ssklower 	ia->ia_flags |= IFA_ROUTE;
64337469Ssklower 	splx(s);
64440894Ssklower 	return (error);
64537469Ssklower }
64637469Ssklower #ifdef notdef
64737469Ssklower 
64836384Ssklower struct ifaddr *
64936384Ssklower iso_ifwithidi(addr)
65036384Ssklower 	register struct sockaddr *addr;
65136384Ssklower {
65236384Ssklower 	register struct ifnet *ifp;
65336384Ssklower 	register struct ifaddr *ifa;
65436384Ssklower 	register u_int af = addr->sa_family;
65536384Ssklower 
65636384Ssklower 	if (af != AF_ISO)
65736384Ssklower 		return (0);
65836384Ssklower 	IFDEBUG(D_ROUTE)
65936384Ssklower 		printf(">>> iso_ifwithidi addr\n");
66036384Ssklower 		dump_isoaddr( (struct sockaddr_iso *)(addr));
66136384Ssklower 		printf("\n");
66236384Ssklower 	ENDDEBUG
66336384Ssklower 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
66436384Ssklower 		IFDEBUG(D_ROUTE)
66536384Ssklower 			printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
66636384Ssklower 		ENDDEBUG
66736384Ssklower 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
66836384Ssklower 			IFDEBUG(D_ROUTE)
66936384Ssklower 				printf("iso_ifwithidi address ");
67037469Ssklower 				dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr));
67136384Ssklower 			ENDDEBUG
67237469Ssklower 			if (ifa->ifa_addr->sa_family != addr->sa_family)
67336384Ssklower 				continue;
67436384Ssklower 
67536384Ssklower #define	IFA_SIS(ifa)\
67637469Ssklower 	((struct sockaddr_iso *)((ifa)->ifa_addr))
67736384Ssklower 
67836384Ssklower 			IFDEBUG(D_ROUTE)
67936384Ssklower 				printf(" af same, args to iso_eqtype:\n");
68036384Ssklower 				printf("0x%x ", IFA_SIS(ifa)->siso_addr);
68136384Ssklower 				printf(" 0x%x\n",
68236384Ssklower 				&(((struct sockaddr_iso *)addr)->siso_addr));
68336384Ssklower 			ENDDEBUG
68436384Ssklower 
68536384Ssklower 			if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr),
68636384Ssklower 				&(((struct sockaddr_iso *)addr)->siso_addr))) {
68736384Ssklower 				IFDEBUG(D_ROUTE)
68836384Ssklower 					printf("ifa_ifwithidi: ifa found\n");
68936384Ssklower 				ENDDEBUG
69036384Ssklower 				return (ifa);
69136384Ssklower 			}
69236384Ssklower 			IFDEBUG(D_ROUTE)
69336384Ssklower 				printf(" iso_eqtype failed\n");
69436384Ssklower 			ENDDEBUG
69536384Ssklower 		}
69636384Ssklower 	}
69736384Ssklower 	return ((struct ifaddr *)0);
69836384Ssklower }
69936384Ssklower 
70037469Ssklower #endif notdef
70136384Ssklower /*
70236384Ssklower  * FUNCTION:		iso_ck_addr
70336384Ssklower  *
70436384Ssklower  * PURPOSE:			return true if the iso_addr passed is
70536384Ssklower  *					within the legal size limit for an iso address.
70636384Ssklower  *
70736384Ssklower  * RETURNS:			true or false
70836384Ssklower  *
70936384Ssklower  * SIDE EFFECTS:
71036384Ssklower  *
71136384Ssklower  */
71236384Ssklower iso_ck_addr(isoa)
71336384Ssklower struct iso_addr	*isoa;	/* address to check */
71436384Ssklower {
71536384Ssklower 	return (isoa->isoa_len <= 20);
71636384Ssklower 
71736384Ssklower }
71836384Ssklower 
71937469Ssklower #ifdef notdef
72036384Ssklower /*
72136384Ssklower  * FUNCTION:		iso_eqtype
72236384Ssklower  *
72336384Ssklower  * PURPOSE:			Determine if two iso addresses are of the same type.
72436384Ssklower  *  This is flaky.  Really we should consider all type 47 addrs to be the
72536384Ssklower  *  same - but there do exist different structures for 47 addrs.
72636384Ssklower  *  Gosip adds a 3rd.
72736384Ssklower  *
72836384Ssklower  * RETURNS:			true if the addresses are the same type
72936384Ssklower  *
73036384Ssklower  * SIDE EFFECTS:
73136384Ssklower  *
73236384Ssklower  * NOTES:			By type, I mean rfc986, t37, or osinet
73336384Ssklower  *
73436384Ssklower  *					This will first compare afis. If they match, then
73536384Ssklower  *					if the addr is not t37, the idis must be compared.
73636384Ssklower  */
73736384Ssklower iso_eqtype(isoaa, isoab)
73836384Ssklower struct iso_addr	*isoaa;		/* first addr to check */
73936384Ssklower struct iso_addr	*isoab;		/* other addr to check */
74036384Ssklower {
74136384Ssklower 	if (isoaa->isoa_afi == isoab->isoa_afi) {
74236384Ssklower 		if (isoaa->isoa_afi == AFI_37)
74336384Ssklower 			return(1);
74436384Ssklower 		else
74536384Ssklower 			return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
74636384Ssklower 	}
74736384Ssklower 	return(0);
74836384Ssklower }
74937469Ssklower #endif notdef
75036384Ssklower /*
75137469Ssklower  * FUNCTION:		iso_localifa()
75236384Ssklower  *
75337469Ssklower  * PURPOSE:			Find an interface addresss having a given destination
75437469Ssklower  *					or at least matching the net.
75536384Ssklower  *
75636384Ssklower  * RETURNS:			ptr to an interface address
75736384Ssklower  *
75836384Ssklower  * SIDE EFFECTS:
75936384Ssklower  *
76036384Ssklower  * NOTES:
76136384Ssklower  */
76236384Ssklower struct iso_ifaddr *
76337469Ssklower iso_localifa(siso)
76437469Ssklower 	register struct sockaddr_iso *siso;
76536384Ssklower {
76636384Ssklower 	register struct iso_ifaddr *ia;
76737469Ssklower 	register char *cp1, *cp2, *cp3;
76837469Ssklower 	register struct ifnet *ifp;
76937469Ssklower 	struct iso_ifaddr *ia_maybe = 0;
77037469Ssklower 	/*
77137469Ssklower 	 * We make one pass looking for both net matches and an exact
77237469Ssklower 	 * dst addr.
77337469Ssklower 	 */
77437469Ssklower 	for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
77537469Ssklower 		if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
77637469Ssklower 			continue;
77737469Ssklower 		if (ifp->if_flags & IFF_POINTOPOINT) {
77837469Ssklower 			if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
77937469Ssklower 				SAME_ISOADDR(&ia->ia_dstaddr, siso))
78037469Ssklower 				return (ia);
78137469Ssklower 			else
78237469Ssklower 				if (SAME_ISOADDR(&ia->ia_addr, siso))
78337469Ssklower 					ia_maybe = ia;
78437469Ssklower 			continue;
78537469Ssklower 		}
78637469Ssklower 		if (ia->ia_sockmask.siso_len) {
78737469Ssklower 			char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask;
78837469Ssklower 			cp1 = ia->ia_sockmask.siso_data;
78937469Ssklower 			cp2 = siso->siso_data;
79037469Ssklower 			cp3 = ia->ia_addr.siso_data;
79139936Ssklower 			while (cp1 < cplim)
79237469Ssklower 				if (*cp1++ & (*cp2++ ^ *cp3++))
79337469Ssklower 					goto next;
79437469Ssklower 			ia_maybe = ia;
79537469Ssklower 		}
79637469Ssklower 		if (SAME_ISOADDR(&ia->ia_addr, siso))
79737469Ssklower 			return ia;
79837469Ssklower 	next:;
79937469Ssklower 	}
80037469Ssklower 	return ia_maybe;
80136384Ssklower }
80236384Ssklower 
80347272Ssklower #ifdef	TPCONS
80436384Ssklower #include "cons.h"
80547272Ssklower #endif	TPCONS
80636384Ssklower /*
80736384Ssklower  * FUNCTION:		iso_nlctloutput
80836384Ssklower  *
80936384Ssklower  * PURPOSE:			Set options at the network level
81036384Ssklower  *
81136384Ssklower  * RETURNS:			E*
81236384Ssklower  *
81336384Ssklower  * SIDE EFFECTS:
81436384Ssklower  *
81536384Ssklower  * NOTES:			This could embody some of the functions of
81636384Ssklower  *					rclnp_ctloutput and cons_ctloutput.
81736384Ssklower  */
81836384Ssklower iso_nlctloutput(cmd, optname, pcb, m)
81936384Ssklower int			cmd;		/* command:set or get */
82036384Ssklower int			optname;	/* option of interest */
82136384Ssklower caddr_t		pcb;		/* nl pcb */
82236384Ssklower struct mbuf	*m;			/* data for set, buffer for get */
82336384Ssklower {
82436384Ssklower 	struct isopcb	*isop = (struct isopcb *)pcb;
82536384Ssklower 	int				error = 0;	/* return value */
82636384Ssklower 	caddr_t			data;		/* data for option */
82736384Ssklower 	int				data_len;	/* data's length */
82836384Ssklower 
82936384Ssklower 	IFDEBUG(D_ISO)
83036384Ssklower 		printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n",
83136384Ssklower 			cmd, optname, pcb, m);
83236384Ssklower 	ENDDEBUG
83336384Ssklower 
83436384Ssklower 	if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
83536384Ssklower 		return(EOPNOTSUPP);
83636384Ssklower 
83736384Ssklower 	data = mtod(m, caddr_t);
83836384Ssklower 	data_len = (m)->m_len;
83936384Ssklower 
84036384Ssklower 	IFDEBUG(D_ISO)
84136384Ssklower 		printf("iso_nlctloutput: data is:\n");
84236384Ssklower 		dump_buf(data, data_len);
84336384Ssklower 	ENDDEBUG
84436384Ssklower 
84536384Ssklower 	switch (optname) {
84636384Ssklower 
84747272Ssklower #ifdef	TPCONS
84836384Ssklower 		case CONSOPT_X25CRUD:
84936384Ssklower 			if (cmd == PRCO_GETOPT) {
85036384Ssklower 				error = EOPNOTSUPP;
85136384Ssklower 				break;
85236384Ssklower 			}
85336384Ssklower 
85436384Ssklower 			if (data_len > MAXX25CRUDLEN) {
85536384Ssklower 				error = EINVAL;
85636384Ssklower 				break;
85736384Ssklower 			}
85836384Ssklower 
85936384Ssklower 			IFDEBUG(D_ISO)
86036384Ssklower 				printf("iso_nlctloutput: setting x25 crud\n");
86136384Ssklower 			ENDDEBUG
86236384Ssklower 
86337469Ssklower 			bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len);
86436384Ssklower 			isop->isop_x25crud_len = data_len;
86536384Ssklower 			break;
86647272Ssklower #endif	TPCONS
86736384Ssklower 
86836384Ssklower 		default:
86936384Ssklower 			error = EOPNOTSUPP;
87036384Ssklower 	}
87136384Ssklower 
87236384Ssklower 	return error;
87336384Ssklower }
87436384Ssklower #endif ISO
87536384Ssklower 
87636384Ssklower #ifdef ARGO_DEBUG
87736384Ssklower 
87836384Ssklower /*
87936384Ssklower  * FUNCTION:		dump_isoaddr
88036384Ssklower  *
88136384Ssklower  * PURPOSE:			debugging
88236384Ssklower  *
88336384Ssklower  * RETURNS:			nada
88436384Ssklower  *
88536384Ssklower  */
88636384Ssklower dump_isoaddr(s)
88736384Ssklower 	struct sockaddr_iso *s;
88836384Ssklower {
88937469Ssklower 	char *clnp_saddr_isop();
89036384Ssklower 	register int i;
89136384Ssklower 
89236384Ssklower 	if( s->siso_family == AF_ISO) {
89337469Ssklower 		printf("ISO address: suffixlen %d, %s\n",
89438841Ssklower 			s->siso_tlen, clnp_saddr_isop(s));
89536384Ssklower 	} else if( s->siso_family == AF_INET) {
89636384Ssklower 		/* hack */
89736384Ssklower 		struct sockaddr_in *sin = (struct sockaddr_in *)s;
89836384Ssklower 
89936384Ssklower 		printf("%d.%d.%d.%d: %d",
90036384Ssklower 			(sin->sin_addr.s_addr>>24)&0xff,
90136384Ssklower 			(sin->sin_addr.s_addr>>16)&0xff,
90236384Ssklower 			(sin->sin_addr.s_addr>>8)&0xff,
90336384Ssklower 			(sin->sin_addr.s_addr)&0xff,
90436384Ssklower 			sin->sin_port);
90536384Ssklower 	}
90636384Ssklower }
90736384Ssklower 
90836384Ssklower #endif ARGO_DEBUG
909