xref: /csrg-svn/sys/netiso/iso_pcb.c (revision 49268)
1*49268Sbostic /*-
2*49268Sbostic  * Copyright (c) 1991 The Regents of the University of California.
3*49268Sbostic  * All rights reserved.
4*49268Sbostic  *
5*49268Sbostic  * %sccs.include.redist.c%
6*49268Sbostic  *
7*49268Sbostic  *	@(#)iso_pcb.c	7.9 (Berkeley) 05/06/91
8*49268Sbostic  */
9*49268Sbostic 
1036389Ssklower /***********************************************************
1136389Ssklower 		Copyright IBM Corporation 1987
1236389Ssklower 
1336389Ssklower                       All Rights Reserved
1436389Ssklower 
1536389Ssklower Permission to use, copy, modify, and distribute this software and its
1636389Ssklower documentation for any purpose and without fee is hereby granted,
1736389Ssklower provided that the above copyright notice appear in all copies and that
1836389Ssklower both that copyright notice and this permission notice appear in
1936389Ssklower supporting documentation, and that the name of IBM not be
2036389Ssklower used in advertising or publicity pertaining to distribution of the
2136389Ssklower software without specific, written prior permission.
2236389Ssklower 
2336389Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2436389Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2536389Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2636389Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2736389Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2836389Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2936389Ssklower SOFTWARE.
3036389Ssklower 
3136389Ssklower ******************************************************************/
3236389Ssklower 
3336389Ssklower /*
3436389Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
3536389Ssklower  */
3636389Ssklower /*
3736389Ssklower  * $Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $
3836389Ssklower  * $Source: /usr/argo/sys/netiso/RCS/iso_pcb.c,v $
3936389Ssklower  *
4036389Ssklower  * Iso address family net-layer(s) pcb stuff. NEH 1/29/87
4136389Ssklower  */
4238477Ssklower 
4336389Ssklower #ifdef ISO
4436389Ssklower 
4536389Ssklower #include "param.h"
4636389Ssklower #include "systm.h"
4736389Ssklower #include "user.h"
4836389Ssklower #include "mbuf.h"
4937469Ssklower #include "socket.h"
5037469Ssklower #include "socketvar.h"
5137469Ssklower #include "argo_debug.h"
5237469Ssklower #include "iso.h"
5337469Ssklower #include "clnp.h"
5436389Ssklower #include "../netinet/in_systm.h"
5536389Ssklower #include "../net/if.h"
5636389Ssklower #include "../net/route.h"
5737469Ssklower #include "iso_pcb.h"
5837469Ssklower #include "iso_var.h"
5936389Ssklower #include "protosw.h"
6036389Ssklower 
6148737Ssklower #ifdef TPCONS
6248737Ssklower #include "../netccitt/x25.h"
6348737Ssklower #include "../netccitt/pk.h"
6448737Ssklower #include "../netccitt/pk_var.h"
6548737Ssklower #endif
6648737Ssklower 
6736389Ssklower #define PCBNULL (struct isopcb *)0
6836389Ssklower struct	iso_addr zeroiso_addr = {
6936389Ssklower 	0
7036389Ssklower };
7136389Ssklower 
7236389Ssklower 
7336389Ssklower /*
7436389Ssklower  * FUNCTION:		iso_pcballoc
7536389Ssklower  *
7636389Ssklower  * PURPOSE:			creates an isopcb structure in an mbuf,
7736389Ssklower  *					with socket (so), and
7836389Ssklower  *					puts it in the queue with head (head)
7936389Ssklower  *
8036389Ssklower  * RETURNS:			0 if OK, ENOBUFS if can't alloc the necessary mbuf
8136389Ssklower  */
8236389Ssklower int
8336389Ssklower iso_pcballoc(so, head)
8436389Ssklower 	struct socket *so;
8536389Ssklower 	struct isopcb *head;
8636389Ssklower {
8736389Ssklower 	register struct isopcb *isop;
8836389Ssklower 
8936389Ssklower 	IFDEBUG(D_ISO)
9036389Ssklower 		printf("iso_pcballoc(so 0x%x)\n", so);
9136389Ssklower 	ENDDEBUG
9237469Ssklower 	MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT);
9337469Ssklower 	if (isop == NULL)
9436389Ssklower 		return ENOBUFS;
9537469Ssklower 	bzero((caddr_t)isop, sizeof(*isop));
9636389Ssklower 	isop->isop_head = head;
9736389Ssklower 	isop->isop_socket = so;
9836389Ssklower 	insque(isop, head);
9948737Ssklower 	if (so)
10048737Ssklower 		so->so_pcb = (caddr_t)isop;
10136389Ssklower 	return 0;
10236389Ssklower }
10336389Ssklower 
10436389Ssklower /*
10536389Ssklower  * FUNCTION:		iso_pcbbind
10636389Ssklower  *
10736389Ssklower  * PURPOSE:			binds the address given in *(nam) to the socket
10836389Ssklower  *					specified by the isopcb in *(isop)
10936389Ssklower  *					If the given address is zero, it makes sure the
11036389Ssklower  *					address isn't already in use and if it's got a network
11136389Ssklower  *					portion, we look for an interface with that network
11236389Ssklower  *					address.  If the address given is zero, we allocate
11336389Ssklower  *					a port and stuff it in the (nam) structure.
11436389Ssklower  *
11536389Ssklower  * RETURNS:			errno E* or 0 if ok.
11636389Ssklower  *
11736389Ssklower  * SIDE EFFECTS:	increments head->isop_lport if it allocates a port #
11836389Ssklower  *
11936389Ssklower  * NOTES:
12036389Ssklower  */
12137469Ssklower #define	satosiso(sa)	((struct sockaddr_iso *)(sa))
12236389Ssklower int
12336389Ssklower iso_pcbbind(isop, nam)
12436389Ssklower 	register struct isopcb *isop;
12536389Ssklower 	struct mbuf *nam;
12636389Ssklower {
12736389Ssklower 	register struct isopcb *head = isop->isop_head;
12836389Ssklower 	register struct sockaddr_iso *siso;
12937469Ssklower 	struct iso_ifaddr *ia;
13037469Ssklower 	union {
13137469Ssklower 		char data[2];
13237469Ssklower 		u_short s;
13337469Ssklower 	} suf;
13436389Ssklower 
13536389Ssklower 	IFDEBUG(D_ISO)
13636389Ssklower 		printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam);
13736389Ssklower 	ENDDEBUG
13837469Ssklower 	suf.s = 0;
13936389Ssklower 	if (iso_ifaddr == 0) /* any interfaces attached? */
14036389Ssklower 		return EADDRNOTAVAIL;
14137469Ssklower 	if (isop->isop_laddr)  /* already bound */
14236389Ssklower 		return EADDRINUSE;
14337469Ssklower 	if(nam == (struct mbuf *)0) {
14437469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
14538841Ssklower 		isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso);
14638841Ssklower 		isop->isop_sladdr.siso_family = AF_ISO;
14738841Ssklower 		isop->isop_sladdr.siso_tlen = 2;
14837469Ssklower 		isop->isop_sladdr.siso_nlen = 0;
14938841Ssklower 		isop->isop_sladdr.siso_slen = 0;
15038841Ssklower 		isop->isop_sladdr.siso_plen = 0;
15136389Ssklower 		goto noname;
15237469Ssklower 	}
15336389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
15436389Ssklower 	IFDEBUG(D_ISO)
15536389Ssklower 		printf("iso_pcbbind(name len 0x%x)\n", nam->m_len);
15636389Ssklower 		printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr));
15736389Ssklower 	ENDDEBUG
15836389Ssklower 	/*
15936389Ssklower 	 * We would like sort of length check but since some OSI addrs
16036389Ssklower 	 * do not have fixed length, we can't really do much.
16136389Ssklower 	 * The ONLY thing we can say is that an osi addr has to have
16236389Ssklower 	 * at LEAST an afi and one more byte and had better fit into
16336389Ssklower 	 * a struct iso_addr.
16436389Ssklower 	 * However, in fact the size of the whole thing is a struct
16536389Ssklower 	 * sockaddr_iso, so probably this is what we should check for.
16636389Ssklower 	 */
16737469Ssklower 	if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) {
16836389Ssklower 			return ENAMETOOLONG;
16936389Ssklower 	}
17038841Ssklower 	if (siso->siso_tlen) {
17137469Ssklower 			register char *cp = TSEL(siso);
17237469Ssklower 			suf.data[0] = cp[0];
17337469Ssklower 			suf.data[1] = cp[1];
17437469Ssklower 	}
17537469Ssklower 	if (siso->siso_nlen) {
17636389Ssklower 		/* non-zero net addr- better match one of our interfaces */
17736389Ssklower 		IFDEBUG(D_ISO)
17836389Ssklower 			printf("iso_pcbbind: bind to NOT zeroisoaddr\n");
17936389Ssklower 		ENDDEBUG
18037469Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
18137469Ssklower 			if (SAME_ISOADDR(siso, &ia->ia_addr))
18237469Ssklower 				break;
18337469Ssklower 		if (ia == 0)
18436389Ssklower 			return EADDRNOTAVAIL;
18536389Ssklower 	}
18637469Ssklower 	if (siso->siso_len <= sizeof (isop->isop_sladdr)) {
18737469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
18837469Ssklower 	} else {
18937469Ssklower 		if ((nam = m_copy(nam, 0, (int)M_COPYALL)) == 0)
19037469Ssklower 			return ENOBUFS;
19137469Ssklower 		isop->isop_laddr = mtod(nam, struct sockaddr_iso *);
19237469Ssklower 	}
19337469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len);
19439934Ssklower 	if (suf.s || siso->siso_tlen != 2) {
19538841Ssklower 		if((suf.s < ISO_PORT_RESERVED) && (siso->siso_tlen <= 2) &&
19637469Ssklower 		   (u.u_uid != 0))
19736389Ssklower 			return EACCES;
19836389Ssklower 		if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
19937469Ssklower 			iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr))
20036389Ssklower 			return EADDRINUSE;
20137469Ssklower 	} else {
20237469Ssklower 		register char *cp;
20336389Ssklower noname:
20437469Ssklower 		cp = TSEL(isop->isop_laddr);
20536389Ssklower 	IFDEBUG(D_ISO)
20636389Ssklower 		printf("iso_pcbbind noname\n");
20736389Ssklower 	ENDDEBUG
20836389Ssklower 		do {
20936389Ssklower 			if (head->isop_lport++ < ISO_PORT_RESERVED ||
21036389Ssklower 			    head->isop_lport > ISO_PORT_USERRESERVED)
21136389Ssklower 				head->isop_lport = ISO_PORT_RESERVED;
21237469Ssklower 			suf.s = head->isop_lport;
21337469Ssklower 			cp[0] = suf.data[0];
21437469Ssklower 			cp[1] = suf.data[1];
21537469Ssklower 		} while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr));
21637469Ssklower 	}
21736389Ssklower 	IFDEBUG(D_ISO)
21836389Ssklower 		printf("iso_pcbbind returns 0, suf 0x%x\n", suf);
21936389Ssklower 	ENDDEBUG
22036389Ssklower 	return 0;
22136389Ssklower }
22236389Ssklower /*
22336389Ssklower  * FUNCTION:		iso_pcbconnect
22436389Ssklower  *
22536389Ssklower  * PURPOSE:			Make the isopcb (isop) look like it's connected.
22636389Ssklower  *					In other words, give it the peer address given in
22736389Ssklower  *					the mbuf * (nam).   Make sure such a combination
22836389Ssklower  *					of local, peer addresses doesn't already exist
22936389Ssklower  *					for this protocol.  Internet mentality prevails here,
23036389Ssklower  *					wherein a src,dst pair uniquely identifies a connection.
23136389Ssklower  * 					Both net address and port must be specified in argument
23236389Ssklower  *					(nam).
23336389Ssklower  * 					If we don't have a local address for this socket yet,
23436389Ssklower  *					we pick one by calling iso_pcbbind().
23536389Ssklower  *
23636389Ssklower  * RETURNS:			errno E* or 0 if ok.
23736389Ssklower  *
23836389Ssklower  * SIDE EFFECTS:	Looks up a route, which may cause one to be left
23936389Ssklower  *					in the isopcb.
24036389Ssklower  *
24136389Ssklower  * NOTES:
24236389Ssklower  */
24336389Ssklower int
24436389Ssklower iso_pcbconnect(isop, nam)
24537469Ssklower 	register struct isopcb *isop;
24636389Ssklower 	struct mbuf *nam;
24736389Ssklower {
24836389Ssklower 	register struct sockaddr_iso	*siso = mtod(nam, struct sockaddr_iso *);
24937469Ssklower 	int								local_zero, error = 0;
25037469Ssklower 	struct iso_ifaddr 				*ia;
25136389Ssklower 
25236389Ssklower 	IFDEBUG(D_ISO)
25337469Ssklower 		printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x",
25437469Ssklower 					isop, isop->isop_socket, nam);
25537469Ssklower 		printf("nam->m_len 0x%x), addr:\n", nam->m_len);
25636389Ssklower 		dump_isoaddr(siso);
25736389Ssklower 	ENDDEBUG
25837469Ssklower 	if (nam->m_len < siso->siso_len)
25937469Ssklower 		return EINVAL;
26036389Ssklower 	if (siso->siso_family != AF_ISO)
26136389Ssklower 		return EAFNOSUPPORT;
26238477Ssklower 	if (siso->siso_nlen == 0) {
26338477Ssklower 		if (ia = iso_ifaddr) {
26438477Ssklower 			int nlen = ia->ia_addr.siso_nlen;
26538477Ssklower 			ovbcopy(TSEL(siso), nlen + TSEL(siso),
26638841Ssklower 				siso->siso_plen + siso->siso_tlen + siso->siso_slen);
26738477Ssklower 			bcopy((caddr_t)&ia->ia_addr.siso_addr,
26838477Ssklower 				  (caddr_t)&siso->siso_addr, nlen + 1);
26938477Ssklower 			/* includes siso->siso_nlen = nlen; */
27038477Ssklower 		} else
27138477Ssklower 			return EADDRNOTAVAIL;
27238477Ssklower 	}
27337469Ssklower 	/*
27437469Ssklower 	 * Local zero means either not bound, or bound to a TSEL, but no
27537469Ssklower 	 * particular local interface.  So, if we want to send somebody
27637469Ssklower 	 * we need to choose a return address.
27736389Ssklower 	 */
27837469Ssklower 	local_zero =
27937469Ssklower 		((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0));
28036389Ssklower 	if (local_zero) {
28137469Ssklower 		int flags;
28236389Ssklower 
28336389Ssklower 		IFDEBUG(D_ISO)
28436389Ssklower 			printf("iso_pcbconnect localzero 1\n");
28536389Ssklower 		ENDDEBUG
28636389Ssklower 		/*
28736389Ssklower 		 * If route is known or can be allocated now,
28836389Ssklower 		 * our src addr is taken from the i/f, else punt.
28936389Ssklower 		 */
29037469Ssklower 		flags = isop->isop_socket->so_options & SO_DONTROUTE;
29137469Ssklower 		if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags,
29237469Ssklower 						(struct sockaddr **)0, &ia))
29337469Ssklower 			return error;
29436389Ssklower 		IFDEBUG(D_ISO)
29537469Ssklower 			printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x",
29637469Ssklower 				isop->isop_route.ro_rt);
29737469Ssklower 			printf(" ia 0x%x\n", ia);
29836389Ssklower 		ENDDEBUG
29936389Ssklower 	}
30036389Ssklower 	IFDEBUG(D_ISO)
30136389Ssklower 		printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n",
30236389Ssklower 			isop, isop->isop_socket);
30336389Ssklower 	ENDDEBUG
30436389Ssklower 	if (local_zero) {
30537469Ssklower 		int nlen, tlen, totlen; caddr_t oldtsel, newtsel;
30637469Ssklower 		siso = isop->isop_laddr;
30738841Ssklower 		if (siso == 0 || siso->siso_tlen == 0)
30836389Ssklower 			(void)iso_pcbbind(isop, (struct mbuf *)0);
30937469Ssklower 		/*
31037469Ssklower 		 * Here we have problem of squezeing in a definite network address
31137469Ssklower 		 * into an existing sockaddr_iso, which in fact may not have room
31237469Ssklower 		 * for it.  This gets messy.
31337469Ssklower 		 */
31437469Ssklower 		siso = isop->isop_laddr;
31537469Ssklower 		oldtsel = TSEL(siso);
31638841Ssklower 		tlen = siso->siso_tlen;
31737469Ssklower 		nlen = ia->ia_addr.siso_nlen;
31837469Ssklower 		totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]);
31937469Ssklower 		if ((siso == &isop->isop_sladdr) &&
32037469Ssklower 			(totlen > sizeof(isop->isop_sladdr))) {
32137469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
32237469Ssklower 			if (m == 0)
32337469Ssklower 					return ENOBUFS;
32437469Ssklower 			m->m_len = totlen;
32537469Ssklower 			isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *);
32637469Ssklower 		}
32737469Ssklower 		siso->siso_nlen = ia->ia_addr.siso_nlen;
32837469Ssklower 		newtsel = TSEL(siso);
32937469Ssklower 		ovbcopy(oldtsel, newtsel, tlen);
33037469Ssklower 		bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
33138841Ssklower 		siso->siso_tlen = tlen;
33237469Ssklower 		siso->siso_family = AF_ISO;
33337469Ssklower 		siso->siso_len = totlen;
33437469Ssklower 		siso = mtod(nam, struct sockaddr_iso *);
33536389Ssklower 	}
33636389Ssklower 	IFDEBUG(D_ISO)
33736389Ssklower 		printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n",
33836389Ssklower 			isop, isop->isop_socket);
33936389Ssklower 	ENDDEBUG
34037469Ssklower 	/*
34137469Ssklower 	 * If we had to allocate space to a previous big foreign address,
34237469Ssklower 	 * and for some reason we didn't free it, we reuse it knowing
34337469Ssklower 	 * that is going to be big enough, as sockaddrs are delivered in
34437469Ssklower 	 * 128 byte mbufs.
34537469Ssklower 	 * If the foreign address is small enough, we use default space;
34637469Ssklower 	 * otherwise, we grab an mbuf to copy into.
34737469Ssklower 	 */
34837469Ssklower 	if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) {
34937469Ssklower 		if (siso->siso_len <= sizeof(isop->isop_sfaddr))
35037469Ssklower 			isop->isop_faddr = &isop->isop_sfaddr;
35137469Ssklower 		else {
35237469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
35337469Ssklower 			if (m == 0)
35437469Ssklower 				return ENOBUFS;
35537469Ssklower 			isop->isop_faddr = mtod(m, struct sockaddr_iso *);
35637469Ssklower 		}
35737469Ssklower 	}
35837469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len);
35936389Ssklower 	IFDEBUG(D_ISO)
36036389Ssklower 		printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n",
36136389Ssklower 			isop, isop->isop_socket);
36236389Ssklower 		printf("iso_pcbconnect connected to addr:\n");
36337469Ssklower 		dump_isoaddr(isop->isop_faddr);
36436389Ssklower 		printf("iso_pcbconnect end: src addr:\n");
36537469Ssklower 		dump_isoaddr(isop->isop_laddr);
36636389Ssklower 	ENDDEBUG
36736389Ssklower 	return 0;
36836389Ssklower }
36936389Ssklower 
37036389Ssklower /*
37136389Ssklower  * FUNCTION:		iso_pcbdisconnect()
37236389Ssklower  *
37336389Ssklower  * PURPOSE:			washes away the peer address info so the socket
37436389Ssklower  *					appears to be disconnected.
37536389Ssklower  *					If there's no file descriptor associated with the socket
37636389Ssklower  *					it detaches the pcb.
37736389Ssklower  *
37836389Ssklower  * RETURNS:			Nada.
37936389Ssklower  *
38036389Ssklower  * SIDE EFFECTS:	May detach the pcb.
38136389Ssklower  *
38236389Ssklower  * NOTES:
38336389Ssklower  */
38436389Ssklower void
38536389Ssklower iso_pcbdisconnect(isop)
38636389Ssklower 	struct isopcb *isop;
38736389Ssklower {
38836389Ssklower 	void iso_pcbdetach();
38939934Ssklower 	register struct sockaddr_iso *siso;
39036389Ssklower 
39136389Ssklower 	IFDEBUG(D_ISO)
39236389Ssklower 		printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
39336389Ssklower 	ENDDEBUG
39437469Ssklower 	/*
39537469Ssklower 	 * Preserver binding infnormation if already bound.
39637469Ssklower 	 */
39739934Ssklower 	if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) {
39839934Ssklower 		caddr_t otsel = TSEL(siso);
39939934Ssklower 		siso->siso_nlen = 0;
40039934Ssklower 		ovbcopy(otsel, TSEL(siso), siso->siso_tlen);
40139934Ssklower 	}
40237469Ssklower 	if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
40337469Ssklower 		m_freem(dtom(isop->isop_faddr));
40437469Ssklower 	isop->isop_faddr = 0;
40536389Ssklower 	if (isop->isop_socket->so_state & SS_NOFDREF)
40636389Ssklower 		iso_pcbdetach(isop);
40736389Ssklower }
40836389Ssklower 
40936389Ssklower /*
41036389Ssklower  * FUNCTION:		iso_pcbdetach
41136389Ssklower  *
41236389Ssklower  * PURPOSE:			detach the pcb at *(isop) from it's socket and free
41336389Ssklower  *					the mbufs associated with the pcb..
41436389Ssklower  *					Dequeues (isop) from its head.
41536389Ssklower  *
41636389Ssklower  * RETURNS:			Nada.
41736389Ssklower  *
41836389Ssklower  * SIDE EFFECTS:
41936389Ssklower  *
42036389Ssklower  * NOTES:
42136389Ssklower  */
42236389Ssklower void
42336389Ssklower iso_pcbdetach(isop)
42436389Ssklower 	struct isopcb *isop;
42536389Ssklower {
42636389Ssklower 	struct socket *so = isop->isop_socket;
42736389Ssklower 
42836389Ssklower 	IFDEBUG(D_ISO)
42936389Ssklower 		printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n",
43036389Ssklower 			isop, isop->isop_socket, so);
43136389Ssklower 	ENDDEBUG
43248737Ssklower #ifdef TPCONS
43348737Ssklower 	if (isop->isop_refcnt) {
43448737Ssklower 		register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
43548737Ssklower 		if (--isop->isop_refcnt > 0)
43648737Ssklower 			return;
43748737Ssklower 		if (lcp && lcp->lcd_state == DATA_TRANSFER)
43848737Ssklower 			pk_disconnect(lcp);
43948737Ssklower 		isop->isop_chan = 0;
44048737Ssklower 	}
44148737Ssklower #endif
44248737Ssklower 	if (so) { /* in the x.25 domain, we sometimes have no socket */
44336389Ssklower 		so->so_pcb = 0;
44436389Ssklower 		sofree(so);
44536389Ssklower 	}
44636389Ssklower 	IFDEBUG(D_ISO)
44736389Ssklower 		printf("iso_pcbdetach 2 \n");
44836389Ssklower 	ENDDEBUG
44936389Ssklower 	if (isop->isop_options)
45036389Ssklower 		(void)m_free(isop->isop_options);
45136389Ssklower 	IFDEBUG(D_ISO)
45236389Ssklower 		printf("iso_pcbdetach 3 \n");
45336389Ssklower 	ENDDEBUG
45436389Ssklower 	if (isop->isop_route.ro_rt)
45536389Ssklower 		rtfree(isop->isop_route.ro_rt);
45636389Ssklower 	IFDEBUG(D_ISO)
45736389Ssklower 		printf("iso_pcbdetach 3.1\n");
45836389Ssklower 	ENDDEBUG
45936389Ssklower 	if (isop->isop_clnpcache != NULL) {
46036389Ssklower 		struct clnp_cache *clcp =
46136389Ssklower 			mtod(isop->isop_clnpcache, struct clnp_cache *);
46236389Ssklower 		IFDEBUG(D_ISO)
46336389Ssklower 			printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n",
46436389Ssklower 				clcp, clcp->clc_hdr);
46536389Ssklower 		ENDDEBUG
46636389Ssklower 		if (clcp->clc_hdr != NULL)
46736389Ssklower 			m_free(clcp->clc_hdr);
46836389Ssklower 		IFDEBUG(D_ISO)
46936389Ssklower 			printf("iso_pcbdetach 3.3: freeing cache x%x\n",
47036389Ssklower 				isop->isop_clnpcache);
47136389Ssklower 		ENDDEBUG
47236389Ssklower 		m_free(isop->isop_clnpcache);
47336389Ssklower 	}
47436389Ssklower 	IFDEBUG(D_ISO)
47536389Ssklower 		printf("iso_pcbdetach 4 \n");
47636389Ssklower 	ENDDEBUG
47736389Ssklower 	remque(isop);
47836389Ssklower 	IFDEBUG(D_ISO)
47936389Ssklower 		printf("iso_pcbdetach 5 \n");
48036389Ssklower 	ENDDEBUG
48137469Ssklower 	if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
48237469Ssklower 		m_freem(dtom(isop->isop_laddr));
48340951Ssklower 	free((caddr_t)isop, M_PCB);
48436389Ssklower }
48536389Ssklower 
48636389Ssklower 
48736389Ssklower /*
48836389Ssklower  * FUNCTION:		iso_pcbnotify
48936389Ssklower  *
49036389Ssklower  * PURPOSE:			notify all connections in this protocol's queue (head)
49136389Ssklower  *					that have peer address (dst) of the problem (errno)
49236389Ssklower  *					by calling (notify) on the connections' isopcbs.
49336389Ssklower  *
49436389Ssklower  * RETURNS:			Rien.
49536389Ssklower  *
49636389Ssklower  * SIDE EFFECTS:
49736389Ssklower  *
49836389Ssklower  * NOTES:			(notify) is called at splimp!
49936389Ssklower  */
50036389Ssklower void
50139934Ssklower iso_pcbnotify(head, siso, errno, notify)
50236389Ssklower 	struct isopcb *head;
50339934Ssklower 	register struct sockaddr_iso *siso;
50436389Ssklower 	int errno, (*notify)();
50536389Ssklower {
50639934Ssklower 	register struct isopcb *isop;
50736389Ssklower 	int s = splimp();
50836389Ssklower 
50936389Ssklower 	IFDEBUG(D_ISO)
51036389Ssklower 		printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
51136389Ssklower 	ENDDEBUG
51239934Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
51339934Ssklower 		if (isop->isop_socket == 0 || isop->isop_faddr == 0 ||
51439934Ssklower 			!SAME_ISOADDR(siso, isop->isop_faddr)) {
51536389Ssklower 			IFDEBUG(D_ISO)
51636389Ssklower 				printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
51736389Ssklower 					isop, isop->isop_socket);
51839934Ssklower 				printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr);
51937469Ssklower 				dump_isoaddr(isop->isop_faddr);
52036389Ssklower 			ENDDEBUG
52136389Ssklower 			continue;
52236389Ssklower 		}
52336389Ssklower 		if (errno)
52436389Ssklower 			isop->isop_socket->so_error = errno;
52536389Ssklower 		if (notify)
52639934Ssklower 			(*notify)(isop);
52736389Ssklower 	}
52836389Ssklower 	splx(s);
52936389Ssklower 	IFDEBUG(D_ISO)
53036389Ssklower 		printf("END OF iso_pcbnotify\n" );
53136389Ssklower 	ENDDEBUG
53236389Ssklower }
53336389Ssklower 
53436389Ssklower 
53536389Ssklower /*
53636389Ssklower  * FUNCTION:		iso_pcblookup
53736389Ssklower  *
53836389Ssklower  * PURPOSE:			looks for a given combination of (faddr), (fport),
53936389Ssklower  *					(lport), (laddr) in the queue named by (head).
54036389Ssklower  *					Argument (flags) is ignored.
54136389Ssklower  *
54236389Ssklower  * RETURNS:			ptr to the isopcb if it finds a connection matching
54336389Ssklower  *					these arguments, o.w. returns zero.
54436389Ssklower  *
54536389Ssklower  * SIDE EFFECTS:
54636389Ssklower  *
54736389Ssklower  * NOTES:
54836389Ssklower  */
54936389Ssklower struct isopcb *
55037469Ssklower iso_pcblookup(head, fportlen, fport, laddr)
55136389Ssklower 	struct isopcb *head;
55237469Ssklower 	register struct sockaddr_iso *laddr;
55337469Ssklower 	caddr_t fport;
55437469Ssklower 	int fportlen;
55536389Ssklower {
55636389Ssklower 	register struct isopcb *isop;
55737469Ssklower 	register caddr_t lp = TSEL(laddr);
55838841Ssklower 	unsigned int llen = laddr->siso_tlen;
55936389Ssklower 
56036389Ssklower 	IFDEBUG(D_ISO)
56137469Ssklower 		printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n",
56237469Ssklower 			head, laddr, fport);
56336389Ssklower 	ENDDEBUG
56436389Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
56537469Ssklower 		if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
56636389Ssklower 			continue;
56738841Ssklower 		if (isop->isop_laddr->siso_tlen != llen)
56836389Ssklower 			continue;
56937469Ssklower 		if (bcmp(lp, TSEL(isop->isop_laddr), llen))
57037469Ssklower 			continue;
57137469Ssklower 		if (fportlen && isop->isop_faddr &&
57237469Ssklower 			bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen))
57337469Ssklower 			continue;
57436389Ssklower 		/*	PHASE2
57536389Ssklower 		 *	addrmatch1 should be iso_addrmatch(a, b, mask)
57636389Ssklower 		 *	where mask is taken from isop->isop_laddrmask (new field)
57736389Ssklower 		 *	isop_lnetmask will also be available in isop
57836389Ssklower 		if (laddr != &zeroiso_addr &&
57936389Ssklower 			!iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr)))
58036389Ssklower 			continue;
58137469Ssklower 		*/
58237469Ssklower 		if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr)))
58337469Ssklower 			continue;
58436389Ssklower 		return (isop);
58536389Ssklower 	}
58636389Ssklower 	return (struct isopcb *)0;
58736389Ssklower }
58836389Ssklower #endif ISO
589