xref: /csrg-svn/sys/netiso/iso_pcb.c (revision 67541)
149268Sbostic /*-
263222Sbostic  * Copyright (c) 1991, 1993
363222Sbostic  *	The Regents of the University of California.  All rights reserved.
449268Sbostic  *
549268Sbostic  * %sccs.include.redist.c%
649268Sbostic  *
7*67541Ssklower  *	@(#)iso_pcb.c	8.3 (Berkeley) 07/19/94
849268Sbostic  */
949268Sbostic 
1036389Ssklower /***********************************************************
1136389Ssklower 		Copyright IBM Corporation 1987
1236389Ssklower 
1336389Ssklower                       All Rights Reserved
1436389Ssklower 
1536389Ssklower Permission to use, copy, modify, and distribute this software and its
1636389Ssklower documentation for any purpose and without fee is hereby granted,
1736389Ssklower provided that the above copyright notice appear in all copies and that
1836389Ssklower both that copyright notice and this permission notice appear in
1936389Ssklower supporting documentation, and that the name of IBM not be
2036389Ssklower used in advertising or publicity pertaining to distribution of the
2136389Ssklower software without specific, written prior permission.
2236389Ssklower 
2336389Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2436389Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2536389Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2636389Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2736389Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2836389Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2936389Ssklower SOFTWARE.
3036389Ssklower 
3136389Ssklower ******************************************************************/
3236389Ssklower 
3336389Ssklower /*
3436389Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
3536389Ssklower  */
3636389Ssklower /*
3736389Ssklower  * $Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $
3836389Ssklower  * $Source: /usr/argo/sys/netiso/RCS/iso_pcb.c,v $
3936389Ssklower  *
4036389Ssklower  * Iso address family net-layer(s) pcb stuff. NEH 1/29/87
4136389Ssklower  */
4238477Ssklower 
4336389Ssklower #ifdef ISO
4436389Ssklower 
4556533Sbostic #include <sys/param.h>
4656533Sbostic #include <sys/systm.h>
4756533Sbostic #include <sys/mbuf.h>
4856533Sbostic #include <sys/socket.h>
4956533Sbostic #include <sys/socketvar.h>
5056533Sbostic #include <sys/errno.h>
5150235Ssklower 
5256533Sbostic #include <netiso/argo_debug.h>
5356533Sbostic #include <netiso/iso.h>
5456533Sbostic #include <netiso/clnp.h>
5556533Sbostic #include <netinet/in_systm.h>
5656533Sbostic #include <net/if.h>
5756533Sbostic #include <net/route.h>
5856533Sbostic #include <netiso/iso_pcb.h>
5956533Sbostic #include <netiso/iso_var.h>
6056533Sbostic #include <sys/protosw.h>
6136389Ssklower 
6248737Ssklower #ifdef TPCONS
6356533Sbostic #include <netccitt/x25.h>
6456533Sbostic #include <netccitt/pk.h>
6556533Sbostic #include <netccitt/pk_var.h>
6648737Ssklower #endif
6748737Ssklower 
6836389Ssklower #define PCBNULL (struct isopcb *)0
6936389Ssklower struct	iso_addr zeroiso_addr = {
7036389Ssklower 	0
7136389Ssklower };
7236389Ssklower 
7336389Ssklower 
7436389Ssklower /*
7536389Ssklower  * FUNCTION:		iso_pcballoc
7636389Ssklower  *
7736389Ssklower  * PURPOSE:			creates an isopcb structure in an mbuf,
7836389Ssklower  *					with socket (so), and
7936389Ssklower  *					puts it in the queue with head (head)
8036389Ssklower  *
8136389Ssklower  * RETURNS:			0 if OK, ENOBUFS if can't alloc the necessary mbuf
8236389Ssklower  */
8336389Ssklower int
iso_pcballoc(so,head)8436389Ssklower iso_pcballoc(so, head)
8536389Ssklower 	struct socket *so;
8636389Ssklower 	struct isopcb *head;
8736389Ssklower {
8836389Ssklower 	register struct isopcb *isop;
8936389Ssklower 
9036389Ssklower 	IFDEBUG(D_ISO)
9136389Ssklower 		printf("iso_pcballoc(so 0x%x)\n", so);
9236389Ssklower 	ENDDEBUG
9337469Ssklower 	MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT);
9437469Ssklower 	if (isop == NULL)
9536389Ssklower 		return ENOBUFS;
9637469Ssklower 	bzero((caddr_t)isop, sizeof(*isop));
9736389Ssklower 	isop->isop_head = head;
9836389Ssklower 	isop->isop_socket = so;
9936389Ssklower 	insque(isop, head);
10048737Ssklower 	if (so)
10148737Ssklower 		so->so_pcb = (caddr_t)isop;
10236389Ssklower 	return 0;
10336389Ssklower }
10436389Ssklower 
10536389Ssklower /*
10636389Ssklower  * FUNCTION:		iso_pcbbind
10736389Ssklower  *
10836389Ssklower  * PURPOSE:			binds the address given in *(nam) to the socket
10936389Ssklower  *					specified by the isopcb in *(isop)
11036389Ssklower  *					If the given address is zero, it makes sure the
11136389Ssklower  *					address isn't already in use and if it's got a network
11236389Ssklower  *					portion, we look for an interface with that network
11336389Ssklower  *					address.  If the address given is zero, we allocate
11436389Ssklower  *					a port and stuff it in the (nam) structure.
11536389Ssklower  *
11636389Ssklower  * RETURNS:			errno E* or 0 if ok.
11736389Ssklower  *
11836389Ssklower  * SIDE EFFECTS:	increments head->isop_lport if it allocates a port #
11936389Ssklower  *
12036389Ssklower  * NOTES:
12136389Ssklower  */
12237469Ssklower #define	satosiso(sa)	((struct sockaddr_iso *)(sa))
12336389Ssklower int
iso_pcbbind(isop,nam)12436389Ssklower iso_pcbbind(isop, nam)
12536389Ssklower 	register struct isopcb *isop;
12636389Ssklower 	struct mbuf *nam;
12736389Ssklower {
12836389Ssklower 	register struct isopcb *head = isop->isop_head;
12936389Ssklower 	register struct sockaddr_iso *siso;
13037469Ssklower 	struct iso_ifaddr *ia;
13137469Ssklower 	union {
13237469Ssklower 		char data[2];
13337469Ssklower 		u_short s;
13437469Ssklower 	} suf;
13536389Ssklower 
13636389Ssklower 	IFDEBUG(D_ISO)
13736389Ssklower 		printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam);
13836389Ssklower 	ENDDEBUG
13937469Ssklower 	suf.s = 0;
14036389Ssklower 	if (iso_ifaddr == 0) /* any interfaces attached? */
14136389Ssklower 		return EADDRNOTAVAIL;
14237469Ssklower 	if (isop->isop_laddr)  /* already bound */
14336389Ssklower 		return EADDRINUSE;
14437469Ssklower 	if(nam == (struct mbuf *)0) {
14537469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
14638841Ssklower 		isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso);
14738841Ssklower 		isop->isop_sladdr.siso_family = AF_ISO;
14838841Ssklower 		isop->isop_sladdr.siso_tlen = 2;
14937469Ssklower 		isop->isop_sladdr.siso_nlen = 0;
15038841Ssklower 		isop->isop_sladdr.siso_slen = 0;
15138841Ssklower 		isop->isop_sladdr.siso_plen = 0;
15236389Ssklower 		goto noname;
15337469Ssklower 	}
15436389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
15536389Ssklower 	IFDEBUG(D_ISO)
15636389Ssklower 		printf("iso_pcbbind(name len 0x%x)\n", nam->m_len);
15736389Ssklower 		printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr));
15836389Ssklower 	ENDDEBUG
15936389Ssklower 	/*
16036389Ssklower 	 * We would like sort of length check but since some OSI addrs
16136389Ssklower 	 * do not have fixed length, we can't really do much.
16236389Ssklower 	 * The ONLY thing we can say is that an osi addr has to have
16336389Ssklower 	 * at LEAST an afi and one more byte and had better fit into
16436389Ssklower 	 * a struct iso_addr.
16536389Ssklower 	 * However, in fact the size of the whole thing is a struct
16636389Ssklower 	 * sockaddr_iso, so probably this is what we should check for.
16736389Ssklower 	 */
16837469Ssklower 	if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) {
16936389Ssklower 			return ENAMETOOLONG;
17036389Ssklower 	}
17137469Ssklower 	if (siso->siso_nlen) {
17236389Ssklower 		/* non-zero net addr- better match one of our interfaces */
17336389Ssklower 		IFDEBUG(D_ISO)
17436389Ssklower 			printf("iso_pcbbind: bind to NOT zeroisoaddr\n");
17536389Ssklower 		ENDDEBUG
17637469Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
17767464Ssklower 			if (SAME_ISOIFADDR(siso, &ia->ia_addr))
17837469Ssklower 				break;
17937469Ssklower 		if (ia == 0)
18036389Ssklower 			return EADDRNOTAVAIL;
18136389Ssklower 	}
18237469Ssklower 	if (siso->siso_len <= sizeof (isop->isop_sladdr)) {
18337469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
18437469Ssklower 	} else {
18537469Ssklower 		if ((nam = m_copy(nam, 0, (int)M_COPYALL)) == 0)
18637469Ssklower 			return ENOBUFS;
18737469Ssklower 		isop->isop_laddr = mtod(nam, struct sockaddr_iso *);
18837469Ssklower 	}
18937469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len);
19053230Ssklower 	if (siso->siso_tlen == 0)
19153230Ssklower 		goto noname;
19253230Ssklower 	if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
19353230Ssklower 		iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr))
19453230Ssklower 		return EADDRINUSE;
19553230Ssklower 	if (siso->siso_tlen <= 2) {
19653230Ssklower 		bcopy(TSEL(siso), suf.data, sizeof(suf.data));
19753230Ssklower 		suf.s = ntohs(suf.s);
19853230Ssklower 		if((suf.s < ISO_PORT_RESERVED) &&
19950235Ssklower 		   (isop->isop_socket->so_state && SS_PRIV) == 0)
20036389Ssklower 			return EACCES;
20137469Ssklower 	} else {
20237469Ssklower 		register char *cp;
20336389Ssklower noname:
20437469Ssklower 		cp = TSEL(isop->isop_laddr);
205*67541Ssklower 		isop->isop_laddr->siso_tlen = 2;
20636389Ssklower 	IFDEBUG(D_ISO)
20736389Ssklower 		printf("iso_pcbbind noname\n");
20836389Ssklower 	ENDDEBUG
20936389Ssklower 		do {
21036389Ssklower 			if (head->isop_lport++ < ISO_PORT_RESERVED ||
21136389Ssklower 			    head->isop_lport > ISO_PORT_USERRESERVED)
21236389Ssklower 				head->isop_lport = ISO_PORT_RESERVED;
21353230Ssklower 			suf.s = htons(head->isop_lport);
21437469Ssklower 			cp[0] = suf.data[0];
21537469Ssklower 			cp[1] = suf.data[1];
21637469Ssklower 		} while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr));
21737469Ssklower 	}
21836389Ssklower 	IFDEBUG(D_ISO)
21936389Ssklower 		printf("iso_pcbbind returns 0, suf 0x%x\n", suf);
22036389Ssklower 	ENDDEBUG
22136389Ssklower 	return 0;
22236389Ssklower }
22336389Ssklower /*
22436389Ssklower  * FUNCTION:		iso_pcbconnect
22536389Ssklower  *
22636389Ssklower  * PURPOSE:			Make the isopcb (isop) look like it's connected.
22736389Ssklower  *					In other words, give it the peer address given in
22836389Ssklower  *					the mbuf * (nam).   Make sure such a combination
22936389Ssklower  *					of local, peer addresses doesn't already exist
23036389Ssklower  *					for this protocol.  Internet mentality prevails here,
23136389Ssklower  *					wherein a src,dst pair uniquely identifies a connection.
23236389Ssklower  * 					Both net address and port must be specified in argument
23336389Ssklower  *					(nam).
23436389Ssklower  * 					If we don't have a local address for this socket yet,
23536389Ssklower  *					we pick one by calling iso_pcbbind().
23636389Ssklower  *
23736389Ssklower  * RETURNS:			errno E* or 0 if ok.
23836389Ssklower  *
23936389Ssklower  * SIDE EFFECTS:	Looks up a route, which may cause one to be left
24036389Ssklower  *					in the isopcb.
24136389Ssklower  *
24236389Ssklower  * NOTES:
24336389Ssklower  */
24436389Ssklower int
iso_pcbconnect(isop,nam)24536389Ssklower iso_pcbconnect(isop, nam)
24637469Ssklower 	register struct isopcb *isop;
24736389Ssklower 	struct mbuf *nam;
24836389Ssklower {
24936389Ssklower 	register struct sockaddr_iso	*siso = mtod(nam, struct sockaddr_iso *);
25037469Ssklower 	int								local_zero, error = 0;
25137469Ssklower 	struct iso_ifaddr 				*ia;
25236389Ssklower 
25336389Ssklower 	IFDEBUG(D_ISO)
25437469Ssklower 		printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x",
25537469Ssklower 					isop, isop->isop_socket, nam);
25637469Ssklower 		printf("nam->m_len 0x%x), addr:\n", nam->m_len);
25736389Ssklower 		dump_isoaddr(siso);
25836389Ssklower 	ENDDEBUG
25937469Ssklower 	if (nam->m_len < siso->siso_len)
26037469Ssklower 		return EINVAL;
26136389Ssklower 	if (siso->siso_family != AF_ISO)
26236389Ssklower 		return EAFNOSUPPORT;
26338477Ssklower 	if (siso->siso_nlen == 0) {
26438477Ssklower 		if (ia = iso_ifaddr) {
26538477Ssklower 			int nlen = ia->ia_addr.siso_nlen;
26638477Ssklower 			ovbcopy(TSEL(siso), nlen + TSEL(siso),
26738841Ssklower 				siso->siso_plen + siso->siso_tlen + siso->siso_slen);
26838477Ssklower 			bcopy((caddr_t)&ia->ia_addr.siso_addr,
26938477Ssklower 				  (caddr_t)&siso->siso_addr, nlen + 1);
27038477Ssklower 			/* includes siso->siso_nlen = nlen; */
27138477Ssklower 		} else
27238477Ssklower 			return EADDRNOTAVAIL;
27338477Ssklower 	}
27437469Ssklower 	/*
27537469Ssklower 	 * Local zero means either not bound, or bound to a TSEL, but no
27637469Ssklower 	 * particular local interface.  So, if we want to send somebody
27737469Ssklower 	 * we need to choose a return address.
27836389Ssklower 	 */
27937469Ssklower 	local_zero =
28037469Ssklower 		((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0));
28136389Ssklower 	if (local_zero) {
28237469Ssklower 		int flags;
28336389Ssklower 
28436389Ssklower 		IFDEBUG(D_ISO)
28536389Ssklower 			printf("iso_pcbconnect localzero 1\n");
28636389Ssklower 		ENDDEBUG
28736389Ssklower 		/*
28836389Ssklower 		 * If route is known or can be allocated now,
28936389Ssklower 		 * our src addr is taken from the i/f, else punt.
29036389Ssklower 		 */
29137469Ssklower 		flags = isop->isop_socket->so_options & SO_DONTROUTE;
29237469Ssklower 		if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags,
29337469Ssklower 						(struct sockaddr **)0, &ia))
29437469Ssklower 			return error;
29536389Ssklower 		IFDEBUG(D_ISO)
29637469Ssklower 			printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x",
29737469Ssklower 				isop->isop_route.ro_rt);
29837469Ssklower 			printf(" ia 0x%x\n", ia);
29936389Ssklower 		ENDDEBUG
30036389Ssklower 	}
30136389Ssklower 	IFDEBUG(D_ISO)
30236389Ssklower 		printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n",
30336389Ssklower 			isop, isop->isop_socket);
30436389Ssklower 	ENDDEBUG
30536389Ssklower 	if (local_zero) {
30637469Ssklower 		int nlen, tlen, totlen; caddr_t oldtsel, newtsel;
30737469Ssklower 		siso = isop->isop_laddr;
30838841Ssklower 		if (siso == 0 || siso->siso_tlen == 0)
30936389Ssklower 			(void)iso_pcbbind(isop, (struct mbuf *)0);
31037469Ssklower 		/*
31137469Ssklower 		 * Here we have problem of squezeing in a definite network address
31237469Ssklower 		 * into an existing sockaddr_iso, which in fact may not have room
31337469Ssklower 		 * for it.  This gets messy.
31437469Ssklower 		 */
31537469Ssklower 		siso = isop->isop_laddr;
31637469Ssklower 		oldtsel = TSEL(siso);
31738841Ssklower 		tlen = siso->siso_tlen;
31837469Ssklower 		nlen = ia->ia_addr.siso_nlen;
31937469Ssklower 		totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]);
32037469Ssklower 		if ((siso == &isop->isop_sladdr) &&
32137469Ssklower 			(totlen > sizeof(isop->isop_sladdr))) {
32237469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
32337469Ssklower 			if (m == 0)
32437469Ssklower 					return ENOBUFS;
32537469Ssklower 			m->m_len = totlen;
32637469Ssklower 			isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *);
32737469Ssklower 		}
32837469Ssklower 		siso->siso_nlen = ia->ia_addr.siso_nlen;
32937469Ssklower 		newtsel = TSEL(siso);
33037469Ssklower 		ovbcopy(oldtsel, newtsel, tlen);
33137469Ssklower 		bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
33238841Ssklower 		siso->siso_tlen = tlen;
33337469Ssklower 		siso->siso_family = AF_ISO;
33437469Ssklower 		siso->siso_len = totlen;
33537469Ssklower 		siso = mtod(nam, struct sockaddr_iso *);
33636389Ssklower 	}
33736389Ssklower 	IFDEBUG(D_ISO)
33836389Ssklower 		printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n",
33936389Ssklower 			isop, isop->isop_socket);
34036389Ssklower 	ENDDEBUG
34137469Ssklower 	/*
34237469Ssklower 	 * If we had to allocate space to a previous big foreign address,
34337469Ssklower 	 * and for some reason we didn't free it, we reuse it knowing
34437469Ssklower 	 * that is going to be big enough, as sockaddrs are delivered in
34537469Ssklower 	 * 128 byte mbufs.
34637469Ssklower 	 * If the foreign address is small enough, we use default space;
34737469Ssklower 	 * otherwise, we grab an mbuf to copy into.
34837469Ssklower 	 */
34937469Ssklower 	if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) {
35037469Ssklower 		if (siso->siso_len <= sizeof(isop->isop_sfaddr))
35137469Ssklower 			isop->isop_faddr = &isop->isop_sfaddr;
35237469Ssklower 		else {
35337469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
35437469Ssklower 			if (m == 0)
35537469Ssklower 				return ENOBUFS;
35637469Ssklower 			isop->isop_faddr = mtod(m, struct sockaddr_iso *);
35737469Ssklower 		}
35837469Ssklower 	}
35937469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len);
36036389Ssklower 	IFDEBUG(D_ISO)
36136389Ssklower 		printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n",
36236389Ssklower 			isop, isop->isop_socket);
36336389Ssklower 		printf("iso_pcbconnect connected to addr:\n");
36437469Ssklower 		dump_isoaddr(isop->isop_faddr);
36536389Ssklower 		printf("iso_pcbconnect end: src addr:\n");
36637469Ssklower 		dump_isoaddr(isop->isop_laddr);
36736389Ssklower 	ENDDEBUG
36836389Ssklower 	return 0;
36936389Ssklower }
37036389Ssklower 
37136389Ssklower /*
37236389Ssklower  * FUNCTION:		iso_pcbdisconnect()
37336389Ssklower  *
37436389Ssklower  * PURPOSE:			washes away the peer address info so the socket
37536389Ssklower  *					appears to be disconnected.
37636389Ssklower  *					If there's no file descriptor associated with the socket
37736389Ssklower  *					it detaches the pcb.
37836389Ssklower  *
37936389Ssklower  * RETURNS:			Nada.
38036389Ssklower  *
38136389Ssklower  * SIDE EFFECTS:	May detach the pcb.
38236389Ssklower  *
38336389Ssklower  * NOTES:
38436389Ssklower  */
38536389Ssklower void
iso_pcbdisconnect(isop)38636389Ssklower iso_pcbdisconnect(isop)
38736389Ssklower 	struct isopcb *isop;
38836389Ssklower {
38936389Ssklower 	void iso_pcbdetach();
39039934Ssklower 	register struct sockaddr_iso *siso;
39136389Ssklower 
39236389Ssklower 	IFDEBUG(D_ISO)
39336389Ssklower 		printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
39436389Ssklower 	ENDDEBUG
39537469Ssklower 	/*
39637469Ssklower 	 * Preserver binding infnormation if already bound.
39737469Ssklower 	 */
39839934Ssklower 	if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) {
39939934Ssklower 		caddr_t otsel = TSEL(siso);
40039934Ssklower 		siso->siso_nlen = 0;
40139934Ssklower 		ovbcopy(otsel, TSEL(siso), siso->siso_tlen);
40239934Ssklower 	}
40337469Ssklower 	if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
40437469Ssklower 		m_freem(dtom(isop->isop_faddr));
40537469Ssklower 	isop->isop_faddr = 0;
40636389Ssklower 	if (isop->isop_socket->so_state & SS_NOFDREF)
40736389Ssklower 		iso_pcbdetach(isop);
40836389Ssklower }
40936389Ssklower 
41036389Ssklower /*
41136389Ssklower  * FUNCTION:		iso_pcbdetach
41236389Ssklower  *
41336389Ssklower  * PURPOSE:			detach the pcb at *(isop) from it's socket and free
41436389Ssklower  *					the mbufs associated with the pcb..
41536389Ssklower  *					Dequeues (isop) from its head.
41636389Ssklower  *
41736389Ssklower  * RETURNS:			Nada.
41836389Ssklower  *
41936389Ssklower  * SIDE EFFECTS:
42036389Ssklower  *
42136389Ssklower  * NOTES:
42236389Ssklower  */
42336389Ssklower void
iso_pcbdetach(isop)42436389Ssklower iso_pcbdetach(isop)
42536389Ssklower 	struct isopcb *isop;
42636389Ssklower {
42736389Ssklower 	struct socket *so = isop->isop_socket;
42836389Ssklower 
42936389Ssklower 	IFDEBUG(D_ISO)
43036389Ssklower 		printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n",
43136389Ssklower 			isop, isop->isop_socket, so);
43236389Ssklower 	ENDDEBUG
43348737Ssklower #ifdef TPCONS
43450648Ssklower 	if (isop->isop_chan) {
43548737Ssklower 		register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
43648737Ssklower 		if (--isop->isop_refcnt > 0)
43748737Ssklower 			return;
43850648Ssklower 		if (lcp && lcp->lcd_state == DATA_TRANSFER) {
43950648Ssklower 			lcp->lcd_upper = 0;
44050648Ssklower 			lcp->lcd_upnext = 0;
44148737Ssklower 			pk_disconnect(lcp);
44250648Ssklower 		}
44348737Ssklower 		isop->isop_chan = 0;
44448737Ssklower 	}
44548737Ssklower #endif
44648737Ssklower 	if (so) { /* in the x.25 domain, we sometimes have no socket */
44736389Ssklower 		so->so_pcb = 0;
44836389Ssklower 		sofree(so);
44936389Ssklower 	}
45036389Ssklower 	IFDEBUG(D_ISO)
45136389Ssklower 		printf("iso_pcbdetach 2 \n");
45236389Ssklower 	ENDDEBUG
45336389Ssklower 	if (isop->isop_options)
45436389Ssklower 		(void)m_free(isop->isop_options);
45536389Ssklower 	IFDEBUG(D_ISO)
45636389Ssklower 		printf("iso_pcbdetach 3 \n");
45736389Ssklower 	ENDDEBUG
45836389Ssklower 	if (isop->isop_route.ro_rt)
45936389Ssklower 		rtfree(isop->isop_route.ro_rt);
46036389Ssklower 	IFDEBUG(D_ISO)
46136389Ssklower 		printf("iso_pcbdetach 3.1\n");
46236389Ssklower 	ENDDEBUG
46336389Ssklower 	if (isop->isop_clnpcache != NULL) {
46436389Ssklower 		struct clnp_cache *clcp =
46536389Ssklower 			mtod(isop->isop_clnpcache, struct clnp_cache *);
46636389Ssklower 		IFDEBUG(D_ISO)
46736389Ssklower 			printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n",
46836389Ssklower 				clcp, clcp->clc_hdr);
46936389Ssklower 		ENDDEBUG
47036389Ssklower 		if (clcp->clc_hdr != NULL)
47136389Ssklower 			m_free(clcp->clc_hdr);
47236389Ssklower 		IFDEBUG(D_ISO)
47336389Ssklower 			printf("iso_pcbdetach 3.3: freeing cache x%x\n",
47436389Ssklower 				isop->isop_clnpcache);
47536389Ssklower 		ENDDEBUG
47636389Ssklower 		m_free(isop->isop_clnpcache);
47736389Ssklower 	}
47836389Ssklower 	IFDEBUG(D_ISO)
47936389Ssklower 		printf("iso_pcbdetach 4 \n");
48036389Ssklower 	ENDDEBUG
48136389Ssklower 	remque(isop);
48236389Ssklower 	IFDEBUG(D_ISO)
48336389Ssklower 		printf("iso_pcbdetach 5 \n");
48436389Ssklower 	ENDDEBUG
48537469Ssklower 	if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
48637469Ssklower 		m_freem(dtom(isop->isop_laddr));
48740951Ssklower 	free((caddr_t)isop, M_PCB);
48836389Ssklower }
48936389Ssklower 
49036389Ssklower 
49136389Ssklower /*
49236389Ssklower  * FUNCTION:		iso_pcbnotify
49336389Ssklower  *
49436389Ssklower  * PURPOSE:			notify all connections in this protocol's queue (head)
49536389Ssklower  *					that have peer address (dst) of the problem (errno)
49636389Ssklower  *					by calling (notify) on the connections' isopcbs.
49736389Ssklower  *
49836389Ssklower  * RETURNS:			Rien.
49936389Ssklower  *
50036389Ssklower  * SIDE EFFECTS:
50136389Ssklower  *
50236389Ssklower  * NOTES:			(notify) is called at splimp!
50336389Ssklower  */
50436389Ssklower void
iso_pcbnotify(head,siso,errno,notify)50539934Ssklower iso_pcbnotify(head, siso, errno, notify)
50636389Ssklower 	struct isopcb *head;
50739934Ssklower 	register struct sockaddr_iso *siso;
50836389Ssklower 	int errno, (*notify)();
50936389Ssklower {
51039934Ssklower 	register struct isopcb *isop;
51136389Ssklower 	int s = splimp();
51236389Ssklower 
51336389Ssklower 	IFDEBUG(D_ISO)
51436389Ssklower 		printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
51536389Ssklower 	ENDDEBUG
51639934Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
51739934Ssklower 		if (isop->isop_socket == 0 || isop->isop_faddr == 0 ||
51839934Ssklower 			!SAME_ISOADDR(siso, isop->isop_faddr)) {
51936389Ssklower 			IFDEBUG(D_ISO)
52036389Ssklower 				printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
52136389Ssklower 					isop, isop->isop_socket);
52239934Ssklower 				printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr);
52337469Ssklower 				dump_isoaddr(isop->isop_faddr);
52436389Ssklower 			ENDDEBUG
52536389Ssklower 			continue;
52636389Ssklower 		}
52736389Ssklower 		if (errno)
52836389Ssklower 			isop->isop_socket->so_error = errno;
52936389Ssklower 		if (notify)
53039934Ssklower 			(*notify)(isop);
53136389Ssklower 	}
53236389Ssklower 	splx(s);
53336389Ssklower 	IFDEBUG(D_ISO)
53436389Ssklower 		printf("END OF iso_pcbnotify\n" );
53536389Ssklower 	ENDDEBUG
53636389Ssklower }
53736389Ssklower 
53836389Ssklower 
53936389Ssklower /*
54036389Ssklower  * FUNCTION:		iso_pcblookup
54136389Ssklower  *
54236389Ssklower  * PURPOSE:			looks for a given combination of (faddr), (fport),
54336389Ssklower  *					(lport), (laddr) in the queue named by (head).
54436389Ssklower  *					Argument (flags) is ignored.
54536389Ssklower  *
54636389Ssklower  * RETURNS:			ptr to the isopcb if it finds a connection matching
54736389Ssklower  *					these arguments, o.w. returns zero.
54836389Ssklower  *
54936389Ssklower  * SIDE EFFECTS:
55036389Ssklower  *
55136389Ssklower  * NOTES:
55236389Ssklower  */
55336389Ssklower struct isopcb *
iso_pcblookup(head,fportlen,fport,laddr)55437469Ssklower iso_pcblookup(head, fportlen, fport, laddr)
55536389Ssklower 	struct isopcb *head;
55637469Ssklower 	register struct sockaddr_iso *laddr;
55737469Ssklower 	caddr_t fport;
55837469Ssklower 	int fportlen;
55936389Ssklower {
56036389Ssklower 	register struct isopcb *isop;
56137469Ssklower 	register caddr_t lp = TSEL(laddr);
56238841Ssklower 	unsigned int llen = laddr->siso_tlen;
56336389Ssklower 
56436389Ssklower 	IFDEBUG(D_ISO)
56537469Ssklower 		printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n",
56637469Ssklower 			head, laddr, fport);
56736389Ssklower 	ENDDEBUG
56836389Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
56937469Ssklower 		if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
57036389Ssklower 			continue;
57138841Ssklower 		if (isop->isop_laddr->siso_tlen != llen)
57236389Ssklower 			continue;
57337469Ssklower 		if (bcmp(lp, TSEL(isop->isop_laddr), llen))
57437469Ssklower 			continue;
57537469Ssklower 		if (fportlen && isop->isop_faddr &&
57637469Ssklower 			bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen))
57737469Ssklower 			continue;
57836389Ssklower 		/*	PHASE2
57936389Ssklower 		 *	addrmatch1 should be iso_addrmatch(a, b, mask)
58036389Ssklower 		 *	where mask is taken from isop->isop_laddrmask (new field)
58136389Ssklower 		 *	isop_lnetmask will also be available in isop
58236389Ssklower 		if (laddr != &zeroiso_addr &&
58336389Ssklower 			!iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr)))
58436389Ssklower 			continue;
58537469Ssklower 		*/
58637469Ssklower 		if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr)))
58737469Ssklower 			continue;
58836389Ssklower 		return (isop);
58936389Ssklower 	}
59036389Ssklower 	return (struct isopcb *)0;
59136389Ssklower }
59260359Sbostic #endif /* ISO */
593