xref: /csrg-svn/sys/netiso/iso_pcb.c (revision 48737)
136389Ssklower /***********************************************************
236389Ssklower 		Copyright IBM Corporation 1987
336389Ssklower 
436389Ssklower                       All Rights Reserved
536389Ssklower 
636389Ssklower Permission to use, copy, modify, and distribute this software and its
736389Ssklower documentation for any purpose and without fee is hereby granted,
836389Ssklower provided that the above copyright notice appear in all copies and that
936389Ssklower both that copyright notice and this permission notice appear in
1036389Ssklower supporting documentation, and that the name of IBM not be
1136389Ssklower used in advertising or publicity pertaining to distribution of the
1236389Ssklower software without specific, written prior permission.
1336389Ssklower 
1436389Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1536389Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1636389Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1736389Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1836389Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1936389Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036389Ssklower SOFTWARE.
2136389Ssklower 
2236389Ssklower ******************************************************************/
2336389Ssklower 
2436389Ssklower /*
2536389Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2636389Ssklower  */
2736389Ssklower /*
2836389Ssklower  * $Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $
2936389Ssklower  * $Source: /usr/argo/sys/netiso/RCS/iso_pcb.c,v $
30*48737Ssklower  *	@(#)iso_pcb.c	7.8 (Berkeley) 04/26/91
3136389Ssklower  *
3236389Ssklower  * Iso address family net-layer(s) pcb stuff. NEH 1/29/87
3336389Ssklower  */
3438477Ssklower 
3536389Ssklower #ifndef lint
3636389Ssklower static char *rcsid = "$Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $";
3736389Ssklower #endif
3836389Ssklower 
3936389Ssklower #ifdef ISO
4036389Ssklower 
4136389Ssklower #include "param.h"
4236389Ssklower #include "systm.h"
4336389Ssklower #include "user.h"
4436389Ssklower #include "mbuf.h"
4537469Ssklower #include "socket.h"
4637469Ssklower #include "socketvar.h"
4737469Ssklower #include "argo_debug.h"
4837469Ssklower #include "iso.h"
4937469Ssklower #include "clnp.h"
5036389Ssklower #include "../netinet/in_systm.h"
5136389Ssklower #include "../net/if.h"
5236389Ssklower #include "../net/route.h"
5337469Ssklower #include "iso_pcb.h"
5437469Ssklower #include "iso_var.h"
5536389Ssklower #include "protosw.h"
5636389Ssklower 
57*48737Ssklower #ifdef TPCONS
58*48737Ssklower #include "../netccitt/x25.h"
59*48737Ssklower #include "../netccitt/pk.h"
60*48737Ssklower #include "../netccitt/pk_var.h"
61*48737Ssklower #endif
62*48737Ssklower 
6336389Ssklower #define PCBNULL (struct isopcb *)0
6436389Ssklower struct	iso_addr zeroiso_addr = {
6536389Ssklower 	0
6636389Ssklower };
6736389Ssklower 
6836389Ssklower 
6936389Ssklower /*
7036389Ssklower  * FUNCTION:		iso_pcballoc
7136389Ssklower  *
7236389Ssklower  * PURPOSE:			creates an isopcb structure in an mbuf,
7336389Ssklower  *					with socket (so), and
7436389Ssklower  *					puts it in the queue with head (head)
7536389Ssklower  *
7636389Ssklower  * RETURNS:			0 if OK, ENOBUFS if can't alloc the necessary mbuf
7736389Ssklower  */
7836389Ssklower int
7936389Ssklower iso_pcballoc(so, head)
8036389Ssklower 	struct socket *so;
8136389Ssklower 	struct isopcb *head;
8236389Ssklower {
8336389Ssklower 	register struct isopcb *isop;
8436389Ssklower 
8536389Ssklower 	IFDEBUG(D_ISO)
8636389Ssklower 		printf("iso_pcballoc(so 0x%x)\n", so);
8736389Ssklower 	ENDDEBUG
8837469Ssklower 	MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT);
8937469Ssklower 	if (isop == NULL)
9036389Ssklower 		return ENOBUFS;
9137469Ssklower 	bzero((caddr_t)isop, sizeof(*isop));
9236389Ssklower 	isop->isop_head = head;
9336389Ssklower 	isop->isop_socket = so;
9436389Ssklower 	insque(isop, head);
95*48737Ssklower 	if (so)
96*48737Ssklower 		so->so_pcb = (caddr_t)isop;
9736389Ssklower 	return 0;
9836389Ssklower }
9936389Ssklower 
10036389Ssklower /*
10136389Ssklower  * FUNCTION:		iso_pcbbind
10236389Ssklower  *
10336389Ssklower  * PURPOSE:			binds the address given in *(nam) to the socket
10436389Ssklower  *					specified by the isopcb in *(isop)
10536389Ssklower  *					If the given address is zero, it makes sure the
10636389Ssklower  *					address isn't already in use and if it's got a network
10736389Ssklower  *					portion, we look for an interface with that network
10836389Ssklower  *					address.  If the address given is zero, we allocate
10936389Ssklower  *					a port and stuff it in the (nam) structure.
11036389Ssklower  *
11136389Ssklower  * RETURNS:			errno E* or 0 if ok.
11236389Ssklower  *
11336389Ssklower  * SIDE EFFECTS:	increments head->isop_lport if it allocates a port #
11436389Ssklower  *
11536389Ssklower  * NOTES:
11636389Ssklower  */
11737469Ssklower #define	satosiso(sa)	((struct sockaddr_iso *)(sa))
11836389Ssklower int
11936389Ssklower iso_pcbbind(isop, nam)
12036389Ssklower 	register struct isopcb *isop;
12136389Ssklower 	struct mbuf *nam;
12236389Ssklower {
12336389Ssklower 	register struct isopcb *head = isop->isop_head;
12436389Ssklower 	register struct sockaddr_iso *siso;
12537469Ssklower 	struct iso_ifaddr *ia;
12637469Ssklower 	union {
12737469Ssklower 		char data[2];
12837469Ssklower 		u_short s;
12937469Ssklower 	} suf;
13036389Ssklower 
13136389Ssklower 	IFDEBUG(D_ISO)
13236389Ssklower 		printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam);
13336389Ssklower 	ENDDEBUG
13437469Ssklower 	suf.s = 0;
13536389Ssklower 	if (iso_ifaddr == 0) /* any interfaces attached? */
13636389Ssklower 		return EADDRNOTAVAIL;
13737469Ssklower 	if (isop->isop_laddr)  /* already bound */
13836389Ssklower 		return EADDRINUSE;
13937469Ssklower 	if(nam == (struct mbuf *)0) {
14037469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
14138841Ssklower 		isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso);
14238841Ssklower 		isop->isop_sladdr.siso_family = AF_ISO;
14338841Ssklower 		isop->isop_sladdr.siso_tlen = 2;
14437469Ssklower 		isop->isop_sladdr.siso_nlen = 0;
14538841Ssklower 		isop->isop_sladdr.siso_slen = 0;
14638841Ssklower 		isop->isop_sladdr.siso_plen = 0;
14736389Ssklower 		goto noname;
14837469Ssklower 	}
14936389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
15036389Ssklower 	IFDEBUG(D_ISO)
15136389Ssklower 		printf("iso_pcbbind(name len 0x%x)\n", nam->m_len);
15236389Ssklower 		printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr));
15336389Ssklower 	ENDDEBUG
15436389Ssklower 	/*
15536389Ssklower 	 * We would like sort of length check but since some OSI addrs
15636389Ssklower 	 * do not have fixed length, we can't really do much.
15736389Ssklower 	 * The ONLY thing we can say is that an osi addr has to have
15836389Ssklower 	 * at LEAST an afi and one more byte and had better fit into
15936389Ssklower 	 * a struct iso_addr.
16036389Ssklower 	 * However, in fact the size of the whole thing is a struct
16136389Ssklower 	 * sockaddr_iso, so probably this is what we should check for.
16236389Ssklower 	 */
16337469Ssklower 	if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) {
16436389Ssklower 			return ENAMETOOLONG;
16536389Ssklower 	}
16638841Ssklower 	if (siso->siso_tlen) {
16737469Ssklower 			register char *cp = TSEL(siso);
16837469Ssklower 			suf.data[0] = cp[0];
16937469Ssklower 			suf.data[1] = cp[1];
17037469Ssklower 	}
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)
17737469Ssklower 			if (SAME_ISOADDR(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);
19039934Ssklower 	if (suf.s || siso->siso_tlen != 2) {
19138841Ssklower 		if((suf.s < ISO_PORT_RESERVED) && (siso->siso_tlen <= 2) &&
19237469Ssklower 		   (u.u_uid != 0))
19336389Ssklower 			return EACCES;
19436389Ssklower 		if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
19537469Ssklower 			iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr))
19636389Ssklower 			return EADDRINUSE;
19737469Ssklower 	} else {
19837469Ssklower 		register char *cp;
19936389Ssklower noname:
20037469Ssklower 		cp = TSEL(isop->isop_laddr);
20136389Ssklower 	IFDEBUG(D_ISO)
20236389Ssklower 		printf("iso_pcbbind noname\n");
20336389Ssklower 	ENDDEBUG
20436389Ssklower 		do {
20536389Ssklower 			if (head->isop_lport++ < ISO_PORT_RESERVED ||
20636389Ssklower 			    head->isop_lport > ISO_PORT_USERRESERVED)
20736389Ssklower 				head->isop_lport = ISO_PORT_RESERVED;
20837469Ssklower 			suf.s = head->isop_lport;
20937469Ssklower 			cp[0] = suf.data[0];
21037469Ssklower 			cp[1] = suf.data[1];
21137469Ssklower 		} while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr));
21237469Ssklower 	}
21336389Ssklower 	IFDEBUG(D_ISO)
21436389Ssklower 		printf("iso_pcbbind returns 0, suf 0x%x\n", suf);
21536389Ssklower 	ENDDEBUG
21636389Ssklower 	return 0;
21736389Ssklower }
21836389Ssklower /*
21936389Ssklower  * FUNCTION:		iso_pcbconnect
22036389Ssklower  *
22136389Ssklower  * PURPOSE:			Make the isopcb (isop) look like it's connected.
22236389Ssklower  *					In other words, give it the peer address given in
22336389Ssklower  *					the mbuf * (nam).   Make sure such a combination
22436389Ssklower  *					of local, peer addresses doesn't already exist
22536389Ssklower  *					for this protocol.  Internet mentality prevails here,
22636389Ssklower  *					wherein a src,dst pair uniquely identifies a connection.
22736389Ssklower  * 					Both net address and port must be specified in argument
22836389Ssklower  *					(nam).
22936389Ssklower  * 					If we don't have a local address for this socket yet,
23036389Ssklower  *					we pick one by calling iso_pcbbind().
23136389Ssklower  *
23236389Ssklower  * RETURNS:			errno E* or 0 if ok.
23336389Ssklower  *
23436389Ssklower  * SIDE EFFECTS:	Looks up a route, which may cause one to be left
23536389Ssklower  *					in the isopcb.
23636389Ssklower  *
23736389Ssklower  * NOTES:
23836389Ssklower  */
23936389Ssklower int
24036389Ssklower iso_pcbconnect(isop, nam)
24137469Ssklower 	register struct isopcb *isop;
24236389Ssklower 	struct mbuf *nam;
24336389Ssklower {
24436389Ssklower 	register struct sockaddr_iso	*siso = mtod(nam, struct sockaddr_iso *);
24537469Ssklower 	int								local_zero, error = 0;
24637469Ssklower 	struct iso_ifaddr 				*ia;
24736389Ssklower 
24836389Ssklower 	IFDEBUG(D_ISO)
24937469Ssklower 		printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x",
25037469Ssklower 					isop, isop->isop_socket, nam);
25137469Ssklower 		printf("nam->m_len 0x%x), addr:\n", nam->m_len);
25236389Ssklower 		dump_isoaddr(siso);
25336389Ssklower 	ENDDEBUG
25437469Ssklower 	if (nam->m_len < siso->siso_len)
25537469Ssklower 		return EINVAL;
25636389Ssklower 	if (siso->siso_family != AF_ISO)
25736389Ssklower 		return EAFNOSUPPORT;
25838477Ssklower 	if (siso->siso_nlen == 0) {
25938477Ssklower 		if (ia = iso_ifaddr) {
26038477Ssklower 			int nlen = ia->ia_addr.siso_nlen;
26138477Ssklower 			ovbcopy(TSEL(siso), nlen + TSEL(siso),
26238841Ssklower 				siso->siso_plen + siso->siso_tlen + siso->siso_slen);
26338477Ssklower 			bcopy((caddr_t)&ia->ia_addr.siso_addr,
26438477Ssklower 				  (caddr_t)&siso->siso_addr, nlen + 1);
26538477Ssklower 			/* includes siso->siso_nlen = nlen; */
26638477Ssklower 		} else
26738477Ssklower 			return EADDRNOTAVAIL;
26838477Ssklower 	}
26937469Ssklower 	/*
27037469Ssklower 	 * Local zero means either not bound, or bound to a TSEL, but no
27137469Ssklower 	 * particular local interface.  So, if we want to send somebody
27237469Ssklower 	 * we need to choose a return address.
27336389Ssklower 	 */
27437469Ssklower 	local_zero =
27537469Ssklower 		((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0));
27636389Ssklower 	if (local_zero) {
27737469Ssklower 		int flags;
27836389Ssklower 
27936389Ssklower 		IFDEBUG(D_ISO)
28036389Ssklower 			printf("iso_pcbconnect localzero 1\n");
28136389Ssklower 		ENDDEBUG
28236389Ssklower 		/*
28336389Ssklower 		 * If route is known or can be allocated now,
28436389Ssklower 		 * our src addr is taken from the i/f, else punt.
28536389Ssklower 		 */
28637469Ssklower 		flags = isop->isop_socket->so_options & SO_DONTROUTE;
28737469Ssklower 		if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags,
28837469Ssklower 						(struct sockaddr **)0, &ia))
28937469Ssklower 			return error;
29036389Ssklower 		IFDEBUG(D_ISO)
29137469Ssklower 			printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x",
29237469Ssklower 				isop->isop_route.ro_rt);
29337469Ssklower 			printf(" ia 0x%x\n", ia);
29436389Ssklower 		ENDDEBUG
29536389Ssklower 	}
29636389Ssklower 	IFDEBUG(D_ISO)
29736389Ssklower 		printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n",
29836389Ssklower 			isop, isop->isop_socket);
29936389Ssklower 	ENDDEBUG
30036389Ssklower 	if (local_zero) {
30137469Ssklower 		int nlen, tlen, totlen; caddr_t oldtsel, newtsel;
30237469Ssklower 		siso = isop->isop_laddr;
30338841Ssklower 		if (siso == 0 || siso->siso_tlen == 0)
30436389Ssklower 			(void)iso_pcbbind(isop, (struct mbuf *)0);
30537469Ssklower 		/*
30637469Ssklower 		 * Here we have problem of squezeing in a definite network address
30737469Ssklower 		 * into an existing sockaddr_iso, which in fact may not have room
30837469Ssklower 		 * for it.  This gets messy.
30937469Ssklower 		 */
31037469Ssklower 		siso = isop->isop_laddr;
31137469Ssklower 		oldtsel = TSEL(siso);
31238841Ssklower 		tlen = siso->siso_tlen;
31337469Ssklower 		nlen = ia->ia_addr.siso_nlen;
31437469Ssklower 		totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]);
31537469Ssklower 		if ((siso == &isop->isop_sladdr) &&
31637469Ssklower 			(totlen > sizeof(isop->isop_sladdr))) {
31737469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
31837469Ssklower 			if (m == 0)
31937469Ssklower 					return ENOBUFS;
32037469Ssklower 			m->m_len = totlen;
32137469Ssklower 			isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *);
32237469Ssklower 		}
32337469Ssklower 		siso->siso_nlen = ia->ia_addr.siso_nlen;
32437469Ssklower 		newtsel = TSEL(siso);
32537469Ssklower 		ovbcopy(oldtsel, newtsel, tlen);
32637469Ssklower 		bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
32738841Ssklower 		siso->siso_tlen = tlen;
32837469Ssklower 		siso->siso_family = AF_ISO;
32937469Ssklower 		siso->siso_len = totlen;
33037469Ssklower 		siso = mtod(nam, struct sockaddr_iso *);
33136389Ssklower 	}
33236389Ssklower 	IFDEBUG(D_ISO)
33336389Ssklower 		printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n",
33436389Ssklower 			isop, isop->isop_socket);
33536389Ssklower 	ENDDEBUG
33637469Ssklower 	/*
33737469Ssklower 	 * If we had to allocate space to a previous big foreign address,
33837469Ssklower 	 * and for some reason we didn't free it, we reuse it knowing
33937469Ssklower 	 * that is going to be big enough, as sockaddrs are delivered in
34037469Ssklower 	 * 128 byte mbufs.
34137469Ssklower 	 * If the foreign address is small enough, we use default space;
34237469Ssklower 	 * otherwise, we grab an mbuf to copy into.
34337469Ssklower 	 */
34437469Ssklower 	if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) {
34537469Ssklower 		if (siso->siso_len <= sizeof(isop->isop_sfaddr))
34637469Ssklower 			isop->isop_faddr = &isop->isop_sfaddr;
34737469Ssklower 		else {
34837469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
34937469Ssklower 			if (m == 0)
35037469Ssklower 				return ENOBUFS;
35137469Ssklower 			isop->isop_faddr = mtod(m, struct sockaddr_iso *);
35237469Ssklower 		}
35337469Ssklower 	}
35437469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len);
35536389Ssklower 	IFDEBUG(D_ISO)
35636389Ssklower 		printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n",
35736389Ssklower 			isop, isop->isop_socket);
35836389Ssklower 		printf("iso_pcbconnect connected to addr:\n");
35937469Ssklower 		dump_isoaddr(isop->isop_faddr);
36036389Ssklower 		printf("iso_pcbconnect end: src addr:\n");
36137469Ssklower 		dump_isoaddr(isop->isop_laddr);
36236389Ssklower 	ENDDEBUG
36336389Ssklower 	return 0;
36436389Ssklower }
36536389Ssklower 
36636389Ssklower /*
36736389Ssklower  * FUNCTION:		iso_pcbdisconnect()
36836389Ssklower  *
36936389Ssklower  * PURPOSE:			washes away the peer address info so the socket
37036389Ssklower  *					appears to be disconnected.
37136389Ssklower  *					If there's no file descriptor associated with the socket
37236389Ssklower  *					it detaches the pcb.
37336389Ssklower  *
37436389Ssklower  * RETURNS:			Nada.
37536389Ssklower  *
37636389Ssklower  * SIDE EFFECTS:	May detach the pcb.
37736389Ssklower  *
37836389Ssklower  * NOTES:
37936389Ssklower  */
38036389Ssklower void
38136389Ssklower iso_pcbdisconnect(isop)
38236389Ssklower 	struct isopcb *isop;
38336389Ssklower {
38436389Ssklower 	void iso_pcbdetach();
38539934Ssklower 	register struct sockaddr_iso *siso;
38636389Ssklower 
38736389Ssklower 	IFDEBUG(D_ISO)
38836389Ssklower 		printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
38936389Ssklower 	ENDDEBUG
39037469Ssklower 	/*
39137469Ssklower 	 * Preserver binding infnormation if already bound.
39237469Ssklower 	 */
39339934Ssklower 	if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) {
39439934Ssklower 		caddr_t otsel = TSEL(siso);
39539934Ssklower 		siso->siso_nlen = 0;
39639934Ssklower 		ovbcopy(otsel, TSEL(siso), siso->siso_tlen);
39739934Ssklower 	}
39837469Ssklower 	if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
39937469Ssklower 		m_freem(dtom(isop->isop_faddr));
40037469Ssklower 	isop->isop_faddr = 0;
40136389Ssklower 	if (isop->isop_socket->so_state & SS_NOFDREF)
40236389Ssklower 		iso_pcbdetach(isop);
40336389Ssklower }
40436389Ssklower 
40536389Ssklower /*
40636389Ssklower  * FUNCTION:		iso_pcbdetach
40736389Ssklower  *
40836389Ssklower  * PURPOSE:			detach the pcb at *(isop) from it's socket and free
40936389Ssklower  *					the mbufs associated with the pcb..
41036389Ssklower  *					Dequeues (isop) from its head.
41136389Ssklower  *
41236389Ssklower  * RETURNS:			Nada.
41336389Ssklower  *
41436389Ssklower  * SIDE EFFECTS:
41536389Ssklower  *
41636389Ssklower  * NOTES:
41736389Ssklower  */
41836389Ssklower void
41936389Ssklower iso_pcbdetach(isop)
42036389Ssklower 	struct isopcb *isop;
42136389Ssklower {
42236389Ssklower 	struct socket *so = isop->isop_socket;
42336389Ssklower 
42436389Ssklower 	IFDEBUG(D_ISO)
42536389Ssklower 		printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n",
42636389Ssklower 			isop, isop->isop_socket, so);
42736389Ssklower 	ENDDEBUG
428*48737Ssklower #ifdef TPCONS
429*48737Ssklower 	if (isop->isop_refcnt) {
430*48737Ssklower 		register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
431*48737Ssklower 		if (--isop->isop_refcnt > 0)
432*48737Ssklower 			return;
433*48737Ssklower 		if (lcp && lcp->lcd_state == DATA_TRANSFER)
434*48737Ssklower 			pk_disconnect(lcp);
435*48737Ssklower 		isop->isop_chan = 0;
436*48737Ssklower 	}
437*48737Ssklower #endif
438*48737Ssklower 	if (so) { /* in the x.25 domain, we sometimes have no socket */
43936389Ssklower 		so->so_pcb = 0;
44036389Ssklower 		sofree(so);
44136389Ssklower 	}
44236389Ssklower 	IFDEBUG(D_ISO)
44336389Ssklower 		printf("iso_pcbdetach 2 \n");
44436389Ssklower 	ENDDEBUG
44536389Ssklower 	if (isop->isop_options)
44636389Ssklower 		(void)m_free(isop->isop_options);
44736389Ssklower 	IFDEBUG(D_ISO)
44836389Ssklower 		printf("iso_pcbdetach 3 \n");
44936389Ssklower 	ENDDEBUG
45036389Ssklower 	if (isop->isop_route.ro_rt)
45136389Ssklower 		rtfree(isop->isop_route.ro_rt);
45236389Ssklower 	IFDEBUG(D_ISO)
45336389Ssklower 		printf("iso_pcbdetach 3.1\n");
45436389Ssklower 	ENDDEBUG
45536389Ssklower 	if (isop->isop_clnpcache != NULL) {
45636389Ssklower 		struct clnp_cache *clcp =
45736389Ssklower 			mtod(isop->isop_clnpcache, struct clnp_cache *);
45836389Ssklower 		IFDEBUG(D_ISO)
45936389Ssklower 			printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n",
46036389Ssklower 				clcp, clcp->clc_hdr);
46136389Ssklower 		ENDDEBUG
46236389Ssklower 		if (clcp->clc_hdr != NULL)
46336389Ssklower 			m_free(clcp->clc_hdr);
46436389Ssklower 		IFDEBUG(D_ISO)
46536389Ssklower 			printf("iso_pcbdetach 3.3: freeing cache x%x\n",
46636389Ssklower 				isop->isop_clnpcache);
46736389Ssklower 		ENDDEBUG
46836389Ssklower 		m_free(isop->isop_clnpcache);
46936389Ssklower 	}
47036389Ssklower 	IFDEBUG(D_ISO)
47136389Ssklower 		printf("iso_pcbdetach 4 \n");
47236389Ssklower 	ENDDEBUG
47336389Ssklower 	remque(isop);
47436389Ssklower 	IFDEBUG(D_ISO)
47536389Ssklower 		printf("iso_pcbdetach 5 \n");
47636389Ssklower 	ENDDEBUG
47737469Ssklower 	if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
47837469Ssklower 		m_freem(dtom(isop->isop_laddr));
47940951Ssklower 	free((caddr_t)isop, M_PCB);
48036389Ssklower }
48136389Ssklower 
48236389Ssklower 
48336389Ssklower /*
48436389Ssklower  * FUNCTION:		iso_pcbnotify
48536389Ssklower  *
48636389Ssklower  * PURPOSE:			notify all connections in this protocol's queue (head)
48736389Ssklower  *					that have peer address (dst) of the problem (errno)
48836389Ssklower  *					by calling (notify) on the connections' isopcbs.
48936389Ssklower  *
49036389Ssklower  * RETURNS:			Rien.
49136389Ssklower  *
49236389Ssklower  * SIDE EFFECTS:
49336389Ssklower  *
49436389Ssklower  * NOTES:			(notify) is called at splimp!
49536389Ssklower  */
49636389Ssklower void
49739934Ssklower iso_pcbnotify(head, siso, errno, notify)
49836389Ssklower 	struct isopcb *head;
49939934Ssklower 	register struct sockaddr_iso *siso;
50036389Ssklower 	int errno, (*notify)();
50136389Ssklower {
50239934Ssklower 	register struct isopcb *isop;
50336389Ssklower 	int s = splimp();
50436389Ssklower 
50536389Ssklower 	IFDEBUG(D_ISO)
50636389Ssklower 		printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
50736389Ssklower 	ENDDEBUG
50839934Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
50939934Ssklower 		if (isop->isop_socket == 0 || isop->isop_faddr == 0 ||
51039934Ssklower 			!SAME_ISOADDR(siso, isop->isop_faddr)) {
51136389Ssklower 			IFDEBUG(D_ISO)
51236389Ssklower 				printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
51336389Ssklower 					isop, isop->isop_socket);
51439934Ssklower 				printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr);
51537469Ssklower 				dump_isoaddr(isop->isop_faddr);
51636389Ssklower 			ENDDEBUG
51736389Ssklower 			continue;
51836389Ssklower 		}
51936389Ssklower 		if (errno)
52036389Ssklower 			isop->isop_socket->so_error = errno;
52136389Ssklower 		if (notify)
52239934Ssklower 			(*notify)(isop);
52336389Ssklower 	}
52436389Ssklower 	splx(s);
52536389Ssklower 	IFDEBUG(D_ISO)
52636389Ssklower 		printf("END OF iso_pcbnotify\n" );
52736389Ssklower 	ENDDEBUG
52836389Ssklower }
52936389Ssklower 
53036389Ssklower 
53136389Ssklower /*
53236389Ssklower  * FUNCTION:		iso_pcblookup
53336389Ssklower  *
53436389Ssklower  * PURPOSE:			looks for a given combination of (faddr), (fport),
53536389Ssklower  *					(lport), (laddr) in the queue named by (head).
53636389Ssklower  *					Argument (flags) is ignored.
53736389Ssklower  *
53836389Ssklower  * RETURNS:			ptr to the isopcb if it finds a connection matching
53936389Ssklower  *					these arguments, o.w. returns zero.
54036389Ssklower  *
54136389Ssklower  * SIDE EFFECTS:
54236389Ssklower  *
54336389Ssklower  * NOTES:
54436389Ssklower  */
54536389Ssklower struct isopcb *
54637469Ssklower iso_pcblookup(head, fportlen, fport, laddr)
54736389Ssklower 	struct isopcb *head;
54837469Ssklower 	register struct sockaddr_iso *laddr;
54937469Ssklower 	caddr_t fport;
55037469Ssklower 	int fportlen;
55136389Ssklower {
55236389Ssklower 	register struct isopcb *isop;
55337469Ssklower 	register caddr_t lp = TSEL(laddr);
55438841Ssklower 	unsigned int llen = laddr->siso_tlen;
55536389Ssklower 
55636389Ssklower 	IFDEBUG(D_ISO)
55737469Ssklower 		printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n",
55837469Ssklower 			head, laddr, fport);
55936389Ssklower 	ENDDEBUG
56036389Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
56137469Ssklower 		if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
56236389Ssklower 			continue;
56338841Ssklower 		if (isop->isop_laddr->siso_tlen != llen)
56436389Ssklower 			continue;
56537469Ssklower 		if (bcmp(lp, TSEL(isop->isop_laddr), llen))
56637469Ssklower 			continue;
56737469Ssklower 		if (fportlen && isop->isop_faddr &&
56837469Ssklower 			bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen))
56937469Ssklower 			continue;
57036389Ssklower 		/*	PHASE2
57136389Ssklower 		 *	addrmatch1 should be iso_addrmatch(a, b, mask)
57236389Ssklower 		 *	where mask is taken from isop->isop_laddrmask (new field)
57336389Ssklower 		 *	isop_lnetmask will also be available in isop
57436389Ssklower 		if (laddr != &zeroiso_addr &&
57536389Ssklower 			!iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr)))
57636389Ssklower 			continue;
57737469Ssklower 		*/
57837469Ssklower 		if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr)))
57937469Ssklower 			continue;
58036389Ssklower 		return (isop);
58136389Ssklower 	}
58236389Ssklower 	return (struct isopcb *)0;
58336389Ssklower }
58436389Ssklower #endif ISO
585