xref: /csrg-svn/sys/netiso/iso_pcb.c (revision 37469)
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 $
3036389Ssklower  *
3136389Ssklower  * Iso address family net-layer(s) pcb stuff. NEH 1/29/87
3236389Ssklower  */
3336389Ssklower #ifndef lint
3436389Ssklower static char *rcsid = "$Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $";
3536389Ssklower #endif
3636389Ssklower 
3736389Ssklower #ifdef ISO
3836389Ssklower 
3936389Ssklower #include "param.h"
4036389Ssklower #include "systm.h"
4136389Ssklower #include "dir.h"
4236389Ssklower #include "user.h"
4336389Ssklower #include "mbuf.h"
44*37469Ssklower #include "socket.h"
45*37469Ssklower #include "socketvar.h"
46*37469Ssklower #include "argo_debug.h"
47*37469Ssklower #include "iso.h"
48*37469Ssklower #include "clnp.h"
4936389Ssklower #include "../netinet/in_systm.h"
5036389Ssklower #include "../net/if.h"
5136389Ssklower #include "../net/route.h"
52*37469Ssklower #include "iso_pcb.h"
53*37469Ssklower #include "iso_var.h"
5436389Ssklower #include "protosw.h"
5536389Ssklower 
5636389Ssklower #define PCBNULL (struct isopcb *)0
5736389Ssklower struct	iso_addr zeroiso_addr = {
5836389Ssklower 	0
5936389Ssklower };
6036389Ssklower 
6136389Ssklower 
6236389Ssklower /*
6336389Ssklower  * FUNCTION:		iso_pcballoc
6436389Ssklower  *
6536389Ssklower  * PURPOSE:			creates an isopcb structure in an mbuf,
6636389Ssklower  *					with socket (so), and
6736389Ssklower  *					puts it in the queue with head (head)
6836389Ssklower  *
6936389Ssklower  * RETURNS:			0 if OK, ENOBUFS if can't alloc the necessary mbuf
7036389Ssklower  */
7136389Ssklower int
7236389Ssklower iso_pcballoc(so, head)
7336389Ssklower 	struct socket *so;
7436389Ssklower 	struct isopcb *head;
7536389Ssklower {
7636389Ssklower 	register struct isopcb *isop;
7736389Ssklower 
7836389Ssklower 	IFDEBUG(D_ISO)
7936389Ssklower 		printf("iso_pcballoc(so 0x%x)\n", so);
8036389Ssklower 	ENDDEBUG
81*37469Ssklower 	MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT);
82*37469Ssklower 	if (isop == NULL)
8336389Ssklower 		return ENOBUFS;
84*37469Ssklower 	bzero((caddr_t)isop, sizeof(*isop));
8536389Ssklower 	isop->isop_head = head;
8636389Ssklower 	isop->isop_socket = so;
8736389Ssklower 	insque(isop, head);
8836389Ssklower 	so->so_pcb = (caddr_t)isop;
8936389Ssklower 	return 0;
9036389Ssklower }
9136389Ssklower 
9236389Ssklower /*
9336389Ssklower  * FUNCTION:		iso_pcbbind
9436389Ssklower  *
9536389Ssklower  * PURPOSE:			binds the address given in *(nam) to the socket
9636389Ssklower  *					specified by the isopcb in *(isop)
9736389Ssklower  *					If the given address is zero, it makes sure the
9836389Ssklower  *					address isn't already in use and if it's got a network
9936389Ssklower  *					portion, we look for an interface with that network
10036389Ssklower  *					address.  If the address given is zero, we allocate
10136389Ssklower  *					a port and stuff it in the (nam) structure.
10236389Ssklower  *
10336389Ssklower  * RETURNS:			errno E* or 0 if ok.
10436389Ssklower  *
10536389Ssklower  * SIDE EFFECTS:	increments head->isop_lport if it allocates a port #
10636389Ssklower  *
10736389Ssklower  * NOTES:
10836389Ssklower  */
109*37469Ssklower #define	satosiso(sa)	((struct sockaddr_iso *)(sa))
11036389Ssklower int
11136389Ssklower iso_pcbbind(isop, nam)
11236389Ssklower 	register struct isopcb *isop;
11336389Ssklower 	struct mbuf *nam;
11436389Ssklower {
11536389Ssklower 	register struct isopcb *head = isop->isop_head;
11636389Ssklower 	register struct sockaddr_iso *siso;
117*37469Ssklower 	struct iso_ifaddr *ia;
118*37469Ssklower 	union {
119*37469Ssklower 		char data[2];
120*37469Ssklower 		u_short s;
121*37469Ssklower 	} suf;
12236389Ssklower 
12336389Ssklower 	IFDEBUG(D_ISO)
12436389Ssklower 		printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam);
12536389Ssklower 	ENDDEBUG
126*37469Ssklower 	suf.s = 0;
12736389Ssklower 	if (iso_ifaddr == 0) /* any interfaces attached? */
12836389Ssklower 		return EADDRNOTAVAIL;
129*37469Ssklower 	if (isop->isop_laddr)  /* already bound */
13036389Ssklower 		return EADDRINUSE;
131*37469Ssklower 	if(nam == (struct mbuf *)0) {
132*37469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
133*37469Ssklower 		isop->isop_sladdr.siso_tsuffixlen = 2;
134*37469Ssklower 		isop->isop_sladdr.siso_nlen = 0;
135*37469Ssklower 		isop->isop_sladdr.siso_family = AF_ISO;
136*37469Ssklower 		isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso);
13736389Ssklower 		goto noname;
138*37469Ssklower 	}
13936389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
14036389Ssklower 	IFDEBUG(D_ISO)
14136389Ssklower 		printf("iso_pcbbind(name len 0x%x)\n", nam->m_len);
14236389Ssklower 		printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr));
14336389Ssklower 	ENDDEBUG
14436389Ssklower 	/*
14536389Ssklower 	 * We would like sort of length check but since some OSI addrs
14636389Ssklower 	 * do not have fixed length, we can't really do much.
14736389Ssklower 	 * The ONLY thing we can say is that an osi addr has to have
14836389Ssklower 	 * at LEAST an afi and one more byte and had better fit into
14936389Ssklower 	 * a struct iso_addr.
15036389Ssklower 	 * However, in fact the size of the whole thing is a struct
15136389Ssklower 	 * sockaddr_iso, so probably this is what we should check for.
15236389Ssklower 	 */
153*37469Ssklower 	if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) {
15436389Ssklower 			return ENAMETOOLONG;
15536389Ssklower 	}
156*37469Ssklower 	if (siso->siso_tsuffixlen) {
157*37469Ssklower 			register char *cp = TSEL(siso);
158*37469Ssklower 			suf.data[0] = cp[0];
159*37469Ssklower 			suf.data[1] = cp[1];
160*37469Ssklower 	}
161*37469Ssklower 	if (siso->siso_nlen) {
16236389Ssklower 		/* non-zero net addr- better match one of our interfaces */
16336389Ssklower 		IFDEBUG(D_ISO)
16436389Ssklower 			printf("iso_pcbbind: bind to NOT zeroisoaddr\n");
16536389Ssklower 		ENDDEBUG
166*37469Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
167*37469Ssklower 			if (SAME_ISOADDR(siso, &ia->ia_addr))
168*37469Ssklower 				break;
169*37469Ssklower 		if (ia == 0)
17036389Ssklower 			return EADDRNOTAVAIL;
17136389Ssklower 	}
172*37469Ssklower 	if (siso->siso_len <= sizeof (isop->isop_sladdr)) {
173*37469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
174*37469Ssklower 	} else {
175*37469Ssklower 		if ((nam = m_copy(nam, 0, (int)M_COPYALL)) == 0)
176*37469Ssklower 			return ENOBUFS;
177*37469Ssklower 		isop->isop_laddr = mtod(nam, struct sockaddr_iso *);
178*37469Ssklower 	}
179*37469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len);
180*37469Ssklower 	if (suf.s) {
181*37469Ssklower 		if((suf.s < ISO_PORT_RESERVED) && (siso->siso_tsuffixlen <= 2) &&
182*37469Ssklower 		   (u.u_uid != 0))
18336389Ssklower 			return EACCES;
18436389Ssklower 		if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
185*37469Ssklower 			iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr))
18636389Ssklower 			return EADDRINUSE;
187*37469Ssklower 	} else {
188*37469Ssklower 		register char *cp;
18936389Ssklower noname:
190*37469Ssklower 		cp = TSEL(isop->isop_laddr);
19136389Ssklower 	IFDEBUG(D_ISO)
19236389Ssklower 		printf("iso_pcbbind noname\n");
19336389Ssklower 	ENDDEBUG
19436389Ssklower 		do {
19536389Ssklower 			if (head->isop_lport++ < ISO_PORT_RESERVED ||
19636389Ssklower 			    head->isop_lport > ISO_PORT_USERRESERVED)
19736389Ssklower 				head->isop_lport = ISO_PORT_RESERVED;
198*37469Ssklower 			suf.s = head->isop_lport;
199*37469Ssklower 			cp[0] = suf.data[0];
200*37469Ssklower 			cp[1] = suf.data[1];
201*37469Ssklower 		} while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr));
202*37469Ssklower 	}
20336389Ssklower 	IFDEBUG(D_ISO)
20436389Ssklower 		printf("iso_pcbbind returns 0, suf 0x%x\n", suf);
20536389Ssklower 	ENDDEBUG
20636389Ssklower 	return 0;
20736389Ssklower }
20836389Ssklower /*
20936389Ssklower  * FUNCTION:		iso_pcbconnect
21036389Ssklower  *
21136389Ssklower  * PURPOSE:			Make the isopcb (isop) look like it's connected.
21236389Ssklower  *					In other words, give it the peer address given in
21336389Ssklower  *					the mbuf * (nam).   Make sure such a combination
21436389Ssklower  *					of local, peer addresses doesn't already exist
21536389Ssklower  *					for this protocol.  Internet mentality prevails here,
21636389Ssklower  *					wherein a src,dst pair uniquely identifies a connection.
21736389Ssklower  * 					Both net address and port must be specified in argument
21836389Ssklower  *					(nam).
21936389Ssklower  * 					If we don't have a local address for this socket yet,
22036389Ssklower  *					we pick one by calling iso_pcbbind().
22136389Ssklower  *
22236389Ssklower  * RETURNS:			errno E* or 0 if ok.
22336389Ssklower  *
22436389Ssklower  * SIDE EFFECTS:	Looks up a route, which may cause one to be left
22536389Ssklower  *					in the isopcb.
22636389Ssklower  *
22736389Ssklower  * NOTES:
22836389Ssklower  */
22936389Ssklower int
23036389Ssklower iso_pcbconnect(isop, nam)
231*37469Ssklower 	register struct isopcb *isop;
23236389Ssklower 	struct mbuf *nam;
23336389Ssklower {
23436389Ssklower 	register struct sockaddr_iso	*siso = mtod(nam, struct sockaddr_iso *);
235*37469Ssklower 	int								local_zero, error = 0;
236*37469Ssklower 	struct iso_ifaddr 				*ia;
23736389Ssklower 
23836389Ssklower 	IFDEBUG(D_ISO)
239*37469Ssklower 		printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x",
240*37469Ssklower 					isop, isop->isop_socket, nam);
241*37469Ssklower 		printf("nam->m_len 0x%x), addr:\n", nam->m_len);
24236389Ssklower 		dump_isoaddr(siso);
24336389Ssklower 	ENDDEBUG
244*37469Ssklower 	if (nam->m_len < siso->siso_len)
245*37469Ssklower 		return EINVAL;
24636389Ssklower 	if (siso->siso_family != AF_ISO)
24736389Ssklower 		return EAFNOSUPPORT;
248*37469Ssklower 	/*
249*37469Ssklower 	 * Local zero means either not bound, or bound to a TSEL, but no
250*37469Ssklower 	 * particular local interface.  So, if we want to send somebody
251*37469Ssklower 	 * we need to choose a return address.
25236389Ssklower 	 */
253*37469Ssklower 	local_zero =
254*37469Ssklower 		((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0));
25536389Ssklower 	if (local_zero) {
256*37469Ssklower 		int flags;
25736389Ssklower 
25836389Ssklower 		IFDEBUG(D_ISO)
25936389Ssklower 			printf("iso_pcbconnect localzero 1\n");
26036389Ssklower 		ENDDEBUG
26136389Ssklower 		/*
26236389Ssklower 		 * If route is known or can be allocated now,
26336389Ssklower 		 * our src addr is taken from the i/f, else punt.
26436389Ssklower 		 */
265*37469Ssklower 		flags = isop->isop_socket->so_options & SO_DONTROUTE;
266*37469Ssklower 		if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags,
267*37469Ssklower 						(struct sockaddr **)0, &ia))
268*37469Ssklower 			return error;
26936389Ssklower 		IFDEBUG(D_ISO)
270*37469Ssklower 			printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x",
271*37469Ssklower 				isop->isop_route.ro_rt);
272*37469Ssklower 			printf(" ia 0x%x\n", ia);
27336389Ssklower 		ENDDEBUG
27436389Ssklower 	}
27536389Ssklower 	IFDEBUG(D_ISO)
27636389Ssklower 		printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n",
27736389Ssklower 			isop, isop->isop_socket);
27836389Ssklower 	ENDDEBUG
27936389Ssklower 	if (local_zero) {
280*37469Ssklower 		int nlen, tlen, totlen; caddr_t oldtsel, newtsel;
281*37469Ssklower 		siso = isop->isop_laddr;
282*37469Ssklower 		if (siso == 0 || siso->siso_tsuffixlen == 0)
28336389Ssklower 			(void)iso_pcbbind(isop, (struct mbuf *)0);
284*37469Ssklower 		/*
285*37469Ssklower 		 * Here we have problem of squezeing in a definite network address
286*37469Ssklower 		 * into an existing sockaddr_iso, which in fact may not have room
287*37469Ssklower 		 * for it.  This gets messy.
288*37469Ssklower 		 */
289*37469Ssklower 		siso = isop->isop_laddr;
290*37469Ssklower 		oldtsel = TSEL(siso);
291*37469Ssklower 		tlen = siso->siso_tsuffixlen;
292*37469Ssklower 		nlen = ia->ia_addr.siso_nlen;
293*37469Ssklower 		totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]);
294*37469Ssklower 		if ((siso == &isop->isop_sladdr) &&
295*37469Ssklower 			(totlen > sizeof(isop->isop_sladdr))) {
296*37469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
297*37469Ssklower 			if (m == 0)
298*37469Ssklower 					return ENOBUFS;
299*37469Ssklower 			m->m_len = totlen;
300*37469Ssklower 			isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *);
301*37469Ssklower 		}
302*37469Ssklower 		siso->siso_nlen = ia->ia_addr.siso_nlen;
303*37469Ssklower 		newtsel = TSEL(siso);
304*37469Ssklower 		ovbcopy(oldtsel, newtsel, tlen);
305*37469Ssklower 		bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
306*37469Ssklower 		siso->siso_tsuffixlen = tlen;
307*37469Ssklower 		siso->siso_family = AF_ISO;
308*37469Ssklower 		siso->siso_len = totlen;
309*37469Ssklower 		siso = mtod(nam, struct sockaddr_iso *);
31036389Ssklower 	}
31136389Ssklower 	IFDEBUG(D_ISO)
31236389Ssklower 		printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n",
31336389Ssklower 			isop, isop->isop_socket);
31436389Ssklower 	ENDDEBUG
315*37469Ssklower 	/*
316*37469Ssklower 	 * If we had to allocate space to a previous big foreign address,
317*37469Ssklower 	 * and for some reason we didn't free it, we reuse it knowing
318*37469Ssklower 	 * that is going to be big enough, as sockaddrs are delivered in
319*37469Ssklower 	 * 128 byte mbufs.
320*37469Ssklower 	 * If the foreign address is small enough, we use default space;
321*37469Ssklower 	 * otherwise, we grab an mbuf to copy into.
322*37469Ssklower 	 */
323*37469Ssklower 	if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) {
324*37469Ssklower 		if (siso->siso_len <= sizeof(isop->isop_sfaddr))
325*37469Ssklower 			isop->isop_faddr = &isop->isop_sfaddr;
326*37469Ssklower 		else {
327*37469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
328*37469Ssklower 			if (m == 0)
329*37469Ssklower 				return ENOBUFS;
330*37469Ssklower 			isop->isop_faddr = mtod(m, struct sockaddr_iso *);
331*37469Ssklower 		}
332*37469Ssklower 	}
333*37469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len);
33436389Ssklower 	IFDEBUG(D_ISO)
33536389Ssklower 		printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n",
33636389Ssklower 			isop, isop->isop_socket);
33736389Ssklower 		printf("iso_pcbconnect connected to addr:\n");
338*37469Ssklower 		dump_isoaddr(isop->isop_faddr);
33936389Ssklower 		printf("iso_pcbconnect end: src addr:\n");
340*37469Ssklower 		dump_isoaddr(isop->isop_laddr);
34136389Ssklower 	ENDDEBUG
34236389Ssklower 	return 0;
34336389Ssklower }
34436389Ssklower 
34536389Ssklower /*
34636389Ssklower  * FUNCTION:		iso_pcbdisconnect()
34736389Ssklower  *
34836389Ssklower  * PURPOSE:			washes away the peer address info so the socket
34936389Ssklower  *					appears to be disconnected.
35036389Ssklower  *					If there's no file descriptor associated with the socket
35136389Ssklower  *					it detaches the pcb.
35236389Ssklower  *
35336389Ssklower  * RETURNS:			Nada.
35436389Ssklower  *
35536389Ssklower  * SIDE EFFECTS:	May detach the pcb.
35636389Ssklower  *
35736389Ssklower  * NOTES:
35836389Ssklower  */
35936389Ssklower void
36036389Ssklower iso_pcbdisconnect(isop)
36136389Ssklower 	struct isopcb *isop;
36236389Ssklower {
36336389Ssklower 	void iso_pcbdetach();
36436389Ssklower 
36536389Ssklower 	IFDEBUG(D_ISO)
36636389Ssklower 		printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
36736389Ssklower 	ENDDEBUG
368*37469Ssklower 	/*
369*37469Ssklower 	 * Preserver binding infnormation if already bound.
370*37469Ssklower 	 */
371*37469Ssklower 	if (isop->isop_laddr && isop->isop_laddr->siso_nlen)
372*37469Ssklower 		isop->isop_laddr->siso_nlen = 0;
373*37469Ssklower 	if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
374*37469Ssklower 		m_freem(dtom(isop->isop_faddr));
375*37469Ssklower 	isop->isop_faddr = 0;
37636389Ssklower 	if (isop->isop_socket->so_state & SS_NOFDREF)
37736389Ssklower 		iso_pcbdetach(isop);
37836389Ssklower }
37936389Ssklower 
38036389Ssklower /*
38136389Ssklower  * FUNCTION:		iso_pcbdetach
38236389Ssklower  *
38336389Ssklower  * PURPOSE:			detach the pcb at *(isop) from it's socket and free
38436389Ssklower  *					the mbufs associated with the pcb..
38536389Ssklower  *					Dequeues (isop) from its head.
38636389Ssklower  *
38736389Ssklower  * RETURNS:			Nada.
38836389Ssklower  *
38936389Ssklower  * SIDE EFFECTS:
39036389Ssklower  *
39136389Ssklower  * NOTES:
39236389Ssklower  */
39336389Ssklower void
39436389Ssklower iso_pcbdetach(isop)
39536389Ssklower 	struct isopcb *isop;
39636389Ssklower {
39736389Ssklower 	struct socket *so = isop->isop_socket;
39836389Ssklower 
39936389Ssklower 	IFDEBUG(D_ISO)
40036389Ssklower 		printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n",
40136389Ssklower 			isop, isop->isop_socket, so);
40236389Ssklower 	ENDDEBUG
40336389Ssklower 	if (so ) { /* in the x.25 domain, we sometimes have no socket */
40436389Ssklower 		so->so_pcb = 0;
40536389Ssklower 		sofree(so);
40636389Ssklower 	}
40736389Ssklower 	IFDEBUG(D_ISO)
40836389Ssklower 		printf("iso_pcbdetach 2 \n");
40936389Ssklower 	ENDDEBUG
41036389Ssklower 	if (isop->isop_options)
41136389Ssklower 		(void)m_free(isop->isop_options);
41236389Ssklower 	IFDEBUG(D_ISO)
41336389Ssklower 		printf("iso_pcbdetach 3 \n");
41436389Ssklower 	ENDDEBUG
41536389Ssklower 	if (isop->isop_route.ro_rt)
41636389Ssklower 		rtfree(isop->isop_route.ro_rt);
41736389Ssklower 	IFDEBUG(D_ISO)
41836389Ssklower 		printf("iso_pcbdetach 3.1\n");
41936389Ssklower 	ENDDEBUG
42036389Ssklower 	if (isop->isop_clnpcache != NULL) {
42136389Ssklower 		struct clnp_cache *clcp =
42236389Ssklower 			mtod(isop->isop_clnpcache, struct clnp_cache *);
42336389Ssklower 		IFDEBUG(D_ISO)
42436389Ssklower 			printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n",
42536389Ssklower 				clcp, clcp->clc_hdr);
42636389Ssklower 		ENDDEBUG
42736389Ssklower 		if (clcp->clc_hdr != NULL)
42836389Ssklower 			m_free(clcp->clc_hdr);
42936389Ssklower 		IFDEBUG(D_ISO)
43036389Ssklower 			printf("iso_pcbdetach 3.3: freeing cache x%x\n",
43136389Ssklower 				isop->isop_clnpcache);
43236389Ssklower 		ENDDEBUG
43336389Ssklower 		m_free(isop->isop_clnpcache);
43436389Ssklower 	}
43536389Ssklower 	IFDEBUG(D_ISO)
43636389Ssklower 		printf("iso_pcbdetach 4 \n");
43736389Ssklower 	ENDDEBUG
43836389Ssklower 	remque(isop);
43936389Ssklower 	IFDEBUG(D_ISO)
44036389Ssklower 		printf("iso_pcbdetach 5 \n");
44136389Ssklower 	ENDDEBUG
442*37469Ssklower 	if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
443*37469Ssklower 		m_freem(dtom(isop->isop_laddr));
444*37469Ssklower 	free((caddr_t)isop, M_IFADDR);
44536389Ssklower }
44636389Ssklower 
44736389Ssklower #ifdef notdef
44836389Ssklower /* NEEDED? */
44936389Ssklower void
45036389Ssklower iso_setsockaddr(isop, nam)
45136389Ssklower 	register struct isopcb *isop;
45236389Ssklower 	struct mbuf *nam;
45336389Ssklower {
45436389Ssklower 	register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
45536389Ssklower 
45636389Ssklower 	nam->m_len = sizeof (*siso);
45736389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
45836389Ssklower 	bzero((caddr_t)siso, sizeof (*siso));
45936389Ssklower 	siso->siso_family = AF_ISO;
46036389Ssklower 	siso->siso_tsuffix = isop->isop_lport;
46136389Ssklower 	siso->siso_addr = isop->isop_laddr.siso_addr;
46236389Ssklower }
46336389Ssklower 
46436389Ssklower /* NEEDED? */
46536389Ssklower void
46636389Ssklower iso_setpeeraddr(isop, nam)
46736389Ssklower 	register struct isopcb *isop;
46836389Ssklower 	struct mbuf *nam;
46936389Ssklower {
47036389Ssklower 	register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
47136389Ssklower 
47236389Ssklower 	nam->m_len = sizeof (*siso);
47336389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
47436389Ssklower 	bzero((caddr_t)siso, sizeof (*siso));
47536389Ssklower 	siso->siso_family = AF_ISO;
47636389Ssklower 	siso->siso_tsuffix = isop->isop_fport;
47736389Ssklower 	siso->siso_addr = isop->isop_faddr.siso_addr;
47836389Ssklower }
47936389Ssklower #endif notdef
48036389Ssklower 
48136389Ssklower /*
48236389Ssklower  * FUNCTION:		iso_pcbnotify
48336389Ssklower  *
48436389Ssklower  * PURPOSE:			notify all connections in this protocol's queue (head)
48536389Ssklower  *					that have peer address (dst) of the problem (errno)
48636389Ssklower  *					by calling (notify) on the connections' isopcbs.
48736389Ssklower  *
48836389Ssklower  * RETURNS:			Rien.
48936389Ssklower  *
49036389Ssklower  * SIDE EFFECTS:
49136389Ssklower  *
49236389Ssklower  * NOTES:			(notify) is called at splimp!
49336389Ssklower  */
49436389Ssklower void
49536389Ssklower iso_pcbnotify(head, dst, errno, notify)
49636389Ssklower 	struct isopcb *head;
49736389Ssklower 	register struct iso_addr *dst;
49836389Ssklower 	int errno, (*notify)();
49936389Ssklower {
50036389Ssklower 	register struct isopcb *isop, *oisop;
50136389Ssklower 	int s = splimp();
50236389Ssklower 
50336389Ssklower 	IFDEBUG(D_ISO)
50436389Ssklower 		printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
50536389Ssklower 	ENDDEBUG
50636389Ssklower 	for (isop = head->isop_next; isop != head;) {
507*37469Ssklower 		if (!iso_addrmatch1(&(isop->isop_faddr->siso_addr), dst) ||
50836389Ssklower 		    isop->isop_socket == 0) {
50936389Ssklower 			IFDEBUG(D_ISO)
51036389Ssklower 				printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
51136389Ssklower 					isop, isop->isop_socket);
51236389Ssklower 				printf("addrmatch cmp'd with (0x%x):\n",
513*37469Ssklower 					&(isop->isop_faddr->siso_addr));
514*37469Ssklower 				dump_isoaddr(isop->isop_faddr);
51536389Ssklower 			ENDDEBUG
51636389Ssklower 			isop = isop->isop_next;
51736389Ssklower 			continue;
51836389Ssklower 		}
51936389Ssklower 		if (errno)
52036389Ssklower 			isop->isop_socket->so_error = errno;
52136389Ssklower 		oisop = isop;
52236389Ssklower 		isop = isop->isop_next;
52336389Ssklower 		if (notify)
52436389Ssklower 			(*notify)(oisop);
52536389Ssklower 	}
52636389Ssklower 	splx(s);
52736389Ssklower 	IFDEBUG(D_ISO)
52836389Ssklower 		printf("END OF iso_pcbnotify\n" );
52936389Ssklower 	ENDDEBUG
53036389Ssklower }
53136389Ssklower 
53236389Ssklower 
53336389Ssklower /*
53436389Ssklower  * FUNCTION:		iso_pcblookup
53536389Ssklower  *
53636389Ssklower  * PURPOSE:			looks for a given combination of (faddr), (fport),
53736389Ssklower  *					(lport), (laddr) in the queue named by (head).
53836389Ssklower  *					Argument (flags) is ignored.
53936389Ssklower  *
54036389Ssklower  * RETURNS:			ptr to the isopcb if it finds a connection matching
54136389Ssklower  *					these arguments, o.w. returns zero.
54236389Ssklower  *
54336389Ssklower  * SIDE EFFECTS:
54436389Ssklower  *
54536389Ssklower  * NOTES:
54636389Ssklower  */
54736389Ssklower struct isopcb *
548*37469Ssklower iso_pcblookup(head, fportlen, fport, laddr)
54936389Ssklower 	struct isopcb *head;
550*37469Ssklower 	register struct sockaddr_iso *laddr;
551*37469Ssklower 	caddr_t fport;
552*37469Ssklower 	int fportlen;
55336389Ssklower {
55436389Ssklower 	register struct isopcb *isop;
555*37469Ssklower 	register caddr_t lp = TSEL(laddr);
556*37469Ssklower 	unsigned int llen = laddr->siso_tsuffixlen;
55736389Ssklower 
55836389Ssklower 	IFDEBUG(D_ISO)
559*37469Ssklower 		printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n",
560*37469Ssklower 			head, laddr, fport);
56136389Ssklower 	ENDDEBUG
56236389Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
563*37469Ssklower 		if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
56436389Ssklower 			continue;
565*37469Ssklower 		if (isop->isop_laddr->siso_tsuffixlen != llen)
56636389Ssklower 			continue;
567*37469Ssklower 		if (bcmp(lp, TSEL(isop->isop_laddr), llen))
568*37469Ssklower 			continue;
569*37469Ssklower 		if (fportlen && isop->isop_faddr &&
570*37469Ssklower 			bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen))
571*37469Ssklower 			continue;
57236389Ssklower 		/*	PHASE2
57336389Ssklower 		 *	addrmatch1 should be iso_addrmatch(a, b, mask)
57436389Ssklower 		 *	where mask is taken from isop->isop_laddrmask (new field)
57536389Ssklower 		 *	isop_lnetmask will also be available in isop
57636389Ssklower 		if (laddr != &zeroiso_addr &&
57736389Ssklower 			!iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr)))
57836389Ssklower 			continue;
579*37469Ssklower 		*/
580*37469Ssklower 		if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr)))
581*37469Ssklower 			continue;
58236389Ssklower 		return (isop);
58336389Ssklower 	}
58436389Ssklower 	return (struct isopcb *)0;
58536389Ssklower }
58636389Ssklower #endif ISO
587