xref: /csrg-svn/sys/netiso/iso_pcb.c (revision 39934)
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*39934Ssklower  *	@(#)iso_pcb.c	7.6 (Berkeley) 01/17/90
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 
5736389Ssklower #define PCBNULL (struct isopcb *)0
5836389Ssklower struct	iso_addr zeroiso_addr = {
5936389Ssklower 	0
6036389Ssklower };
6136389Ssklower 
6236389Ssklower 
6336389Ssklower /*
6436389Ssklower  * FUNCTION:		iso_pcballoc
6536389Ssklower  *
6636389Ssklower  * PURPOSE:			creates an isopcb structure in an mbuf,
6736389Ssklower  *					with socket (so), and
6836389Ssklower  *					puts it in the queue with head (head)
6936389Ssklower  *
7036389Ssklower  * RETURNS:			0 if OK, ENOBUFS if can't alloc the necessary mbuf
7136389Ssklower  */
7236389Ssklower int
7336389Ssklower iso_pcballoc(so, head)
7436389Ssklower 	struct socket *so;
7536389Ssklower 	struct isopcb *head;
7636389Ssklower {
7736389Ssklower 	register struct isopcb *isop;
7836389Ssklower 
7936389Ssklower 	IFDEBUG(D_ISO)
8036389Ssklower 		printf("iso_pcballoc(so 0x%x)\n", so);
8136389Ssklower 	ENDDEBUG
8237469Ssklower 	MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT);
8337469Ssklower 	if (isop == NULL)
8436389Ssklower 		return ENOBUFS;
8537469Ssklower 	bzero((caddr_t)isop, sizeof(*isop));
8636389Ssklower 	isop->isop_head = head;
8736389Ssklower 	isop->isop_socket = so;
8836389Ssklower 	insque(isop, head);
8936389Ssklower 	so->so_pcb = (caddr_t)isop;
9036389Ssklower 	return 0;
9136389Ssklower }
9236389Ssklower 
9336389Ssklower /*
9436389Ssklower  * FUNCTION:		iso_pcbbind
9536389Ssklower  *
9636389Ssklower  * PURPOSE:			binds the address given in *(nam) to the socket
9736389Ssklower  *					specified by the isopcb in *(isop)
9836389Ssklower  *					If the given address is zero, it makes sure the
9936389Ssklower  *					address isn't already in use and if it's got a network
10036389Ssklower  *					portion, we look for an interface with that network
10136389Ssklower  *					address.  If the address given is zero, we allocate
10236389Ssklower  *					a port and stuff it in the (nam) structure.
10336389Ssklower  *
10436389Ssklower  * RETURNS:			errno E* or 0 if ok.
10536389Ssklower  *
10636389Ssklower  * SIDE EFFECTS:	increments head->isop_lport if it allocates a port #
10736389Ssklower  *
10836389Ssklower  * NOTES:
10936389Ssklower  */
11037469Ssklower #define	satosiso(sa)	((struct sockaddr_iso *)(sa))
11136389Ssklower int
11236389Ssklower iso_pcbbind(isop, nam)
11336389Ssklower 	register struct isopcb *isop;
11436389Ssklower 	struct mbuf *nam;
11536389Ssklower {
11636389Ssklower 	register struct isopcb *head = isop->isop_head;
11736389Ssklower 	register struct sockaddr_iso *siso;
11837469Ssklower 	struct iso_ifaddr *ia;
11937469Ssklower 	union {
12037469Ssklower 		char data[2];
12137469Ssklower 		u_short s;
12237469Ssklower 	} suf;
12336389Ssklower 
12436389Ssklower 	IFDEBUG(D_ISO)
12536389Ssklower 		printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam);
12636389Ssklower 	ENDDEBUG
12737469Ssklower 	suf.s = 0;
12836389Ssklower 	if (iso_ifaddr == 0) /* any interfaces attached? */
12936389Ssklower 		return EADDRNOTAVAIL;
13037469Ssklower 	if (isop->isop_laddr)  /* already bound */
13136389Ssklower 		return EADDRINUSE;
13237469Ssklower 	if(nam == (struct mbuf *)0) {
13337469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
13438841Ssklower 		isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso);
13538841Ssklower 		isop->isop_sladdr.siso_family = AF_ISO;
13638841Ssklower 		isop->isop_sladdr.siso_tlen = 2;
13737469Ssklower 		isop->isop_sladdr.siso_nlen = 0;
13838841Ssklower 		isop->isop_sladdr.siso_slen = 0;
13938841Ssklower 		isop->isop_sladdr.siso_plen = 0;
14036389Ssklower 		goto noname;
14137469Ssklower 	}
14236389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
14336389Ssklower 	IFDEBUG(D_ISO)
14436389Ssklower 		printf("iso_pcbbind(name len 0x%x)\n", nam->m_len);
14536389Ssklower 		printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr));
14636389Ssklower 	ENDDEBUG
14736389Ssklower 	/*
14836389Ssklower 	 * We would like sort of length check but since some OSI addrs
14936389Ssklower 	 * do not have fixed length, we can't really do much.
15036389Ssklower 	 * The ONLY thing we can say is that an osi addr has to have
15136389Ssklower 	 * at LEAST an afi and one more byte and had better fit into
15236389Ssklower 	 * a struct iso_addr.
15336389Ssklower 	 * However, in fact the size of the whole thing is a struct
15436389Ssklower 	 * sockaddr_iso, so probably this is what we should check for.
15536389Ssklower 	 */
15637469Ssklower 	if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) {
15736389Ssklower 			return ENAMETOOLONG;
15836389Ssklower 	}
15938841Ssklower 	if (siso->siso_tlen) {
16037469Ssklower 			register char *cp = TSEL(siso);
16137469Ssklower 			suf.data[0] = cp[0];
16237469Ssklower 			suf.data[1] = cp[1];
16337469Ssklower 	}
16437469Ssklower 	if (siso->siso_nlen) {
16536389Ssklower 		/* non-zero net addr- better match one of our interfaces */
16636389Ssklower 		IFDEBUG(D_ISO)
16736389Ssklower 			printf("iso_pcbbind: bind to NOT zeroisoaddr\n");
16836389Ssklower 		ENDDEBUG
16937469Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
17037469Ssklower 			if (SAME_ISOADDR(siso, &ia->ia_addr))
17137469Ssklower 				break;
17237469Ssklower 		if (ia == 0)
17336389Ssklower 			return EADDRNOTAVAIL;
17436389Ssklower 	}
17537469Ssklower 	if (siso->siso_len <= sizeof (isop->isop_sladdr)) {
17637469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
17737469Ssklower 	} else {
17837469Ssklower 		if ((nam = m_copy(nam, 0, (int)M_COPYALL)) == 0)
17937469Ssklower 			return ENOBUFS;
18037469Ssklower 		isop->isop_laddr = mtod(nam, struct sockaddr_iso *);
18137469Ssklower 	}
18237469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len);
183*39934Ssklower 	if (suf.s || siso->siso_tlen != 2) {
18438841Ssklower 		if((suf.s < ISO_PORT_RESERVED) && (siso->siso_tlen <= 2) &&
18537469Ssklower 		   (u.u_uid != 0))
18636389Ssklower 			return EACCES;
18736389Ssklower 		if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
18837469Ssklower 			iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr))
18936389Ssklower 			return EADDRINUSE;
19037469Ssklower 	} else {
19137469Ssklower 		register char *cp;
19236389Ssklower noname:
19337469Ssklower 		cp = TSEL(isop->isop_laddr);
19436389Ssklower 	IFDEBUG(D_ISO)
19536389Ssklower 		printf("iso_pcbbind noname\n");
19636389Ssklower 	ENDDEBUG
19736389Ssklower 		do {
19836389Ssklower 			if (head->isop_lport++ < ISO_PORT_RESERVED ||
19936389Ssklower 			    head->isop_lport > ISO_PORT_USERRESERVED)
20036389Ssklower 				head->isop_lport = ISO_PORT_RESERVED;
20137469Ssklower 			suf.s = head->isop_lport;
20237469Ssklower 			cp[0] = suf.data[0];
20337469Ssklower 			cp[1] = suf.data[1];
20437469Ssklower 		} while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr));
20537469Ssklower 	}
20636389Ssklower 	IFDEBUG(D_ISO)
20736389Ssklower 		printf("iso_pcbbind returns 0, suf 0x%x\n", suf);
20836389Ssklower 	ENDDEBUG
20936389Ssklower 	return 0;
21036389Ssklower }
21136389Ssklower /*
21236389Ssklower  * FUNCTION:		iso_pcbconnect
21336389Ssklower  *
21436389Ssklower  * PURPOSE:			Make the isopcb (isop) look like it's connected.
21536389Ssklower  *					In other words, give it the peer address given in
21636389Ssklower  *					the mbuf * (nam).   Make sure such a combination
21736389Ssklower  *					of local, peer addresses doesn't already exist
21836389Ssklower  *					for this protocol.  Internet mentality prevails here,
21936389Ssklower  *					wherein a src,dst pair uniquely identifies a connection.
22036389Ssklower  * 					Both net address and port must be specified in argument
22136389Ssklower  *					(nam).
22236389Ssklower  * 					If we don't have a local address for this socket yet,
22336389Ssklower  *					we pick one by calling iso_pcbbind().
22436389Ssklower  *
22536389Ssklower  * RETURNS:			errno E* or 0 if ok.
22636389Ssklower  *
22736389Ssklower  * SIDE EFFECTS:	Looks up a route, which may cause one to be left
22836389Ssklower  *					in the isopcb.
22936389Ssklower  *
23036389Ssklower  * NOTES:
23136389Ssklower  */
23236389Ssklower int
23336389Ssklower iso_pcbconnect(isop, nam)
23437469Ssklower 	register struct isopcb *isop;
23536389Ssklower 	struct mbuf *nam;
23636389Ssklower {
23736389Ssklower 	register struct sockaddr_iso	*siso = mtod(nam, struct sockaddr_iso *);
23837469Ssklower 	int								local_zero, error = 0;
23937469Ssklower 	struct iso_ifaddr 				*ia;
24036389Ssklower 
24136389Ssklower 	IFDEBUG(D_ISO)
24237469Ssklower 		printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x",
24337469Ssklower 					isop, isop->isop_socket, nam);
24437469Ssklower 		printf("nam->m_len 0x%x), addr:\n", nam->m_len);
24536389Ssklower 		dump_isoaddr(siso);
24636389Ssklower 	ENDDEBUG
24737469Ssklower 	if (nam->m_len < siso->siso_len)
24837469Ssklower 		return EINVAL;
24936389Ssklower 	if (siso->siso_family != AF_ISO)
25036389Ssklower 		return EAFNOSUPPORT;
25138477Ssklower 	if (siso->siso_nlen == 0) {
25238477Ssklower 		if (ia = iso_ifaddr) {
25338477Ssklower 			int nlen = ia->ia_addr.siso_nlen;
25438477Ssklower 			ovbcopy(TSEL(siso), nlen + TSEL(siso),
25538841Ssklower 				siso->siso_plen + siso->siso_tlen + siso->siso_slen);
25638477Ssklower 			bcopy((caddr_t)&ia->ia_addr.siso_addr,
25738477Ssklower 				  (caddr_t)&siso->siso_addr, nlen + 1);
25838477Ssklower 			/* includes siso->siso_nlen = nlen; */
25938477Ssklower 		} else
26038477Ssklower 			return EADDRNOTAVAIL;
26138477Ssklower 	}
26237469Ssklower 	/*
26337469Ssklower 	 * Local zero means either not bound, or bound to a TSEL, but no
26437469Ssklower 	 * particular local interface.  So, if we want to send somebody
26537469Ssklower 	 * we need to choose a return address.
26636389Ssklower 	 */
26737469Ssklower 	local_zero =
26837469Ssklower 		((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0));
26936389Ssklower 	if (local_zero) {
27037469Ssklower 		int flags;
27136389Ssklower 
27236389Ssklower 		IFDEBUG(D_ISO)
27336389Ssklower 			printf("iso_pcbconnect localzero 1\n");
27436389Ssklower 		ENDDEBUG
27536389Ssklower 		/*
27636389Ssklower 		 * If route is known or can be allocated now,
27736389Ssklower 		 * our src addr is taken from the i/f, else punt.
27836389Ssklower 		 */
27937469Ssklower 		flags = isop->isop_socket->so_options & SO_DONTROUTE;
28037469Ssklower 		if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags,
28137469Ssklower 						(struct sockaddr **)0, &ia))
28237469Ssklower 			return error;
28336389Ssklower 		IFDEBUG(D_ISO)
28437469Ssklower 			printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x",
28537469Ssklower 				isop->isop_route.ro_rt);
28637469Ssklower 			printf(" ia 0x%x\n", ia);
28736389Ssklower 		ENDDEBUG
28836389Ssklower 	}
28936389Ssklower 	IFDEBUG(D_ISO)
29036389Ssklower 		printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n",
29136389Ssklower 			isop, isop->isop_socket);
29236389Ssklower 	ENDDEBUG
29336389Ssklower 	if (local_zero) {
29437469Ssklower 		int nlen, tlen, totlen; caddr_t oldtsel, newtsel;
29537469Ssklower 		siso = isop->isop_laddr;
29638841Ssklower 		if (siso == 0 || siso->siso_tlen == 0)
29736389Ssklower 			(void)iso_pcbbind(isop, (struct mbuf *)0);
29837469Ssklower 		/*
29937469Ssklower 		 * Here we have problem of squezeing in a definite network address
30037469Ssklower 		 * into an existing sockaddr_iso, which in fact may not have room
30137469Ssklower 		 * for it.  This gets messy.
30237469Ssklower 		 */
30337469Ssklower 		siso = isop->isop_laddr;
30437469Ssklower 		oldtsel = TSEL(siso);
30538841Ssklower 		tlen = siso->siso_tlen;
30637469Ssklower 		nlen = ia->ia_addr.siso_nlen;
30737469Ssklower 		totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]);
30837469Ssklower 		if ((siso == &isop->isop_sladdr) &&
30937469Ssklower 			(totlen > sizeof(isop->isop_sladdr))) {
31037469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
31137469Ssklower 			if (m == 0)
31237469Ssklower 					return ENOBUFS;
31337469Ssklower 			m->m_len = totlen;
31437469Ssklower 			isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *);
31537469Ssklower 		}
31637469Ssklower 		siso->siso_nlen = ia->ia_addr.siso_nlen;
31737469Ssklower 		newtsel = TSEL(siso);
31837469Ssklower 		ovbcopy(oldtsel, newtsel, tlen);
31937469Ssklower 		bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
32038841Ssklower 		siso->siso_tlen = tlen;
32137469Ssklower 		siso->siso_family = AF_ISO;
32237469Ssklower 		siso->siso_len = totlen;
32337469Ssklower 		siso = mtod(nam, struct sockaddr_iso *);
32436389Ssklower 	}
32536389Ssklower 	IFDEBUG(D_ISO)
32636389Ssklower 		printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n",
32736389Ssklower 			isop, isop->isop_socket);
32836389Ssklower 	ENDDEBUG
32937469Ssklower 	/*
33037469Ssklower 	 * If we had to allocate space to a previous big foreign address,
33137469Ssklower 	 * and for some reason we didn't free it, we reuse it knowing
33237469Ssklower 	 * that is going to be big enough, as sockaddrs are delivered in
33337469Ssklower 	 * 128 byte mbufs.
33437469Ssklower 	 * If the foreign address is small enough, we use default space;
33537469Ssklower 	 * otherwise, we grab an mbuf to copy into.
33637469Ssklower 	 */
33737469Ssklower 	if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) {
33837469Ssklower 		if (siso->siso_len <= sizeof(isop->isop_sfaddr))
33937469Ssklower 			isop->isop_faddr = &isop->isop_sfaddr;
34037469Ssklower 		else {
34137469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
34237469Ssklower 			if (m == 0)
34337469Ssklower 				return ENOBUFS;
34437469Ssklower 			isop->isop_faddr = mtod(m, struct sockaddr_iso *);
34537469Ssklower 		}
34637469Ssklower 	}
34737469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len);
34836389Ssklower 	IFDEBUG(D_ISO)
34936389Ssklower 		printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n",
35036389Ssklower 			isop, isop->isop_socket);
35136389Ssklower 		printf("iso_pcbconnect connected to addr:\n");
35237469Ssklower 		dump_isoaddr(isop->isop_faddr);
35336389Ssklower 		printf("iso_pcbconnect end: src addr:\n");
35437469Ssklower 		dump_isoaddr(isop->isop_laddr);
35536389Ssklower 	ENDDEBUG
35636389Ssklower 	return 0;
35736389Ssklower }
35836389Ssklower 
35936389Ssklower /*
36036389Ssklower  * FUNCTION:		iso_pcbdisconnect()
36136389Ssklower  *
36236389Ssklower  * PURPOSE:			washes away the peer address info so the socket
36336389Ssklower  *					appears to be disconnected.
36436389Ssklower  *					If there's no file descriptor associated with the socket
36536389Ssklower  *					it detaches the pcb.
36636389Ssklower  *
36736389Ssklower  * RETURNS:			Nada.
36836389Ssklower  *
36936389Ssklower  * SIDE EFFECTS:	May detach the pcb.
37036389Ssklower  *
37136389Ssklower  * NOTES:
37236389Ssklower  */
37336389Ssklower void
37436389Ssklower iso_pcbdisconnect(isop)
37536389Ssklower 	struct isopcb *isop;
37636389Ssklower {
37736389Ssklower 	void iso_pcbdetach();
378*39934Ssklower 	register struct sockaddr_iso *siso;
37936389Ssklower 
38036389Ssklower 	IFDEBUG(D_ISO)
38136389Ssklower 		printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
38236389Ssklower 	ENDDEBUG
38337469Ssklower 	/*
38437469Ssklower 	 * Preserver binding infnormation if already bound.
38537469Ssklower 	 */
386*39934Ssklower 	if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) {
387*39934Ssklower 		caddr_t otsel = TSEL(siso);
388*39934Ssklower 		siso->siso_nlen = 0;
389*39934Ssklower 		ovbcopy(otsel, TSEL(siso), siso->siso_tlen);
390*39934Ssklower 	}
39137469Ssklower 	if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
39237469Ssklower 		m_freem(dtom(isop->isop_faddr));
39337469Ssklower 	isop->isop_faddr = 0;
39436389Ssklower 	if (isop->isop_socket->so_state & SS_NOFDREF)
39536389Ssklower 		iso_pcbdetach(isop);
39636389Ssklower }
39736389Ssklower 
39836389Ssklower /*
39936389Ssklower  * FUNCTION:		iso_pcbdetach
40036389Ssklower  *
40136389Ssklower  * PURPOSE:			detach the pcb at *(isop) from it's socket and free
40236389Ssklower  *					the mbufs associated with the pcb..
40336389Ssklower  *					Dequeues (isop) from its head.
40436389Ssklower  *
40536389Ssklower  * RETURNS:			Nada.
40636389Ssklower  *
40736389Ssklower  * SIDE EFFECTS:
40836389Ssklower  *
40936389Ssklower  * NOTES:
41036389Ssklower  */
41136389Ssklower void
41236389Ssklower iso_pcbdetach(isop)
41336389Ssklower 	struct isopcb *isop;
41436389Ssklower {
41536389Ssklower 	struct socket *so = isop->isop_socket;
41636389Ssklower 
41736389Ssklower 	IFDEBUG(D_ISO)
41836389Ssklower 		printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n",
41936389Ssklower 			isop, isop->isop_socket, so);
42036389Ssklower 	ENDDEBUG
42136389Ssklower 	if (so ) { /* in the x.25 domain, we sometimes have no socket */
42236389Ssklower 		so->so_pcb = 0;
42336389Ssklower 		sofree(so);
42436389Ssklower 	}
42536389Ssklower 	IFDEBUG(D_ISO)
42636389Ssklower 		printf("iso_pcbdetach 2 \n");
42736389Ssklower 	ENDDEBUG
42836389Ssklower 	if (isop->isop_options)
42936389Ssklower 		(void)m_free(isop->isop_options);
43036389Ssklower 	IFDEBUG(D_ISO)
43136389Ssklower 		printf("iso_pcbdetach 3 \n");
43236389Ssklower 	ENDDEBUG
43336389Ssklower 	if (isop->isop_route.ro_rt)
43436389Ssklower 		rtfree(isop->isop_route.ro_rt);
43536389Ssklower 	IFDEBUG(D_ISO)
43636389Ssklower 		printf("iso_pcbdetach 3.1\n");
43736389Ssklower 	ENDDEBUG
43836389Ssklower 	if (isop->isop_clnpcache != NULL) {
43936389Ssklower 		struct clnp_cache *clcp =
44036389Ssklower 			mtod(isop->isop_clnpcache, struct clnp_cache *);
44136389Ssklower 		IFDEBUG(D_ISO)
44236389Ssklower 			printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n",
44336389Ssklower 				clcp, clcp->clc_hdr);
44436389Ssklower 		ENDDEBUG
44536389Ssklower 		if (clcp->clc_hdr != NULL)
44636389Ssklower 			m_free(clcp->clc_hdr);
44736389Ssklower 		IFDEBUG(D_ISO)
44836389Ssklower 			printf("iso_pcbdetach 3.3: freeing cache x%x\n",
44936389Ssklower 				isop->isop_clnpcache);
45036389Ssklower 		ENDDEBUG
45136389Ssklower 		m_free(isop->isop_clnpcache);
45236389Ssklower 	}
45336389Ssklower 	IFDEBUG(D_ISO)
45436389Ssklower 		printf("iso_pcbdetach 4 \n");
45536389Ssklower 	ENDDEBUG
45636389Ssklower 	remque(isop);
45736389Ssklower 	IFDEBUG(D_ISO)
45836389Ssklower 		printf("iso_pcbdetach 5 \n");
45936389Ssklower 	ENDDEBUG
46037469Ssklower 	if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
46137469Ssklower 		m_freem(dtom(isop->isop_laddr));
46237469Ssklower 	free((caddr_t)isop, M_IFADDR);
46336389Ssklower }
46436389Ssklower 
46536389Ssklower 
46636389Ssklower /*
46736389Ssklower  * FUNCTION:		iso_pcbnotify
46836389Ssklower  *
46936389Ssklower  * PURPOSE:			notify all connections in this protocol's queue (head)
47036389Ssklower  *					that have peer address (dst) of the problem (errno)
47136389Ssklower  *					by calling (notify) on the connections' isopcbs.
47236389Ssklower  *
47336389Ssklower  * RETURNS:			Rien.
47436389Ssklower  *
47536389Ssklower  * SIDE EFFECTS:
47636389Ssklower  *
47736389Ssklower  * NOTES:			(notify) is called at splimp!
47836389Ssklower  */
47936389Ssklower void
480*39934Ssklower iso_pcbnotify(head, siso, errno, notify)
48136389Ssklower 	struct isopcb *head;
482*39934Ssklower 	register struct sockaddr_iso *siso;
48336389Ssklower 	int errno, (*notify)();
48436389Ssklower {
485*39934Ssklower 	register struct isopcb *isop;
48636389Ssklower 	int s = splimp();
48736389Ssklower 
48836389Ssklower 	IFDEBUG(D_ISO)
48936389Ssklower 		printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
49036389Ssklower 	ENDDEBUG
491*39934Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
492*39934Ssklower 		if (isop->isop_socket == 0 || isop->isop_faddr == 0 ||
493*39934Ssklower 			!SAME_ISOADDR(siso, isop->isop_faddr)) {
49436389Ssklower 			IFDEBUG(D_ISO)
49536389Ssklower 				printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
49636389Ssklower 					isop, isop->isop_socket);
497*39934Ssklower 				printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr);
49837469Ssklower 				dump_isoaddr(isop->isop_faddr);
49936389Ssklower 			ENDDEBUG
50036389Ssklower 			continue;
50136389Ssklower 		}
50236389Ssklower 		if (errno)
50336389Ssklower 			isop->isop_socket->so_error = errno;
50436389Ssklower 		if (notify)
505*39934Ssklower 			(*notify)(isop);
50636389Ssklower 	}
50736389Ssklower 	splx(s);
50836389Ssklower 	IFDEBUG(D_ISO)
50936389Ssklower 		printf("END OF iso_pcbnotify\n" );
51036389Ssklower 	ENDDEBUG
51136389Ssklower }
51236389Ssklower 
51336389Ssklower 
51436389Ssklower /*
51536389Ssklower  * FUNCTION:		iso_pcblookup
51636389Ssklower  *
51736389Ssklower  * PURPOSE:			looks for a given combination of (faddr), (fport),
51836389Ssklower  *					(lport), (laddr) in the queue named by (head).
51936389Ssklower  *					Argument (flags) is ignored.
52036389Ssklower  *
52136389Ssklower  * RETURNS:			ptr to the isopcb if it finds a connection matching
52236389Ssklower  *					these arguments, o.w. returns zero.
52336389Ssklower  *
52436389Ssklower  * SIDE EFFECTS:
52536389Ssklower  *
52636389Ssklower  * NOTES:
52736389Ssklower  */
52836389Ssklower struct isopcb *
52937469Ssklower iso_pcblookup(head, fportlen, fport, laddr)
53036389Ssklower 	struct isopcb *head;
53137469Ssklower 	register struct sockaddr_iso *laddr;
53237469Ssklower 	caddr_t fport;
53337469Ssklower 	int fportlen;
53436389Ssklower {
53536389Ssklower 	register struct isopcb *isop;
53637469Ssklower 	register caddr_t lp = TSEL(laddr);
53738841Ssklower 	unsigned int llen = laddr->siso_tlen;
53836389Ssklower 
53936389Ssklower 	IFDEBUG(D_ISO)
54037469Ssklower 		printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n",
54137469Ssklower 			head, laddr, fport);
54236389Ssklower 	ENDDEBUG
54336389Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
54437469Ssklower 		if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
54536389Ssklower 			continue;
54638841Ssklower 		if (isop->isop_laddr->siso_tlen != llen)
54736389Ssklower 			continue;
54837469Ssklower 		if (bcmp(lp, TSEL(isop->isop_laddr), llen))
54937469Ssklower 			continue;
55037469Ssklower 		if (fportlen && isop->isop_faddr &&
55137469Ssklower 			bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen))
55237469Ssklower 			continue;
55336389Ssklower 		/*	PHASE2
55436389Ssklower 		 *	addrmatch1 should be iso_addrmatch(a, b, mask)
55536389Ssklower 		 *	where mask is taken from isop->isop_laddrmask (new field)
55636389Ssklower 		 *	isop_lnetmask will also be available in isop
55736389Ssklower 		if (laddr != &zeroiso_addr &&
55836389Ssklower 			!iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr)))
55936389Ssklower 			continue;
56037469Ssklower 		*/
56137469Ssklower 		if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr)))
56237469Ssklower 			continue;
56336389Ssklower 		return (isop);
56436389Ssklower 	}
56536389Ssklower 	return (struct isopcb *)0;
56636389Ssklower }
56736389Ssklower #endif ISO
568