xref: /csrg-svn/sys/netiso/iso.c (revision 43333)
136384Ssklower /***********************************************************
236384Ssklower 		Copyright IBM Corporation 1987
336384Ssklower 
436384Ssklower                       All Rights Reserved
536384Ssklower 
636384Ssklower Permission to use, copy, modify, and distribute this software and its
736384Ssklower documentation for any purpose and without fee is hereby granted,
836384Ssklower provided that the above copyright notice appear in all copies and that
936384Ssklower both that copyright notice and this permission notice appear in
1036384Ssklower supporting documentation, and that the name of IBM not be
1136384Ssklower used in advertising or publicity pertaining to distribution of the
1236384Ssklower software without specific, written prior permission.
1336384Ssklower 
1436384Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1536384Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1636384Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1736384Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1836384Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1936384Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036384Ssklower SOFTWARE.
2136384Ssklower 
2236384Ssklower ******************************************************************/
2336384Ssklower 
2436384Ssklower /*
2536384Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2636384Ssklower  */
2736384Ssklower /*
2836384Ssklower  * $Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $
2936384Ssklower  * $Source: /usr/argo/sys/netiso/RCS/iso.c,v $
30*43333Ssklower  *	@(#)iso.c	7.9 (Berkeley) 06/20/90
3136384Ssklower  *
3236384Ssklower  * iso.c: miscellaneous routines to support the iso address family
3336384Ssklower  */
3436384Ssklower 
3536384Ssklower #ifndef lint
3636384Ssklower static char *rcsid = "$Header: iso.c,v 4.11 88/09/19 14:58:35 root Exp $";
3736384Ssklower #endif
3836384Ssklower 
3936384Ssklower 
4037469Ssklower #include "types.h"
4137469Ssklower #include "param.h"
4237469Ssklower #include "ioctl.h"
4337469Ssklower #include "mbuf.h"
4437469Ssklower #include "domain.h"
4537469Ssklower #include "protosw.h"
4637469Ssklower #include "socket.h"
4737469Ssklower #include "socketvar.h"
4837469Ssklower #include "user.h"
4937469Ssklower #include "errno.h"
5036384Ssklower 
5136384Ssklower #include "../net/if.h"
5236384Ssklower #include "../net/route.h"
5336384Ssklower #include "../net/af.h"
5436384Ssklower 
5537469Ssklower #include "iso.h"
5637469Ssklower #include "iso_var.h"
5737469Ssklower #include "iso_snpac.h"
5837469Ssklower #include "iso_pcb.h"
5937469Ssklower #include "clnp.h"
6037469Ssklower #include "argo_debug.h"
6136384Ssklower 
6236384Ssklower #ifdef ISO
6337469Ssklower #include "argoxtwentyfive.h"
6436384Ssklower 
6536384Ssklower int	iso_interfaces = 0;		/* number of external interfaces */
6636384Ssklower extern	struct ifnet loif;	/* loopback interface */
67*43333Ssklower int ether_output(), llc_rtrequest();
6836384Ssklower 
6936384Ssklower 
7036384Ssklower /*
7136384Ssklower  * FUNCTION:		iso_init
7236384Ssklower  *
7336384Ssklower  * PURPOSE:			initialize the iso address family
7436384Ssklower  *
7536384Ssklower  * RETURNS:			nothing
7636384Ssklower  *
7736384Ssklower  * SIDE EFFECTS:	1) zeros the maptab table.
7837469Ssklower  *					2) initializes the routing table.
7936384Ssklower  *
8036384Ssklower  * NOTES:
8136384Ssklower  */
8237469Ssklower struct radix_node_head *iso_rnhead;
8336384Ssklower iso_init()
8436384Ssklower {
8537469Ssklower 	static iso_init_done;
8636384Ssklower 
8737469Ssklower 	if (iso_init_done == 0) {
8837469Ssklower 		iso_init_done++;
8937469Ssklower 		rn_inithead(&iso_rnhead, 40, AF_ISO);
9037469Ssklower 	}
9136384Ssklower }
9236384Ssklower 
9336384Ssklower /*
9436384Ssklower  * FUNCTION:		iso_addrmatch1
9536384Ssklower  *
9636384Ssklower  * PURPOSE:			decide if the two iso_addrs passed are equal
9736384Ssklower  *
9836384Ssklower  * RETURNS:			true if the addrs match, false if they do not
9936384Ssklower  *
10036384Ssklower  * SIDE EFFECTS:
10136384Ssklower  *
10236384Ssklower  * NOTES:
10336384Ssklower  */
10436384Ssklower iso_addrmatch1(isoaa, isoab)
10537469Ssklower register struct iso_addr *isoaa, *isoab;		/* addresses to check */
10636384Ssklower {
10737469Ssklower 	u_int	compare_len;
10836384Ssklower 
10936384Ssklower 	IFDEBUG(D_ROUTE)
11036384Ssklower 		printf("iso_addrmatch1: comparing lengths: %d to %d\n", isoaa->isoa_len,
11136384Ssklower 			isoab->isoa_len);
11236384Ssklower 		printf("a:\n");
11337469Ssklower 		dump_buf(isoaa->isoa_genaddr, isoaa->isoa_len);
11436384Ssklower 		printf("b:\n");
11537469Ssklower 		dump_buf(isoab->isoa_genaddr, isoab->isoa_len);
11636384Ssklower 	ENDDEBUG
11736384Ssklower 
11836384Ssklower 	if ((compare_len = isoaa->isoa_len) != isoab->isoa_len) {
11936384Ssklower 		IFDEBUG(D_ROUTE)
12036384Ssklower 			printf("iso_addrmatch1: returning false because of lengths\n");
12136384Ssklower 		ENDDEBUG
12236384Ssklower 		return 0;
12336384Ssklower 	}
12436384Ssklower 
12537469Ssklower #ifdef notdef
12636384Ssklower 	/* TODO : generalize this to all afis with masks */
12736384Ssklower 	if(	isoaa->isoa_afi == AFI_37 ) {
12836384Ssklower 		/* must not compare 2 least significant digits, or for
12936384Ssklower 		 * that matter, the DSP
13036384Ssklower 		 */
13136384Ssklower 		compare_len = ADDR37_IDI_LEN - 1;
13236384Ssklower 	}
13337469Ssklower #endif
13436384Ssklower 
13536384Ssklower 	IFDEBUG(D_ROUTE)
13636384Ssklower 		int i;
13736384Ssklower 		char *a, *b;
13836384Ssklower 
13937469Ssklower 		a = isoaa->isoa_genaddr;
14037469Ssklower 		b = isoab->isoa_genaddr;
14136384Ssklower 
14236384Ssklower 		for (i=0; i<compare_len; i++) {
14336384Ssklower 			printf("<%x=%x>", a[i]&0xff, b[i]&0xff);
14436384Ssklower 			if (a[i] != b[i]) {
14536384Ssklower 				printf("\naddrs are not equal at byte %d\n", i);
14636384Ssklower 				return(0);
14736384Ssklower 			}
14836384Ssklower 		}
14936384Ssklower 		printf("\n");
15036384Ssklower 		printf("addrs are equal\n");
15136384Ssklower 		return (1);
15236384Ssklower 	ENDDEBUG
15337469Ssklower 	return (!bcmp(isoaa->isoa_genaddr, isoab->isoa_genaddr, compare_len));
15436384Ssklower }
15536384Ssklower 
15636384Ssklower /*
15736384Ssklower  * FUNCTION:		iso_addrmatch
15836384Ssklower  *
15936384Ssklower  * PURPOSE:			decide if the two sockadrr_isos passed are equal
16036384Ssklower  *
16136384Ssklower  * RETURNS:			true if the addrs match, false if they do not
16236384Ssklower  *
16336384Ssklower  * SIDE EFFECTS:
16436384Ssklower  *
16536384Ssklower  * NOTES:
16636384Ssklower  */
16736384Ssklower iso_addrmatch(sisoa, sisob)
16836384Ssklower struct sockaddr_iso	*sisoa, *sisob;		/* addresses to check */
16936384Ssklower {
17036384Ssklower 	return(iso_addrmatch1(&sisoa->siso_addr, &sisob->siso_addr));
17136384Ssklower }
17237469Ssklower #ifdef notdef
17336384Ssklower /*
17436384Ssklower  * FUNCTION:		iso_netmatch
17536384Ssklower  *
17636384Ssklower  * PURPOSE:			similar to iso_addrmatch but takes sockaddr_iso
17736384Ssklower  *					as argument.
17836384Ssklower  *
17936384Ssklower  * RETURNS:			true if same net, false if not
18036384Ssklower  *
18136384Ssklower  * SIDE EFFECTS:
18236384Ssklower  *
18336384Ssklower  * NOTES:
18436384Ssklower  */
18536384Ssklower iso_netmatch(sisoa, sisob)
18636384Ssklower struct sockaddr_iso *sisoa, *sisob;
18736384Ssklower {
18836384Ssklower 	u_char			bufa[sizeof(struct sockaddr_iso)];
18936384Ssklower 	u_char			bufb[sizeof(struct sockaddr_iso)];
19036384Ssklower 	register int	lena, lenb;
19136384Ssklower 
19236384Ssklower 	lena = iso_netof(&sisoa->siso_addr, bufa);
19336384Ssklower 	lenb = iso_netof(&sisob->siso_addr, bufb);
19436384Ssklower 
19536384Ssklower 	IFDEBUG(D_ROUTE)
19636384Ssklower 		printf("iso_netmatch: comparing lengths: %d to %d\n", lena, lenb);
19736384Ssklower 		printf("a:\n");
19836384Ssklower 		dump_buf(bufa, lena);
19936384Ssklower 		printf("b:\n");
20036384Ssklower 		dump_buf(bufb, lenb);
20136384Ssklower 	ENDDEBUG
20236384Ssklower 
20336384Ssklower 	return ((lena == lenb) && (!bcmp(bufa, bufb, lena)));
20436384Ssklower }
20537469Ssklower #endif notdef
20636384Ssklower 
20736384Ssklower /*
20836384Ssklower  * FUNCTION:		iso_hashchar
20936384Ssklower  *
21036384Ssklower  * PURPOSE:			Hash all character in the buffer specified into
21136384Ssklower  *					a long. Return the long.
21236384Ssklower  *
21336384Ssklower  * RETURNS:			The hash value.
21436384Ssklower  *
21536384Ssklower  * SIDE EFFECTS:
21636384Ssklower  *
21736384Ssklower  * NOTES:			The hash is achieved by exclusive ORing 4 byte
21836384Ssklower  *					quantities.
21936384Ssklower  */
22036384Ssklower u_long
22136384Ssklower iso_hashchar(buf, len)
22236384Ssklower register caddr_t	buf;		/* buffer to pack from */
22336384Ssklower register int		len;		/* length of buffer */
22436384Ssklower {
22536384Ssklower 	register u_long	h = 0;
22636384Ssklower 	register int	i;
22736384Ssklower 
22836384Ssklower 	for (i=0; i<len; i+=4) {
22936384Ssklower 		register u_long	l = 0;
23036384Ssklower 
23136384Ssklower 		if ((len - i) < 4) {
23236384Ssklower 			/* buffer not multiple of 4 */
23336384Ssklower 			switch (len - i) {
23436384Ssklower 				case 3:
23536384Ssklower 					l |= buf[i+2] << 8;
23636384Ssklower 				case 2:
23736384Ssklower 					l |= buf[i+1] << 16;
23836384Ssklower 				case 1:
23936384Ssklower 					l |= buf[i] << 24;
24036384Ssklower 					break;
24136384Ssklower 				default:
24236384Ssklower 					printf("iso_hashchar: unexpected value x%x\n", len - i);
24336384Ssklower 					break;
24436384Ssklower 			}
24536384Ssklower 		} else {
24636384Ssklower 			l |= buf[i] << 24;
24736384Ssklower 			l |= buf[i+1] << 16;
24836384Ssklower 			l |= buf[i+2] << 8;
24936384Ssklower 			l |= buf[i+3];
25036384Ssklower 		}
25136384Ssklower 
25236384Ssklower 		h ^= l;
25336384Ssklower 	}
25436384Ssklower 
25536384Ssklower 	h ^= (u_long) (len % 4);
25636384Ssklower 
25736384Ssklower 	return(h);
25836384Ssklower }
25937469Ssklower #ifdef notdef
26036384Ssklower /*
26136384Ssklower  * FUNCTION:		iso_hash
26236384Ssklower  *
26336384Ssklower  * PURPOSE:			Fill in fields of afhash structure based upon addr passed.
26436384Ssklower  *
26536384Ssklower  * RETURNS:			none
26636384Ssklower  *
26736384Ssklower  * SIDE EFFECTS:
26836384Ssklower  *
26936384Ssklower  * NOTES:
27036384Ssklower  */
27136384Ssklower iso_hash(siso, hp)
27236384Ssklower struct sockaddr_iso	*siso;		/* address to perform hash on */
27336384Ssklower struct afhash		*hp;		/* RETURN: hash info here */
27436384Ssklower {
27536384Ssklower 	u_long			buf[sizeof(struct sockaddr_iso)+1/4];
27636384Ssklower 	register int	bufsize;
27736384Ssklower 
27836384Ssklower 
27936384Ssklower 	bzero(buf, sizeof(buf));
28036384Ssklower 
28136384Ssklower 	bufsize = iso_netof(&siso->siso_addr, buf);
28236384Ssklower 	hp->afh_nethash = iso_hashchar((caddr_t)buf, bufsize);
28336384Ssklower 
28436384Ssklower 	IFDEBUG(D_ROUTE)
28536384Ssklower 		printf("iso_hash: iso_netof: bufsize = %d\n", bufsize);
28636384Ssklower 	ENDDEBUG
28736384Ssklower 
28836384Ssklower 	hp->afh_hosthash = iso_hashchar((caddr_t)&siso->siso_addr,
28936384Ssklower 		siso->siso_addr.isoa_len);
29036384Ssklower 
29136384Ssklower 	IFDEBUG(D_ROUTE)
29236384Ssklower 		printf("iso_hash: %s: nethash = x%x, hosthash = x%x\n",
29336384Ssklower 			clnp_iso_addrp(&siso->siso_addr), hp->afh_nethash,
29436384Ssklower 			hp->afh_hosthash);
29536384Ssklower 	ENDDEBUG
29636384Ssklower }
29736384Ssklower /*
29836384Ssklower  * FUNCTION:		iso_netof
29936384Ssklower  *
30036384Ssklower  * PURPOSE:			Extract the network portion of the iso address.
30136384Ssklower  *					The network portion of the iso address varies depending
30236384Ssklower  *					on the type of address. The network portion of the
30336384Ssklower  *					address will include the IDP. The network portion is:
30436384Ssklower  *
30536384Ssklower  *						TYPE			DESC
30636384Ssklower  *					t37					The AFI and x.121 (IDI)
30736384Ssklower  *					osinet				The AFI, orgid, snetid
30836384Ssklower  *					rfc986				The AFI, vers and network part of
30936384Ssklower  *										internet address.
31036384Ssklower  *
31136384Ssklower  * RETURNS:			number of bytes placed into buf.
31236384Ssklower  *
31336384Ssklower  * SIDE EFFECTS:
31436384Ssklower  *
31536384Ssklower  * NOTES:			Buf is assumed to be big enough
31636384Ssklower  */
31736384Ssklower iso_netof(isoa, buf)
31836384Ssklower struct iso_addr	*isoa;		/* address */
31936384Ssklower caddr_t			buf;		/* RESULT: network portion of address here */
32036384Ssklower {
32136384Ssklower 	u_int		len = 1;	/* length of afi */
32236384Ssklower 
32336384Ssklower 	switch (isoa->isoa_afi) {
32436384Ssklower 		case AFI_37:
32536384Ssklower 			/*
32636384Ssklower 			 * Due to classic x.25 tunnel vision, there is no
32736384Ssklower 			 * net portion of an x.121 address.  For our purposes
32836384Ssklower 			 * the AFI will do, so that all x.25 -type addresses
32936384Ssklower 			 * map to the single x.25 SNPA. (Cannot have more than
33036384Ssklower 			 * one, obviously).
33136384Ssklower 			 */
33236384Ssklower 
33336384Ssklower 			break;
33436384Ssklower 
33536384Ssklower /* 		case AFI_OSINET:*/
33636384Ssklower 		case AFI_RFC986: {
33736384Ssklower 			u_short	idi;	/* value of idi */
33836384Ssklower 
33936384Ssklower 			/* osinet and rfc986 have idi in the same place */
34036384Ssklower 			CTOH(isoa->rfc986_idi[0], isoa->rfc986_idi[1], idi);
34136384Ssklower 
34236384Ssklower 			if (idi == IDI_OSINET)
34336384Ssklower /*
34436384Ssklower  *	Network portion of OSINET address can only be the IDI. Clearly,
34536384Ssklower  *	with one x25 interface, one could get to several orgids, and
34636384Ssklower  *	several snetids.
34736384Ssklower 				len += (ADDROSINET_IDI_LEN + OVLOSINET_ORGID_LEN +
34836384Ssklower 						OVLOSINET_SNETID_LEN);
34936384Ssklower  */
35036384Ssklower 				len += ADDROSINET_IDI_LEN;
35136384Ssklower 			else if (idi == IDI_RFC986) {
35236384Ssklower 				u_long				inetaddr;
35336384Ssklower 				struct ovl_rfc986	*o986 = (struct ovl_rfc986 *)isoa;
35436384Ssklower 
35536384Ssklower 				/* bump len to include idi and version (1 byte) */
35636384Ssklower 				len += ADDRRFC986_IDI_LEN + 1;
35736384Ssklower 
35836384Ssklower 				/* get inet addr long aligned */
35936384Ssklower 				bcopy(o986->o986_inetaddr, &inetaddr, sizeof(inetaddr));
36036384Ssklower 				inetaddr = ntohl(inetaddr);	/* convert to host byte order */
36136384Ssklower 
36236384Ssklower 				IFDEBUG(D_ROUTE)
36336384Ssklower 					printf("iso_netof: isoa ");
36436384Ssklower 					dump_buf(isoa, sizeof(*isoa));
36536384Ssklower 					printf("iso_netof: inetaddr 0x%x ", inetaddr);
36636384Ssklower 				ENDDEBUG
36736384Ssklower 
36836384Ssklower 				/* bump len by size of network portion of inet address */
36936384Ssklower 				if (IN_CLASSA(inetaddr)) {
37036384Ssklower 					len += 4-IN_CLASSA_NSHIFT/8;
37136384Ssklower 					IFDEBUG(D_ROUTE)
37236384Ssklower 						printf("iso_netof: class A net len is now %d\n", len);
37336384Ssklower 					ENDDEBUG
37436384Ssklower 				} else if (IN_CLASSB(inetaddr)) {
37536384Ssklower 					len += 4-IN_CLASSB_NSHIFT/8;
37636384Ssklower 					IFDEBUG(D_ROUTE)
37736384Ssklower 						printf("iso_netof: class B net len is now %d\n", len);
37836384Ssklower 					ENDDEBUG
37936384Ssklower 				} else {
38036384Ssklower 					len += 4-IN_CLASSC_NSHIFT/8;
38136384Ssklower 					IFDEBUG(D_ROUTE)
38236384Ssklower 						printf("iso_netof: class C net len is now %d\n", len);
38336384Ssklower 					ENDDEBUG
38436384Ssklower 				}
38536384Ssklower 			} else
38636384Ssklower 				len = 0;
38736384Ssklower 		} break;
38836384Ssklower 
38936384Ssklower 		default:
39036384Ssklower 			len = 0;
39136384Ssklower 	}
39236384Ssklower 
39336384Ssklower 	bcopy((caddr_t)isoa, buf, len);
39436384Ssklower 	IFDEBUG(D_ROUTE)
39536384Ssklower 		printf("in_netof: isoa ");
39636384Ssklower 		dump_buf(isoa, len);
39736384Ssklower 		printf("in_netof: net ");
39836384Ssklower 		dump_buf(buf, len);
39936384Ssklower 	ENDDEBUG
40036384Ssklower 	return len;
40136384Ssklower }
40237469Ssklower #endif notdef
40336384Ssklower /*
40437469Ssklower  * Generic iso control operations (ioctl's).
40537469Ssklower  * Ifp is 0 if not an interface-specific ioctl.
40636384Ssklower  */
40737469Ssklower /* ARGSUSED */
40836384Ssklower iso_control(so, cmd, data, ifp)
40937469Ssklower 	struct socket *so;
41037469Ssklower 	int cmd;
41137469Ssklower 	caddr_t data;
41237469Ssklower 	register struct ifnet *ifp;
41336384Ssklower {
41437469Ssklower 	register struct iso_ifreq *ifr = (struct iso_ifreq *)data;
41537469Ssklower 	register struct iso_ifaddr *ia = 0;
41637469Ssklower 	register struct ifaddr *ifa;
41737469Ssklower 	struct iso_ifaddr *oia;
41837469Ssklower 	struct iso_aliasreq *ifra = (struct iso_aliasreq *)data;
41937469Ssklower 	int error, hostIsNew, maskIsNew;
42036384Ssklower 
42137469Ssklower 	/*
42237469Ssklower 	 * Find address for this interface, if it exists.
42337469Ssklower 	 */
42437469Ssklower 	if (ifp)
42537469Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
42637469Ssklower 			if (ia->ia_ifp == ifp)
42737469Ssklower 				break;
42836384Ssklower 
42936384Ssklower 	switch (cmd) {
43037469Ssklower 
43137469Ssklower 	case SIOCAIFADDR_ISO:
43237469Ssklower 	case SIOCDIFADDR_ISO:
43337469Ssklower 		if (ifra->ifra_addr.siso_family == AF_ISO)
43437469Ssklower 		    for (oia = ia; ia; ia = ia->ia_next) {
43537469Ssklower 			if (ia->ia_ifp == ifp  &&
43637469Ssklower 			    SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
43737469Ssklower 				break;
43837469Ssklower 		}
43937547Smckusick 		if (error = suser(u.u_cred, &u.u_acflag))
44037547Smckusick 			return (error);
44136384Ssklower 		if (ifp == 0)
44237469Ssklower 			panic("iso_control");
44337469Ssklower 		if (ia == (struct iso_ifaddr *)0) {
44437469Ssklower 			struct iso_ifaddr *nia;
44537469Ssklower 			if (cmd == SIOCDIFADDR_ISO)
44637469Ssklower 				return (EADDRNOTAVAIL);
44737469Ssklower 			MALLOC(nia, struct iso_ifaddr *, sizeof(*nia),
44837469Ssklower 				       M_IFADDR, M_WAITOK);
44937469Ssklower 			if (nia == (struct iso_ifaddr *)0)
45037469Ssklower 				return (ENOBUFS);
45137469Ssklower 			bzero((caddr_t)nia, sizeof(*nia));
45237469Ssklower 			if (ia = iso_ifaddr) {
45337469Ssklower 				for ( ; ia->ia_next; ia = ia->ia_next)
45437469Ssklower 					;
45537469Ssklower 				ia->ia_next = nia;
45637469Ssklower 			} else
45737469Ssklower 				iso_ifaddr = nia;
45837469Ssklower 			ia = nia;
45937469Ssklower 			if (ifa = ifp->if_addrlist) {
46037469Ssklower 				for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
46137469Ssklower 					;
46237469Ssklower 				ifa->ifa_next = (struct ifaddr *) ia;
46337469Ssklower 			} else
46437469Ssklower 				ifp->if_addrlist = (struct ifaddr *) ia;
46537469Ssklower 			ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
46637469Ssklower 			ia->ia_ifa.ifa_dstaddr
46737469Ssklower 					= (struct sockaddr *)&ia->ia_dstaddr;
46837469Ssklower 			ia->ia_ifa.ifa_netmask
46937469Ssklower 					= (struct sockaddr *)&ia->ia_sockmask;
47037469Ssklower 			ia->ia_ifp = ifp;
47137469Ssklower 			if (ifp != &loif)
47237469Ssklower 				iso_interfaces++;
47337469Ssklower 		}
47437469Ssklower 		break;
47536384Ssklower 
47637469Ssklower #define cmdbyte(x)	(((x) >> 8) & 0xff)
47737469Ssklower 	default:
47837469Ssklower 		if (cmdbyte(cmd) == 'a')
47937469Ssklower 			return (snpac_ioctl(cmd, data));
48037469Ssklower 		if (ia == (struct iso_ifaddr *)0)
48137469Ssklower 			return (EADDRNOTAVAIL);
48237469Ssklower 		break;
48337469Ssklower 	}
48437469Ssklower 	switch (cmd) {
48536384Ssklower 
48637469Ssklower 	case SIOCGIFADDR_ISO:
48737469Ssklower 		ifr->ifr_Addr = ia->ia_addr;
48837469Ssklower 		break;
48936384Ssklower 
49037469Ssklower 	case SIOCGIFDSTADDR_ISO:
49137469Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
49237469Ssklower 			return (EINVAL);
49337469Ssklower 		ifr->ifr_Addr = ia->ia_dstaddr;
49437469Ssklower 		break;
49536384Ssklower 
49637469Ssklower 	case SIOCGIFNETMASK_ISO:
49737469Ssklower 		ifr->ifr_Addr = ia->ia_sockmask;
49837469Ssklower 		break;
49936384Ssklower 
50037469Ssklower 	case SIOCAIFADDR_ISO:
50137469Ssklower 		maskIsNew = 0; hostIsNew = 1; error = u.u_error;
50237469Ssklower 		if (ia->ia_addr.siso_family == AF_ISO) {
50337469Ssklower 			if (ifra->ifra_addr.siso_len == 0) {
50437469Ssklower 				ifra->ifra_addr = ia->ia_addr;
50537469Ssklower 				hostIsNew = 0;
50637469Ssklower 			} else if (SAME_ISOADDR(&ia->ia_addr, &ifra->ifra_addr))
50737469Ssklower 				hostIsNew = 0;
50837469Ssklower 		}
50937469Ssklower 		if (ifra->ifra_mask.siso_len) {
51037469Ssklower 			iso_ifscrub(ifp, ia);
51137469Ssklower 			ia->ia_sockmask = ifra->ifra_mask;
51237469Ssklower 			maskIsNew = 1;
51337469Ssklower 		}
51437469Ssklower 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
51537469Ssklower 		    (ifra->ifra_dstaddr.siso_family == AF_ISO)) {
51637469Ssklower 			iso_ifscrub(ifp, ia);
51737469Ssklower 			ia->ia_dstaddr = ifra->ifra_dstaddr;
51837469Ssklower 			maskIsNew  = 1; /* We lie; but the effect's the same */
51937469Ssklower 		}
52037469Ssklower 		if (ifra->ifra_addr.siso_family == AF_ISO &&
52137469Ssklower 					    (hostIsNew || maskIsNew)) {
52237469Ssklower 			error = iso_ifinit(ifp, ia, &ifra->ifra_addr, 0);
52337469Ssklower 		}
52437469Ssklower 		if (ifra->ifra_snpaoffset)
52537469Ssklower 			ia->ia_snpaoffset = ifra->ifra_snpaoffset;
52637469Ssklower 		return (error);
52737469Ssklower 
52837469Ssklower 	case SIOCDIFADDR_ISO:
52937469Ssklower 		iso_ifscrub(ifp, ia);
53037469Ssklower 		if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
53137469Ssklower 			ifp->if_addrlist = ifa->ifa_next;
53237469Ssklower 		else {
53337469Ssklower 			while (ifa->ifa_next &&
53437469Ssklower 			       (ifa->ifa_next != (struct ifaddr *)ia))
53537469Ssklower 				    ifa = ifa->ifa_next;
53637469Ssklower 			if (ifa->ifa_next)
53737469Ssklower 			    ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
53837469Ssklower 			else
53937469Ssklower 				printf("Couldn't unlink isoifaddr from ifp\n");
54037469Ssklower 		}
54137469Ssklower 		oia = ia;
54237469Ssklower 		if (oia == (ia = iso_ifaddr)) {
54337469Ssklower 			iso_ifaddr = ia->ia_next;
54437469Ssklower 		} else {
54537469Ssklower 			while (ia->ia_next && (ia->ia_next != oia)) {
54637469Ssklower 				ia = ia->ia_next;
54736384Ssklower 			}
54837469Ssklower 			if (ia->ia_next)
54937469Ssklower 			    ia->ia_next = oia->ia_next;
55037469Ssklower 			else
55137469Ssklower 				printf("Didn't unlink isoifadr from list\n");
55236384Ssklower 		}
55337469Ssklower 		free((caddr_t)oia, M_IFADDR);
55437469Ssklower 		break;
55536384Ssklower 
55636384Ssklower 	default:
55736384Ssklower 		if (ifp == 0 || ifp->if_ioctl == 0)
55836384Ssklower 			return (EOPNOTSUPP);
55936384Ssklower 		return ((*ifp->if_ioctl)(ifp, cmd, data));
56036384Ssklower 	}
56137469Ssklower 	return (0);
56236384Ssklower }
56336384Ssklower 
56437469Ssklower /*
56537469Ssklower  * Delete any existing route for an interface.
56637469Ssklower  */
56737469Ssklower iso_ifscrub(ifp, ia)
56837469Ssklower 	register struct ifnet *ifp;
56937469Ssklower 	register struct iso_ifaddr *ia;
57037469Ssklower {
571*43333Ssklower 	int nsellength = ia->ia_addr.siso_tlen;
57237469Ssklower 	if ((ia->ia_flags & IFA_ROUTE) == 0)
57337469Ssklower 		return;
574*43333Ssklower 	ia->ia_addr.siso_tlen = 0;
57537469Ssklower 	if (ifp->if_flags & IFF_LOOPBACK)
57637469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
57737469Ssklower 	else if (ifp->if_flags & IFF_POINTOPOINT)
57837469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
57937469Ssklower 	else {
58037469Ssklower 		rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
58137469Ssklower 	}
582*43333Ssklower 	ia->ia_addr.siso_tlen = nsellength;
58337469Ssklower 	ia->ia_flags &= ~IFA_ROUTE;
58437469Ssklower }
58537469Ssklower 
58637469Ssklower /*
58737469Ssklower  * Initialize an interface's internet address
58837469Ssklower  * and routing table entry.
58937469Ssklower  */
59037469Ssklower iso_ifinit(ifp, ia, siso, scrub)
59137469Ssklower 	register struct ifnet *ifp;
59237469Ssklower 	register struct iso_ifaddr *ia;
59337469Ssklower 	struct sockaddr_iso *siso;
59437469Ssklower {
59537469Ssklower 	struct sockaddr_iso oldaddr;
596*43333Ssklower 	int s = splimp(), error, nsellength;
59737469Ssklower 
59837469Ssklower 	oldaddr = ia->ia_addr;
59937469Ssklower 	ia->ia_addr = *siso;
60037469Ssklower 	/*
60137469Ssklower 	 * Give the interface a chance to initialize
60237469Ssklower 	 * if this is its first address,
60337469Ssklower 	 * and to validate the address if necessary.
60437469Ssklower 	 */
60537469Ssklower 	if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
60637469Ssklower 		splx(s);
60737469Ssklower 		ia->ia_addr = oldaddr;
60837469Ssklower 		return (error);
60937469Ssklower 	}
61037469Ssklower 	if (scrub) {
61137469Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
61237469Ssklower 		iso_ifscrub(ifp, ia);
61337469Ssklower 		ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
61437469Ssklower 	}
615*43333Ssklower 	/* XXX -- The following is here temporarily out of laziness
616*43333Ssklower 	   in not changing every ethernet driver's if_ioctl routine */
617*43333Ssklower 	if (ifp->if_output == ether_output) {
618*43333Ssklower 		ia->ia_ifa.ifa_rtrequest = llc_rtrequest;
619*43333Ssklower 		ia->ia_ifa.ifa_flags |= RTF_CLONING;
620*43333Ssklower 		ia->ia_ifa.ifa_llinfolen = sizeof(struct llinfo_llc);
621*43333Ssklower 	}
62237469Ssklower 	/*
62337469Ssklower 	 * Add route for the network.
62437469Ssklower 	 */
625*43333Ssklower 	nsellength = ia->ia_addr.siso_tlen;
626*43333Ssklower 	ia->ia_addr.siso_tlen = 0;
62737469Ssklower 	if (ifp->if_flags & IFF_LOOPBACK) {
62837469Ssklower 		ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
62940894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
63037469Ssklower 	} else if (ifp->if_flags & IFF_POINTOPOINT &&
63137469Ssklower 		 ia->ia_dstaddr.siso_family == AF_ISO)
63240894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
63337469Ssklower 	else {
63440894Ssklower 		rt_maskedcopy(ia->ia_ifa.ifa_addr, ia->ia_ifa.ifa_dstaddr,
63540894Ssklower 			ia->ia_ifa.ifa_netmask);
63640894Ssklower 		error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
63737469Ssklower 	}
638*43333Ssklower 	ia->ia_addr.siso_tlen = nsellength;
63937469Ssklower 	ia->ia_flags |= IFA_ROUTE;
64037469Ssklower 	splx(s);
64140894Ssklower 	return (error);
64237469Ssklower }
64337469Ssklower #ifdef notdef
64437469Ssklower 
64536384Ssklower struct ifaddr *
64636384Ssklower iso_ifwithidi(addr)
64736384Ssklower 	register struct sockaddr *addr;
64836384Ssklower {
64936384Ssklower 	register struct ifnet *ifp;
65036384Ssklower 	register struct ifaddr *ifa;
65136384Ssklower 	register u_int af = addr->sa_family;
65236384Ssklower 
65336384Ssklower 	if (af != AF_ISO)
65436384Ssklower 		return (0);
65536384Ssklower 	IFDEBUG(D_ROUTE)
65636384Ssklower 		printf(">>> iso_ifwithidi addr\n");
65736384Ssklower 		dump_isoaddr( (struct sockaddr_iso *)(addr));
65836384Ssklower 		printf("\n");
65936384Ssklower 	ENDDEBUG
66036384Ssklower 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
66136384Ssklower 		IFDEBUG(D_ROUTE)
66236384Ssklower 			printf("iso_ifwithidi ifnet %s\n", ifp->if_name);
66336384Ssklower 		ENDDEBUG
66436384Ssklower 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
66536384Ssklower 			IFDEBUG(D_ROUTE)
66636384Ssklower 				printf("iso_ifwithidi address ");
66737469Ssklower 				dump_isoaddr( (struct sockaddr_iso *)(ifa->ifa_addr));
66836384Ssklower 			ENDDEBUG
66937469Ssklower 			if (ifa->ifa_addr->sa_family != addr->sa_family)
67036384Ssklower 				continue;
67136384Ssklower 
67236384Ssklower #define	IFA_SIS(ifa)\
67337469Ssklower 	((struct sockaddr_iso *)((ifa)->ifa_addr))
67436384Ssklower 
67536384Ssklower 			IFDEBUG(D_ROUTE)
67636384Ssklower 				printf(" af same, args to iso_eqtype:\n");
67736384Ssklower 				printf("0x%x ", IFA_SIS(ifa)->siso_addr);
67836384Ssklower 				printf(" 0x%x\n",
67936384Ssklower 				&(((struct sockaddr_iso *)addr)->siso_addr));
68036384Ssklower 			ENDDEBUG
68136384Ssklower 
68236384Ssklower 			if (iso_eqtype(&(IFA_SIS(ifa)->siso_addr),
68336384Ssklower 				&(((struct sockaddr_iso *)addr)->siso_addr))) {
68436384Ssklower 				IFDEBUG(D_ROUTE)
68536384Ssklower 					printf("ifa_ifwithidi: ifa found\n");
68636384Ssklower 				ENDDEBUG
68736384Ssklower 				return (ifa);
68836384Ssklower 			}
68936384Ssklower 			IFDEBUG(D_ROUTE)
69036384Ssklower 				printf(" iso_eqtype failed\n");
69136384Ssklower 			ENDDEBUG
69236384Ssklower 		}
69336384Ssklower 	}
69436384Ssklower 	return ((struct ifaddr *)0);
69536384Ssklower }
69636384Ssklower 
69737469Ssklower #endif notdef
69836384Ssklower /*
69936384Ssklower  * FUNCTION:		iso_ck_addr
70036384Ssklower  *
70136384Ssklower  * PURPOSE:			return true if the iso_addr passed is
70236384Ssklower  *					within the legal size limit for an iso address.
70336384Ssklower  *
70436384Ssklower  * RETURNS:			true or false
70536384Ssklower  *
70636384Ssklower  * SIDE EFFECTS:
70736384Ssklower  *
70836384Ssklower  */
70936384Ssklower iso_ck_addr(isoa)
71036384Ssklower struct iso_addr	*isoa;	/* address to check */
71136384Ssklower {
71236384Ssklower 	return (isoa->isoa_len <= 20);
71336384Ssklower 
71436384Ssklower }
71536384Ssklower 
71637469Ssklower #ifdef notdef
71736384Ssklower /*
71836384Ssklower  * FUNCTION:		iso_eqtype
71936384Ssklower  *
72036384Ssklower  * PURPOSE:			Determine if two iso addresses are of the same type.
72136384Ssklower  *  This is flaky.  Really we should consider all type 47 addrs to be the
72236384Ssklower  *  same - but there do exist different structures for 47 addrs.
72336384Ssklower  *  Gosip adds a 3rd.
72436384Ssklower  *
72536384Ssklower  * RETURNS:			true if the addresses are the same type
72636384Ssklower  *
72736384Ssklower  * SIDE EFFECTS:
72836384Ssklower  *
72936384Ssklower  * NOTES:			By type, I mean rfc986, t37, or osinet
73036384Ssklower  *
73136384Ssklower  *					This will first compare afis. If they match, then
73236384Ssklower  *					if the addr is not t37, the idis must be compared.
73336384Ssklower  */
73436384Ssklower iso_eqtype(isoaa, isoab)
73536384Ssklower struct iso_addr	*isoaa;		/* first addr to check */
73636384Ssklower struct iso_addr	*isoab;		/* other addr to check */
73736384Ssklower {
73836384Ssklower 	if (isoaa->isoa_afi == isoab->isoa_afi) {
73936384Ssklower 		if (isoaa->isoa_afi == AFI_37)
74036384Ssklower 			return(1);
74136384Ssklower 		else
74236384Ssklower 			return (!bcmp(&isoaa->isoa_u, &isoab->isoa_u, 2));
74336384Ssklower 	}
74436384Ssklower 	return(0);
74536384Ssklower }
74637469Ssklower #endif notdef
74736384Ssklower /*
74837469Ssklower  * FUNCTION:		iso_localifa()
74936384Ssklower  *
75037469Ssklower  * PURPOSE:			Find an interface addresss having a given destination
75137469Ssklower  *					or at least matching the net.
75236384Ssklower  *
75336384Ssklower  * RETURNS:			ptr to an interface address
75436384Ssklower  *
75536384Ssklower  * SIDE EFFECTS:
75636384Ssklower  *
75736384Ssklower  * NOTES:
75836384Ssklower  */
75936384Ssklower struct iso_ifaddr *
76037469Ssklower iso_localifa(siso)
76137469Ssklower 	register struct sockaddr_iso *siso;
76236384Ssklower {
76336384Ssklower 	register struct iso_ifaddr *ia;
76437469Ssklower 	register char *cp1, *cp2, *cp3;
76537469Ssklower 	register struct ifnet *ifp;
76637469Ssklower 	struct iso_ifaddr *ia_maybe = 0;
76737469Ssklower 	/*
76837469Ssklower 	 * We make one pass looking for both net matches and an exact
76937469Ssklower 	 * dst addr.
77037469Ssklower 	 */
77137469Ssklower 	for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
77237469Ssklower 		if ((ifp = ia->ia_ifp) == 0 || ((ifp->if_flags & IFF_UP) == 0))
77337469Ssklower 			continue;
77437469Ssklower 		if (ifp->if_flags & IFF_POINTOPOINT) {
77537469Ssklower 			if ((ia->ia_dstaddr.siso_family == AF_ISO) &&
77637469Ssklower 				SAME_ISOADDR(&ia->ia_dstaddr, siso))
77737469Ssklower 				return (ia);
77837469Ssklower 			else
77937469Ssklower 				if (SAME_ISOADDR(&ia->ia_addr, siso))
78037469Ssklower 					ia_maybe = ia;
78137469Ssklower 			continue;
78237469Ssklower 		}
78337469Ssklower 		if (ia->ia_sockmask.siso_len) {
78437469Ssklower 			char *cplim = ia->ia_sockmask.siso_len + (char *)&ia->ia_sockmask;
78537469Ssklower 			cp1 = ia->ia_sockmask.siso_data;
78637469Ssklower 			cp2 = siso->siso_data;
78737469Ssklower 			cp3 = ia->ia_addr.siso_data;
78839936Ssklower 			while (cp1 < cplim)
78937469Ssklower 				if (*cp1++ & (*cp2++ ^ *cp3++))
79037469Ssklower 					goto next;
79137469Ssklower 			ia_maybe = ia;
79237469Ssklower 		}
79337469Ssklower 		if (SAME_ISOADDR(&ia->ia_addr, siso))
79437469Ssklower 			return ia;
79537469Ssklower 	next:;
79637469Ssklower 	}
79737469Ssklower 	return ia_maybe;
79836384Ssklower }
79936384Ssklower 
80036384Ssklower #ifdef	NARGOXTWENTYFIVE > 0
80136384Ssklower #include "cons.h"
80236384Ssklower #endif	NARGOXTWENTYFIVE > 0
80336384Ssklower /*
80436384Ssklower  * FUNCTION:		iso_nlctloutput
80536384Ssklower  *
80636384Ssklower  * PURPOSE:			Set options at the network level
80736384Ssklower  *
80836384Ssklower  * RETURNS:			E*
80936384Ssklower  *
81036384Ssklower  * SIDE EFFECTS:
81136384Ssklower  *
81236384Ssklower  * NOTES:			This could embody some of the functions of
81336384Ssklower  *					rclnp_ctloutput and cons_ctloutput.
81436384Ssklower  */
81536384Ssklower iso_nlctloutput(cmd, optname, pcb, m)
81636384Ssklower int			cmd;		/* command:set or get */
81736384Ssklower int			optname;	/* option of interest */
81836384Ssklower caddr_t		pcb;		/* nl pcb */
81936384Ssklower struct mbuf	*m;			/* data for set, buffer for get */
82036384Ssklower {
82136384Ssklower 	struct isopcb	*isop = (struct isopcb *)pcb;
82236384Ssklower 	int				error = 0;	/* return value */
82336384Ssklower 	caddr_t			data;		/* data for option */
82436384Ssklower 	int				data_len;	/* data's length */
82536384Ssklower 
82636384Ssklower 	IFDEBUG(D_ISO)
82736384Ssklower 		printf("iso_nlctloutput: cmd %x, opt %x, pcb %x, m %x\n",
82836384Ssklower 			cmd, optname, pcb, m);
82936384Ssklower 	ENDDEBUG
83036384Ssklower 
83136384Ssklower 	if ((cmd != PRCO_GETOPT) && (cmd != PRCO_SETOPT))
83236384Ssklower 		return(EOPNOTSUPP);
83336384Ssklower 
83436384Ssklower 	data = mtod(m, caddr_t);
83536384Ssklower 	data_len = (m)->m_len;
83636384Ssklower 
83736384Ssklower 	IFDEBUG(D_ISO)
83836384Ssklower 		printf("iso_nlctloutput: data is:\n");
83936384Ssklower 		dump_buf(data, data_len);
84036384Ssklower 	ENDDEBUG
84136384Ssklower 
84236384Ssklower 	switch (optname) {
84336384Ssklower 
84436384Ssklower #ifdef	NARGOXTWENTYFIVE > 0
84536384Ssklower 		case CONSOPT_X25CRUD:
84636384Ssklower 			if (cmd == PRCO_GETOPT) {
84736384Ssklower 				error = EOPNOTSUPP;
84836384Ssklower 				break;
84936384Ssklower 			}
85036384Ssklower 
85136384Ssklower 			if (data_len > MAXX25CRUDLEN) {
85236384Ssklower 				error = EINVAL;
85336384Ssklower 				break;
85436384Ssklower 			}
85536384Ssklower 
85636384Ssklower 			IFDEBUG(D_ISO)
85736384Ssklower 				printf("iso_nlctloutput: setting x25 crud\n");
85836384Ssklower 			ENDDEBUG
85936384Ssklower 
86037469Ssklower 			bcopy(data, (caddr_t)isop->isop_x25crud, (unsigned)data_len);
86136384Ssklower 			isop->isop_x25crud_len = data_len;
86236384Ssklower 			break;
86336384Ssklower #endif	NARGOXTWENTYFIVE > 0
86436384Ssklower 
86536384Ssklower 		default:
86636384Ssklower 			error = EOPNOTSUPP;
86736384Ssklower 	}
86836384Ssklower 
86936384Ssklower 	return error;
87036384Ssklower }
87136384Ssklower #endif ISO
87236384Ssklower 
87336384Ssklower #ifdef ARGO_DEBUG
87436384Ssklower 
87536384Ssklower /*
87636384Ssklower  * FUNCTION:		dump_isoaddr
87736384Ssklower  *
87836384Ssklower  * PURPOSE:			debugging
87936384Ssklower  *
88036384Ssklower  * RETURNS:			nada
88136384Ssklower  *
88236384Ssklower  */
88336384Ssklower dump_isoaddr(s)
88436384Ssklower 	struct sockaddr_iso *s;
88536384Ssklower {
88637469Ssklower 	char *clnp_saddr_isop();
88736384Ssklower 	register int i;
88836384Ssklower 
88936384Ssklower 	if( s->siso_family == AF_ISO) {
89037469Ssklower 		printf("ISO address: suffixlen %d, %s\n",
89138841Ssklower 			s->siso_tlen, clnp_saddr_isop(s));
89236384Ssklower 	} else if( s->siso_family == AF_INET) {
89336384Ssklower 		/* hack */
89436384Ssklower 		struct sockaddr_in *sin = (struct sockaddr_in *)s;
89536384Ssklower 
89636384Ssklower 		printf("%d.%d.%d.%d: %d",
89736384Ssklower 			(sin->sin_addr.s_addr>>24)&0xff,
89836384Ssklower 			(sin->sin_addr.s_addr>>16)&0xff,
89936384Ssklower 			(sin->sin_addr.s_addr>>8)&0xff,
90036384Ssklower 			(sin->sin_addr.s_addr)&0xff,
90136384Ssklower 			sin->sin_port);
90236384Ssklower 	}
90336384Ssklower }
90436384Ssklower 
90536384Ssklower #endif ARGO_DEBUG
906