xref: /csrg-svn/sys/netiso/iso_pcb.c (revision 38477)
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*38477Ssklower  *	@(#)iso_pcb.c	7.4 (Berkeley) 07/19/89
3136389Ssklower  *
3236389Ssklower  * Iso address family net-layer(s) pcb stuff. NEH 1/29/87
3336389Ssklower  */
34*38477Ssklower 
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;
13437469Ssklower 		isop->isop_sladdr.siso_tsuffixlen = 2;
13537469Ssklower 		isop->isop_sladdr.siso_nlen = 0;
13637469Ssklower 		isop->isop_sladdr.siso_family = AF_ISO;
13737469Ssklower 		isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso);
13836389Ssklower 		goto noname;
13937469Ssklower 	}
14036389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
14136389Ssklower 	IFDEBUG(D_ISO)
14236389Ssklower 		printf("iso_pcbbind(name len 0x%x)\n", nam->m_len);
14336389Ssklower 		printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr));
14436389Ssklower 	ENDDEBUG
14536389Ssklower 	/*
14636389Ssklower 	 * We would like sort of length check but since some OSI addrs
14736389Ssklower 	 * do not have fixed length, we can't really do much.
14836389Ssklower 	 * The ONLY thing we can say is that an osi addr has to have
14936389Ssklower 	 * at LEAST an afi and one more byte and had better fit into
15036389Ssklower 	 * a struct iso_addr.
15136389Ssklower 	 * However, in fact the size of the whole thing is a struct
15236389Ssklower 	 * sockaddr_iso, so probably this is what we should check for.
15336389Ssklower 	 */
15437469Ssklower 	if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) {
15536389Ssklower 			return ENAMETOOLONG;
15636389Ssklower 	}
15737469Ssklower 	if (siso->siso_tsuffixlen) {
15837469Ssklower 			register char *cp = TSEL(siso);
15937469Ssklower 			suf.data[0] = cp[0];
16037469Ssklower 			suf.data[1] = cp[1];
16137469Ssklower 	}
16237469Ssklower 	if (siso->siso_nlen) {
16336389Ssklower 		/* non-zero net addr- better match one of our interfaces */
16436389Ssklower 		IFDEBUG(D_ISO)
16536389Ssklower 			printf("iso_pcbbind: bind to NOT zeroisoaddr\n");
16636389Ssklower 		ENDDEBUG
16737469Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
16837469Ssklower 			if (SAME_ISOADDR(siso, &ia->ia_addr))
16937469Ssklower 				break;
17037469Ssklower 		if (ia == 0)
17136389Ssklower 			return EADDRNOTAVAIL;
17236389Ssklower 	}
17337469Ssklower 	if (siso->siso_len <= sizeof (isop->isop_sladdr)) {
17437469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
17537469Ssklower 	} else {
17637469Ssklower 		if ((nam = m_copy(nam, 0, (int)M_COPYALL)) == 0)
17737469Ssklower 			return ENOBUFS;
17837469Ssklower 		isop->isop_laddr = mtod(nam, struct sockaddr_iso *);
17937469Ssklower 	}
18037469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len);
18137469Ssklower 	if (suf.s) {
18237469Ssklower 		if((suf.s < ISO_PORT_RESERVED) && (siso->siso_tsuffixlen <= 2) &&
18337469Ssklower 		   (u.u_uid != 0))
18436389Ssklower 			return EACCES;
18536389Ssklower 		if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
18637469Ssklower 			iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr))
18736389Ssklower 			return EADDRINUSE;
18837469Ssklower 	} else {
18937469Ssklower 		register char *cp;
19036389Ssklower noname:
19137469Ssklower 		cp = TSEL(isop->isop_laddr);
19236389Ssklower 	IFDEBUG(D_ISO)
19336389Ssklower 		printf("iso_pcbbind noname\n");
19436389Ssklower 	ENDDEBUG
19536389Ssklower 		do {
19636389Ssklower 			if (head->isop_lport++ < ISO_PORT_RESERVED ||
19736389Ssklower 			    head->isop_lport > ISO_PORT_USERRESERVED)
19836389Ssklower 				head->isop_lport = ISO_PORT_RESERVED;
19937469Ssklower 			suf.s = head->isop_lport;
20037469Ssklower 			cp[0] = suf.data[0];
20137469Ssklower 			cp[1] = suf.data[1];
20237469Ssklower 		} while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr));
20337469Ssklower 	}
20436389Ssklower 	IFDEBUG(D_ISO)
20536389Ssklower 		printf("iso_pcbbind returns 0, suf 0x%x\n", suf);
20636389Ssklower 	ENDDEBUG
20736389Ssklower 	return 0;
20836389Ssklower }
20936389Ssklower /*
21036389Ssklower  * FUNCTION:		iso_pcbconnect
21136389Ssklower  *
21236389Ssklower  * PURPOSE:			Make the isopcb (isop) look like it's connected.
21336389Ssklower  *					In other words, give it the peer address given in
21436389Ssklower  *					the mbuf * (nam).   Make sure such a combination
21536389Ssklower  *					of local, peer addresses doesn't already exist
21636389Ssklower  *					for this protocol.  Internet mentality prevails here,
21736389Ssklower  *					wherein a src,dst pair uniquely identifies a connection.
21836389Ssklower  * 					Both net address and port must be specified in argument
21936389Ssklower  *					(nam).
22036389Ssklower  * 					If we don't have a local address for this socket yet,
22136389Ssklower  *					we pick one by calling iso_pcbbind().
22236389Ssklower  *
22336389Ssklower  * RETURNS:			errno E* or 0 if ok.
22436389Ssklower  *
22536389Ssklower  * SIDE EFFECTS:	Looks up a route, which may cause one to be left
22636389Ssklower  *					in the isopcb.
22736389Ssklower  *
22836389Ssklower  * NOTES:
22936389Ssklower  */
23036389Ssklower int
23136389Ssklower iso_pcbconnect(isop, nam)
23237469Ssklower 	register struct isopcb *isop;
23336389Ssklower 	struct mbuf *nam;
23436389Ssklower {
23536389Ssklower 	register struct sockaddr_iso	*siso = mtod(nam, struct sockaddr_iso *);
23637469Ssklower 	int								local_zero, error = 0;
23737469Ssklower 	struct iso_ifaddr 				*ia;
23836389Ssklower 
23936389Ssklower 	IFDEBUG(D_ISO)
24037469Ssklower 		printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x",
24137469Ssklower 					isop, isop->isop_socket, nam);
24237469Ssklower 		printf("nam->m_len 0x%x), addr:\n", nam->m_len);
24336389Ssklower 		dump_isoaddr(siso);
24436389Ssklower 	ENDDEBUG
24537469Ssklower 	if (nam->m_len < siso->siso_len)
24637469Ssklower 		return EINVAL;
24736389Ssklower 	if (siso->siso_family != AF_ISO)
24836389Ssklower 		return EAFNOSUPPORT;
249*38477Ssklower 	if (siso->siso_nlen == 0) {
250*38477Ssklower 		if (ia = iso_ifaddr) {
251*38477Ssklower 			int nlen = ia->ia_addr.siso_nlen;
252*38477Ssklower 			ovbcopy(TSEL(siso), nlen + TSEL(siso),
253*38477Ssklower 				siso->siso_tsuffixlen + siso->siso_ssuffixlen);
254*38477Ssklower 			bcopy((caddr_t)&ia->ia_addr.siso_addr,
255*38477Ssklower 				  (caddr_t)&siso->siso_addr, nlen + 1);
256*38477Ssklower 			/* includes siso->siso_nlen = nlen; */
257*38477Ssklower 		} else
258*38477Ssklower 			return EADDRNOTAVAIL;
259*38477Ssklower 	}
26037469Ssklower 	/*
26137469Ssklower 	 * Local zero means either not bound, or bound to a TSEL, but no
26237469Ssklower 	 * particular local interface.  So, if we want to send somebody
26337469Ssklower 	 * we need to choose a return address.
26436389Ssklower 	 */
26537469Ssklower 	local_zero =
26637469Ssklower 		((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0));
26736389Ssklower 	if (local_zero) {
26837469Ssklower 		int flags;
26936389Ssklower 
27036389Ssklower 		IFDEBUG(D_ISO)
27136389Ssklower 			printf("iso_pcbconnect localzero 1\n");
27236389Ssklower 		ENDDEBUG
27336389Ssklower 		/*
27436389Ssklower 		 * If route is known or can be allocated now,
27536389Ssklower 		 * our src addr is taken from the i/f, else punt.
27636389Ssklower 		 */
27737469Ssklower 		flags = isop->isop_socket->so_options & SO_DONTROUTE;
27837469Ssklower 		if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags,
27937469Ssklower 						(struct sockaddr **)0, &ia))
28037469Ssklower 			return error;
28136389Ssklower 		IFDEBUG(D_ISO)
28237469Ssklower 			printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x",
28337469Ssklower 				isop->isop_route.ro_rt);
28437469Ssklower 			printf(" ia 0x%x\n", ia);
28536389Ssklower 		ENDDEBUG
28636389Ssklower 	}
28736389Ssklower 	IFDEBUG(D_ISO)
28836389Ssklower 		printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n",
28936389Ssklower 			isop, isop->isop_socket);
29036389Ssklower 	ENDDEBUG
29136389Ssklower 	if (local_zero) {
29237469Ssklower 		int nlen, tlen, totlen; caddr_t oldtsel, newtsel;
29337469Ssklower 		siso = isop->isop_laddr;
29437469Ssklower 		if (siso == 0 || siso->siso_tsuffixlen == 0)
29536389Ssklower 			(void)iso_pcbbind(isop, (struct mbuf *)0);
29637469Ssklower 		/*
29737469Ssklower 		 * Here we have problem of squezeing in a definite network address
29837469Ssklower 		 * into an existing sockaddr_iso, which in fact may not have room
29937469Ssklower 		 * for it.  This gets messy.
30037469Ssklower 		 */
30137469Ssklower 		siso = isop->isop_laddr;
30237469Ssklower 		oldtsel = TSEL(siso);
30337469Ssklower 		tlen = siso->siso_tsuffixlen;
30437469Ssklower 		nlen = ia->ia_addr.siso_nlen;
30537469Ssklower 		totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]);
30637469Ssklower 		if ((siso == &isop->isop_sladdr) &&
30737469Ssklower 			(totlen > sizeof(isop->isop_sladdr))) {
30837469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
30937469Ssklower 			if (m == 0)
31037469Ssklower 					return ENOBUFS;
31137469Ssklower 			m->m_len = totlen;
31237469Ssklower 			isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *);
31337469Ssklower 		}
31437469Ssklower 		siso->siso_nlen = ia->ia_addr.siso_nlen;
31537469Ssklower 		newtsel = TSEL(siso);
31637469Ssklower 		ovbcopy(oldtsel, newtsel, tlen);
31737469Ssklower 		bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
31837469Ssklower 		siso->siso_tsuffixlen = tlen;
31937469Ssklower 		siso->siso_family = AF_ISO;
32037469Ssklower 		siso->siso_len = totlen;
32137469Ssklower 		siso = mtod(nam, struct sockaddr_iso *);
32236389Ssklower 	}
32336389Ssklower 	IFDEBUG(D_ISO)
32436389Ssklower 		printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n",
32536389Ssklower 			isop, isop->isop_socket);
32636389Ssklower 	ENDDEBUG
32737469Ssklower 	/*
32837469Ssklower 	 * If we had to allocate space to a previous big foreign address,
32937469Ssklower 	 * and for some reason we didn't free it, we reuse it knowing
33037469Ssklower 	 * that is going to be big enough, as sockaddrs are delivered in
33137469Ssklower 	 * 128 byte mbufs.
33237469Ssklower 	 * If the foreign address is small enough, we use default space;
33337469Ssklower 	 * otherwise, we grab an mbuf to copy into.
33437469Ssklower 	 */
33537469Ssklower 	if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) {
33637469Ssklower 		if (siso->siso_len <= sizeof(isop->isop_sfaddr))
33737469Ssklower 			isop->isop_faddr = &isop->isop_sfaddr;
33837469Ssklower 		else {
33937469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
34037469Ssklower 			if (m == 0)
34137469Ssklower 				return ENOBUFS;
34237469Ssklower 			isop->isop_faddr = mtod(m, struct sockaddr_iso *);
34337469Ssklower 		}
34437469Ssklower 	}
34537469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len);
34636389Ssklower 	IFDEBUG(D_ISO)
34736389Ssklower 		printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n",
34836389Ssklower 			isop, isop->isop_socket);
34936389Ssklower 		printf("iso_pcbconnect connected to addr:\n");
35037469Ssklower 		dump_isoaddr(isop->isop_faddr);
35136389Ssklower 		printf("iso_pcbconnect end: src addr:\n");
35237469Ssklower 		dump_isoaddr(isop->isop_laddr);
35336389Ssklower 	ENDDEBUG
35436389Ssklower 	return 0;
35536389Ssklower }
35636389Ssklower 
35736389Ssklower /*
35836389Ssklower  * FUNCTION:		iso_pcbdisconnect()
35936389Ssklower  *
36036389Ssklower  * PURPOSE:			washes away the peer address info so the socket
36136389Ssklower  *					appears to be disconnected.
36236389Ssklower  *					If there's no file descriptor associated with the socket
36336389Ssklower  *					it detaches the pcb.
36436389Ssklower  *
36536389Ssklower  * RETURNS:			Nada.
36636389Ssklower  *
36736389Ssklower  * SIDE EFFECTS:	May detach the pcb.
36836389Ssklower  *
36936389Ssklower  * NOTES:
37036389Ssklower  */
37136389Ssklower void
37236389Ssklower iso_pcbdisconnect(isop)
37336389Ssklower 	struct isopcb *isop;
37436389Ssklower {
37536389Ssklower 	void iso_pcbdetach();
37636389Ssklower 
37736389Ssklower 	IFDEBUG(D_ISO)
37836389Ssklower 		printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
37936389Ssklower 	ENDDEBUG
38037469Ssklower 	/*
38137469Ssklower 	 * Preserver binding infnormation if already bound.
38237469Ssklower 	 */
38337469Ssklower 	if (isop->isop_laddr && isop->isop_laddr->siso_nlen)
38437469Ssklower 		isop->isop_laddr->siso_nlen = 0;
38537469Ssklower 	if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
38637469Ssklower 		m_freem(dtom(isop->isop_faddr));
38737469Ssklower 	isop->isop_faddr = 0;
38836389Ssklower 	if (isop->isop_socket->so_state & SS_NOFDREF)
38936389Ssklower 		iso_pcbdetach(isop);
39036389Ssklower }
39136389Ssklower 
39236389Ssklower /*
39336389Ssklower  * FUNCTION:		iso_pcbdetach
39436389Ssklower  *
39536389Ssklower  * PURPOSE:			detach the pcb at *(isop) from it's socket and free
39636389Ssklower  *					the mbufs associated with the pcb..
39736389Ssklower  *					Dequeues (isop) from its head.
39836389Ssklower  *
39936389Ssklower  * RETURNS:			Nada.
40036389Ssklower  *
40136389Ssklower  * SIDE EFFECTS:
40236389Ssklower  *
40336389Ssklower  * NOTES:
40436389Ssklower  */
40536389Ssklower void
40636389Ssklower iso_pcbdetach(isop)
40736389Ssklower 	struct isopcb *isop;
40836389Ssklower {
40936389Ssklower 	struct socket *so = isop->isop_socket;
41036389Ssklower 
41136389Ssklower 	IFDEBUG(D_ISO)
41236389Ssklower 		printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n",
41336389Ssklower 			isop, isop->isop_socket, so);
41436389Ssklower 	ENDDEBUG
41536389Ssklower 	if (so ) { /* in the x.25 domain, we sometimes have no socket */
41636389Ssklower 		so->so_pcb = 0;
41736389Ssklower 		sofree(so);
41836389Ssklower 	}
41936389Ssklower 	IFDEBUG(D_ISO)
42036389Ssklower 		printf("iso_pcbdetach 2 \n");
42136389Ssklower 	ENDDEBUG
42236389Ssklower 	if (isop->isop_options)
42336389Ssklower 		(void)m_free(isop->isop_options);
42436389Ssklower 	IFDEBUG(D_ISO)
42536389Ssklower 		printf("iso_pcbdetach 3 \n");
42636389Ssklower 	ENDDEBUG
42736389Ssklower 	if (isop->isop_route.ro_rt)
42836389Ssklower 		rtfree(isop->isop_route.ro_rt);
42936389Ssklower 	IFDEBUG(D_ISO)
43036389Ssklower 		printf("iso_pcbdetach 3.1\n");
43136389Ssklower 	ENDDEBUG
43236389Ssklower 	if (isop->isop_clnpcache != NULL) {
43336389Ssklower 		struct clnp_cache *clcp =
43436389Ssklower 			mtod(isop->isop_clnpcache, struct clnp_cache *);
43536389Ssklower 		IFDEBUG(D_ISO)
43636389Ssklower 			printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n",
43736389Ssklower 				clcp, clcp->clc_hdr);
43836389Ssklower 		ENDDEBUG
43936389Ssklower 		if (clcp->clc_hdr != NULL)
44036389Ssklower 			m_free(clcp->clc_hdr);
44136389Ssklower 		IFDEBUG(D_ISO)
44236389Ssklower 			printf("iso_pcbdetach 3.3: freeing cache x%x\n",
44336389Ssklower 				isop->isop_clnpcache);
44436389Ssklower 		ENDDEBUG
44536389Ssklower 		m_free(isop->isop_clnpcache);
44636389Ssklower 	}
44736389Ssklower 	IFDEBUG(D_ISO)
44836389Ssklower 		printf("iso_pcbdetach 4 \n");
44936389Ssklower 	ENDDEBUG
45036389Ssklower 	remque(isop);
45136389Ssklower 	IFDEBUG(D_ISO)
45236389Ssklower 		printf("iso_pcbdetach 5 \n");
45336389Ssklower 	ENDDEBUG
45437469Ssklower 	if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
45537469Ssklower 		m_freem(dtom(isop->isop_laddr));
45637469Ssklower 	free((caddr_t)isop, M_IFADDR);
45736389Ssklower }
45836389Ssklower 
45936389Ssklower #ifdef notdef
46036389Ssklower /* NEEDED? */
46136389Ssklower void
46236389Ssklower iso_setsockaddr(isop, nam)
46336389Ssklower 	register struct isopcb *isop;
46436389Ssklower 	struct mbuf *nam;
46536389Ssklower {
46636389Ssklower 	register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
46736389Ssklower 
46836389Ssklower 	nam->m_len = sizeof (*siso);
46936389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
47036389Ssklower 	bzero((caddr_t)siso, sizeof (*siso));
47136389Ssklower 	siso->siso_family = AF_ISO;
47236389Ssklower 	siso->siso_tsuffix = isop->isop_lport;
47336389Ssklower 	siso->siso_addr = isop->isop_laddr.siso_addr;
47436389Ssklower }
47536389Ssklower 
47636389Ssklower /* NEEDED? */
47736389Ssklower void
47836389Ssklower iso_setpeeraddr(isop, nam)
47936389Ssklower 	register struct isopcb *isop;
48036389Ssklower 	struct mbuf *nam;
48136389Ssklower {
48236389Ssklower 	register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
48336389Ssklower 
48436389Ssklower 	nam->m_len = sizeof (*siso);
48536389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
48636389Ssklower 	bzero((caddr_t)siso, sizeof (*siso));
48736389Ssklower 	siso->siso_family = AF_ISO;
48836389Ssklower 	siso->siso_tsuffix = isop->isop_fport;
48936389Ssklower 	siso->siso_addr = isop->isop_faddr.siso_addr;
49036389Ssklower }
49136389Ssklower #endif notdef
49236389Ssklower 
49336389Ssklower /*
49436389Ssklower  * FUNCTION:		iso_pcbnotify
49536389Ssklower  *
49636389Ssklower  * PURPOSE:			notify all connections in this protocol's queue (head)
49736389Ssklower  *					that have peer address (dst) of the problem (errno)
49836389Ssklower  *					by calling (notify) on the connections' isopcbs.
49936389Ssklower  *
50036389Ssklower  * RETURNS:			Rien.
50136389Ssklower  *
50236389Ssklower  * SIDE EFFECTS:
50336389Ssklower  *
50436389Ssklower  * NOTES:			(notify) is called at splimp!
50536389Ssklower  */
50636389Ssklower void
50736389Ssklower iso_pcbnotify(head, dst, errno, notify)
50836389Ssklower 	struct isopcb *head;
50936389Ssklower 	register struct iso_addr *dst;
51036389Ssklower 	int errno, (*notify)();
51136389Ssklower {
51236389Ssklower 	register struct isopcb *isop, *oisop;
51336389Ssklower 	int s = splimp();
51436389Ssklower 
51536389Ssklower 	IFDEBUG(D_ISO)
51636389Ssklower 		printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
51736389Ssklower 	ENDDEBUG
51836389Ssklower 	for (isop = head->isop_next; isop != head;) {
51937469Ssklower 		if (!iso_addrmatch1(&(isop->isop_faddr->siso_addr), dst) ||
52036389Ssklower 		    isop->isop_socket == 0) {
52136389Ssklower 			IFDEBUG(D_ISO)
52236389Ssklower 				printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
52336389Ssklower 					isop, isop->isop_socket);
52436389Ssklower 				printf("addrmatch cmp'd with (0x%x):\n",
52537469Ssklower 					&(isop->isop_faddr->siso_addr));
52637469Ssklower 				dump_isoaddr(isop->isop_faddr);
52736389Ssklower 			ENDDEBUG
52836389Ssklower 			isop = isop->isop_next;
52936389Ssklower 			continue;
53036389Ssklower 		}
53136389Ssklower 		if (errno)
53236389Ssklower 			isop->isop_socket->so_error = errno;
53336389Ssklower 		oisop = isop;
53436389Ssklower 		isop = isop->isop_next;
53536389Ssklower 		if (notify)
53636389Ssklower 			(*notify)(oisop);
53736389Ssklower 	}
53836389Ssklower 	splx(s);
53936389Ssklower 	IFDEBUG(D_ISO)
54036389Ssklower 		printf("END OF iso_pcbnotify\n" );
54136389Ssklower 	ENDDEBUG
54236389Ssklower }
54336389Ssklower 
54436389Ssklower 
54536389Ssklower /*
54636389Ssklower  * FUNCTION:		iso_pcblookup
54736389Ssklower  *
54836389Ssklower  * PURPOSE:			looks for a given combination of (faddr), (fport),
54936389Ssklower  *					(lport), (laddr) in the queue named by (head).
55036389Ssklower  *					Argument (flags) is ignored.
55136389Ssklower  *
55236389Ssklower  * RETURNS:			ptr to the isopcb if it finds a connection matching
55336389Ssklower  *					these arguments, o.w. returns zero.
55436389Ssklower  *
55536389Ssklower  * SIDE EFFECTS:
55636389Ssklower  *
55736389Ssklower  * NOTES:
55836389Ssklower  */
55936389Ssklower struct isopcb *
56037469Ssklower iso_pcblookup(head, fportlen, fport, laddr)
56136389Ssklower 	struct isopcb *head;
56237469Ssklower 	register struct sockaddr_iso *laddr;
56337469Ssklower 	caddr_t fport;
56437469Ssklower 	int fportlen;
56536389Ssklower {
56636389Ssklower 	register struct isopcb *isop;
56737469Ssklower 	register caddr_t lp = TSEL(laddr);
56837469Ssklower 	unsigned int llen = laddr->siso_tsuffixlen;
56936389Ssklower 
57036389Ssklower 	IFDEBUG(D_ISO)
57137469Ssklower 		printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n",
57237469Ssklower 			head, laddr, fport);
57336389Ssklower 	ENDDEBUG
57436389Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
57537469Ssklower 		if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
57636389Ssklower 			continue;
57737469Ssklower 		if (isop->isop_laddr->siso_tsuffixlen != llen)
57836389Ssklower 			continue;
57937469Ssklower 		if (bcmp(lp, TSEL(isop->isop_laddr), llen))
58037469Ssklower 			continue;
58137469Ssklower 		if (fportlen && isop->isop_faddr &&
58237469Ssklower 			bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen))
58337469Ssklower 			continue;
58436389Ssklower 		/*	PHASE2
58536389Ssklower 		 *	addrmatch1 should be iso_addrmatch(a, b, mask)
58636389Ssklower 		 *	where mask is taken from isop->isop_laddrmask (new field)
58736389Ssklower 		 *	isop_lnetmask will also be available in isop
58836389Ssklower 		if (laddr != &zeroiso_addr &&
58936389Ssklower 			!iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr)))
59036389Ssklower 			continue;
59137469Ssklower 		*/
59237469Ssklower 		if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr)))
59337469Ssklower 			continue;
59436389Ssklower 		return (isop);
59536389Ssklower 	}
59636389Ssklower 	return (struct isopcb *)0;
59736389Ssklower }
59836389Ssklower #endif ISO
599