xref: /csrg-svn/sys/netiso/iso_pcb.c (revision 50235)
149268Sbostic /*-
249268Sbostic  * Copyright (c) 1991 The Regents of the University of California.
349268Sbostic  * All rights reserved.
449268Sbostic  *
549268Sbostic  * %sccs.include.redist.c%
649268Sbostic  *
7*50235Ssklower  *	@(#)iso_pcb.c	7.10 (Berkeley) 06/27/91
849268Sbostic  */
949268Sbostic 
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 "mbuf.h"
4837469Ssklower #include "socket.h"
4937469Ssklower #include "socketvar.h"
50*50235Ssklower #include "errno.h"
51*50235Ssklower 
5237469Ssklower #include "argo_debug.h"
5337469Ssklower #include "iso.h"
5437469Ssklower #include "clnp.h"
5536389Ssklower #include "../netinet/in_systm.h"
5636389Ssklower #include "../net/if.h"
5736389Ssklower #include "../net/route.h"
5837469Ssklower #include "iso_pcb.h"
5937469Ssklower #include "iso_var.h"
6036389Ssklower #include "protosw.h"
6136389Ssklower 
6248737Ssklower #ifdef TPCONS
6348737Ssklower #include "../netccitt/x25.h"
6448737Ssklower #include "../netccitt/pk.h"
6548737Ssklower #include "../netccitt/pk_var.h"
6648737Ssklower #endif
6748737Ssklower 
6836389Ssklower #define PCBNULL (struct isopcb *)0
6936389Ssklower struct	iso_addr zeroiso_addr = {
7036389Ssklower 	0
7136389Ssklower };
7236389Ssklower 
7336389Ssklower 
7436389Ssklower /*
7536389Ssklower  * FUNCTION:		iso_pcballoc
7636389Ssklower  *
7736389Ssklower  * PURPOSE:			creates an isopcb structure in an mbuf,
7836389Ssklower  *					with socket (so), and
7936389Ssklower  *					puts it in the queue with head (head)
8036389Ssklower  *
8136389Ssklower  * RETURNS:			0 if OK, ENOBUFS if can't alloc the necessary mbuf
8236389Ssklower  */
8336389Ssklower int
8436389Ssklower iso_pcballoc(so, head)
8536389Ssklower 	struct socket *so;
8636389Ssklower 	struct isopcb *head;
8736389Ssklower {
8836389Ssklower 	register struct isopcb *isop;
8936389Ssklower 
9036389Ssklower 	IFDEBUG(D_ISO)
9136389Ssklower 		printf("iso_pcballoc(so 0x%x)\n", so);
9236389Ssklower 	ENDDEBUG
9337469Ssklower 	MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT);
9437469Ssklower 	if (isop == NULL)
9536389Ssklower 		return ENOBUFS;
9637469Ssklower 	bzero((caddr_t)isop, sizeof(*isop));
9736389Ssklower 	isop->isop_head = head;
9836389Ssklower 	isop->isop_socket = so;
9936389Ssklower 	insque(isop, head);
10048737Ssklower 	if (so)
10148737Ssklower 		so->so_pcb = (caddr_t)isop;
10236389Ssklower 	return 0;
10336389Ssklower }
10436389Ssklower 
10536389Ssklower /*
10636389Ssklower  * FUNCTION:		iso_pcbbind
10736389Ssklower  *
10836389Ssklower  * PURPOSE:			binds the address given in *(nam) to the socket
10936389Ssklower  *					specified by the isopcb in *(isop)
11036389Ssklower  *					If the given address is zero, it makes sure the
11136389Ssklower  *					address isn't already in use and if it's got a network
11236389Ssklower  *					portion, we look for an interface with that network
11336389Ssklower  *					address.  If the address given is zero, we allocate
11436389Ssklower  *					a port and stuff it in the (nam) structure.
11536389Ssklower  *
11636389Ssklower  * RETURNS:			errno E* or 0 if ok.
11736389Ssklower  *
11836389Ssklower  * SIDE EFFECTS:	increments head->isop_lport if it allocates a port #
11936389Ssklower  *
12036389Ssklower  * NOTES:
12136389Ssklower  */
12237469Ssklower #define	satosiso(sa)	((struct sockaddr_iso *)(sa))
12336389Ssklower int
12436389Ssklower iso_pcbbind(isop, nam)
12536389Ssklower 	register struct isopcb *isop;
12636389Ssklower 	struct mbuf *nam;
12736389Ssklower {
12836389Ssklower 	register struct isopcb *head = isop->isop_head;
12936389Ssklower 	register struct sockaddr_iso *siso;
13037469Ssklower 	struct iso_ifaddr *ia;
13137469Ssklower 	union {
13237469Ssklower 		char data[2];
13337469Ssklower 		u_short s;
13437469Ssklower 	} suf;
13536389Ssklower 
13636389Ssklower 	IFDEBUG(D_ISO)
13736389Ssklower 		printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam);
13836389Ssklower 	ENDDEBUG
13937469Ssklower 	suf.s = 0;
14036389Ssklower 	if (iso_ifaddr == 0) /* any interfaces attached? */
14136389Ssklower 		return EADDRNOTAVAIL;
14237469Ssklower 	if (isop->isop_laddr)  /* already bound */
14336389Ssklower 		return EADDRINUSE;
14437469Ssklower 	if(nam == (struct mbuf *)0) {
14537469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
14638841Ssklower 		isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso);
14738841Ssklower 		isop->isop_sladdr.siso_family = AF_ISO;
14838841Ssklower 		isop->isop_sladdr.siso_tlen = 2;
14937469Ssklower 		isop->isop_sladdr.siso_nlen = 0;
15038841Ssklower 		isop->isop_sladdr.siso_slen = 0;
15138841Ssklower 		isop->isop_sladdr.siso_plen = 0;
15236389Ssklower 		goto noname;
15337469Ssklower 	}
15436389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
15536389Ssklower 	IFDEBUG(D_ISO)
15636389Ssklower 		printf("iso_pcbbind(name len 0x%x)\n", nam->m_len);
15736389Ssklower 		printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr));
15836389Ssklower 	ENDDEBUG
15936389Ssklower 	/*
16036389Ssklower 	 * We would like sort of length check but since some OSI addrs
16136389Ssklower 	 * do not have fixed length, we can't really do much.
16236389Ssklower 	 * The ONLY thing we can say is that an osi addr has to have
16336389Ssklower 	 * at LEAST an afi and one more byte and had better fit into
16436389Ssklower 	 * a struct iso_addr.
16536389Ssklower 	 * However, in fact the size of the whole thing is a struct
16636389Ssklower 	 * sockaddr_iso, so probably this is what we should check for.
16736389Ssklower 	 */
16837469Ssklower 	if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) {
16936389Ssklower 			return ENAMETOOLONG;
17036389Ssklower 	}
17138841Ssklower 	if (siso->siso_tlen) {
17237469Ssklower 			register char *cp = TSEL(siso);
17337469Ssklower 			suf.data[0] = cp[0];
17437469Ssklower 			suf.data[1] = cp[1];
17537469Ssklower 	}
17637469Ssklower 	if (siso->siso_nlen) {
17736389Ssklower 		/* non-zero net addr- better match one of our interfaces */
17836389Ssklower 		IFDEBUG(D_ISO)
17936389Ssklower 			printf("iso_pcbbind: bind to NOT zeroisoaddr\n");
18036389Ssklower 		ENDDEBUG
18137469Ssklower 		for (ia = iso_ifaddr; ia; ia = ia->ia_next)
18237469Ssklower 			if (SAME_ISOADDR(siso, &ia->ia_addr))
18337469Ssklower 				break;
18437469Ssklower 		if (ia == 0)
18536389Ssklower 			return EADDRNOTAVAIL;
18636389Ssklower 	}
18737469Ssklower 	if (siso->siso_len <= sizeof (isop->isop_sladdr)) {
18837469Ssklower 		isop->isop_laddr = &isop->isop_sladdr;
18937469Ssklower 	} else {
19037469Ssklower 		if ((nam = m_copy(nam, 0, (int)M_COPYALL)) == 0)
19137469Ssklower 			return ENOBUFS;
19237469Ssklower 		isop->isop_laddr = mtod(nam, struct sockaddr_iso *);
19337469Ssklower 	}
19437469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len);
19539934Ssklower 	if (suf.s || siso->siso_tlen != 2) {
19638841Ssklower 		if((suf.s < ISO_PORT_RESERVED) && (siso->siso_tlen <= 2) &&
197*50235Ssklower 		   (isop->isop_socket->so_state && SS_PRIV) == 0)
19836389Ssklower 			return EACCES;
19936389Ssklower 		if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
20037469Ssklower 			iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr))
20136389Ssklower 			return EADDRINUSE;
20237469Ssklower 	} else {
20337469Ssklower 		register char *cp;
20436389Ssklower noname:
20537469Ssklower 		cp = TSEL(isop->isop_laddr);
20636389Ssklower 	IFDEBUG(D_ISO)
20736389Ssklower 		printf("iso_pcbbind noname\n");
20836389Ssklower 	ENDDEBUG
20936389Ssklower 		do {
21036389Ssklower 			if (head->isop_lport++ < ISO_PORT_RESERVED ||
21136389Ssklower 			    head->isop_lport > ISO_PORT_USERRESERVED)
21236389Ssklower 				head->isop_lport = ISO_PORT_RESERVED;
21337469Ssklower 			suf.s = head->isop_lport;
21437469Ssklower 			cp[0] = suf.data[0];
21537469Ssklower 			cp[1] = suf.data[1];
21637469Ssklower 		} while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr));
21737469Ssklower 	}
21836389Ssklower 	IFDEBUG(D_ISO)
21936389Ssklower 		printf("iso_pcbbind returns 0, suf 0x%x\n", suf);
22036389Ssklower 	ENDDEBUG
22136389Ssklower 	return 0;
22236389Ssklower }
22336389Ssklower /*
22436389Ssklower  * FUNCTION:		iso_pcbconnect
22536389Ssklower  *
22636389Ssklower  * PURPOSE:			Make the isopcb (isop) look like it's connected.
22736389Ssklower  *					In other words, give it the peer address given in
22836389Ssklower  *					the mbuf * (nam).   Make sure such a combination
22936389Ssklower  *					of local, peer addresses doesn't already exist
23036389Ssklower  *					for this protocol.  Internet mentality prevails here,
23136389Ssklower  *					wherein a src,dst pair uniquely identifies a connection.
23236389Ssklower  * 					Both net address and port must be specified in argument
23336389Ssklower  *					(nam).
23436389Ssklower  * 					If we don't have a local address for this socket yet,
23536389Ssklower  *					we pick one by calling iso_pcbbind().
23636389Ssklower  *
23736389Ssklower  * RETURNS:			errno E* or 0 if ok.
23836389Ssklower  *
23936389Ssklower  * SIDE EFFECTS:	Looks up a route, which may cause one to be left
24036389Ssklower  *					in the isopcb.
24136389Ssklower  *
24236389Ssklower  * NOTES:
24336389Ssklower  */
24436389Ssklower int
24536389Ssklower iso_pcbconnect(isop, nam)
24637469Ssklower 	register struct isopcb *isop;
24736389Ssklower 	struct mbuf *nam;
24836389Ssklower {
24936389Ssklower 	register struct sockaddr_iso	*siso = mtod(nam, struct sockaddr_iso *);
25037469Ssklower 	int								local_zero, error = 0;
25137469Ssklower 	struct iso_ifaddr 				*ia;
25236389Ssklower 
25336389Ssklower 	IFDEBUG(D_ISO)
25437469Ssklower 		printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x",
25537469Ssklower 					isop, isop->isop_socket, nam);
25637469Ssklower 		printf("nam->m_len 0x%x), addr:\n", nam->m_len);
25736389Ssklower 		dump_isoaddr(siso);
25836389Ssklower 	ENDDEBUG
25937469Ssklower 	if (nam->m_len < siso->siso_len)
26037469Ssklower 		return EINVAL;
26136389Ssklower 	if (siso->siso_family != AF_ISO)
26236389Ssklower 		return EAFNOSUPPORT;
26338477Ssklower 	if (siso->siso_nlen == 0) {
26438477Ssklower 		if (ia = iso_ifaddr) {
26538477Ssklower 			int nlen = ia->ia_addr.siso_nlen;
26638477Ssklower 			ovbcopy(TSEL(siso), nlen + TSEL(siso),
26738841Ssklower 				siso->siso_plen + siso->siso_tlen + siso->siso_slen);
26838477Ssklower 			bcopy((caddr_t)&ia->ia_addr.siso_addr,
26938477Ssklower 				  (caddr_t)&siso->siso_addr, nlen + 1);
27038477Ssklower 			/* includes siso->siso_nlen = nlen; */
27138477Ssklower 		} else
27238477Ssklower 			return EADDRNOTAVAIL;
27338477Ssklower 	}
27437469Ssklower 	/*
27537469Ssklower 	 * Local zero means either not bound, or bound to a TSEL, but no
27637469Ssklower 	 * particular local interface.  So, if we want to send somebody
27737469Ssklower 	 * we need to choose a return address.
27836389Ssklower 	 */
27937469Ssklower 	local_zero =
28037469Ssklower 		((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0));
28136389Ssklower 	if (local_zero) {
28237469Ssklower 		int flags;
28336389Ssklower 
28436389Ssklower 		IFDEBUG(D_ISO)
28536389Ssklower 			printf("iso_pcbconnect localzero 1\n");
28636389Ssklower 		ENDDEBUG
28736389Ssklower 		/*
28836389Ssklower 		 * If route is known or can be allocated now,
28936389Ssklower 		 * our src addr is taken from the i/f, else punt.
29036389Ssklower 		 */
29137469Ssklower 		flags = isop->isop_socket->so_options & SO_DONTROUTE;
29237469Ssklower 		if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags,
29337469Ssklower 						(struct sockaddr **)0, &ia))
29437469Ssklower 			return error;
29536389Ssklower 		IFDEBUG(D_ISO)
29637469Ssklower 			printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x",
29737469Ssklower 				isop->isop_route.ro_rt);
29837469Ssklower 			printf(" ia 0x%x\n", ia);
29936389Ssklower 		ENDDEBUG
30036389Ssklower 	}
30136389Ssklower 	IFDEBUG(D_ISO)
30236389Ssklower 		printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n",
30336389Ssklower 			isop, isop->isop_socket);
30436389Ssklower 	ENDDEBUG
30536389Ssklower 	if (local_zero) {
30637469Ssklower 		int nlen, tlen, totlen; caddr_t oldtsel, newtsel;
30737469Ssklower 		siso = isop->isop_laddr;
30838841Ssklower 		if (siso == 0 || siso->siso_tlen == 0)
30936389Ssklower 			(void)iso_pcbbind(isop, (struct mbuf *)0);
31037469Ssklower 		/*
31137469Ssklower 		 * Here we have problem of squezeing in a definite network address
31237469Ssklower 		 * into an existing sockaddr_iso, which in fact may not have room
31337469Ssklower 		 * for it.  This gets messy.
31437469Ssklower 		 */
31537469Ssklower 		siso = isop->isop_laddr;
31637469Ssklower 		oldtsel = TSEL(siso);
31738841Ssklower 		tlen = siso->siso_tlen;
31837469Ssklower 		nlen = ia->ia_addr.siso_nlen;
31937469Ssklower 		totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]);
32037469Ssklower 		if ((siso == &isop->isop_sladdr) &&
32137469Ssklower 			(totlen > sizeof(isop->isop_sladdr))) {
32237469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
32337469Ssklower 			if (m == 0)
32437469Ssklower 					return ENOBUFS;
32537469Ssklower 			m->m_len = totlen;
32637469Ssklower 			isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *);
32737469Ssklower 		}
32837469Ssklower 		siso->siso_nlen = ia->ia_addr.siso_nlen;
32937469Ssklower 		newtsel = TSEL(siso);
33037469Ssklower 		ovbcopy(oldtsel, newtsel, tlen);
33137469Ssklower 		bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
33238841Ssklower 		siso->siso_tlen = tlen;
33337469Ssklower 		siso->siso_family = AF_ISO;
33437469Ssklower 		siso->siso_len = totlen;
33537469Ssklower 		siso = mtod(nam, struct sockaddr_iso *);
33636389Ssklower 	}
33736389Ssklower 	IFDEBUG(D_ISO)
33836389Ssklower 		printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n",
33936389Ssklower 			isop, isop->isop_socket);
34036389Ssklower 	ENDDEBUG
34137469Ssklower 	/*
34237469Ssklower 	 * If we had to allocate space to a previous big foreign address,
34337469Ssklower 	 * and for some reason we didn't free it, we reuse it knowing
34437469Ssklower 	 * that is going to be big enough, as sockaddrs are delivered in
34537469Ssklower 	 * 128 byte mbufs.
34637469Ssklower 	 * If the foreign address is small enough, we use default space;
34737469Ssklower 	 * otherwise, we grab an mbuf to copy into.
34837469Ssklower 	 */
34937469Ssklower 	if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) {
35037469Ssklower 		if (siso->siso_len <= sizeof(isop->isop_sfaddr))
35137469Ssklower 			isop->isop_faddr = &isop->isop_sfaddr;
35237469Ssklower 		else {
35337469Ssklower 			struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
35437469Ssklower 			if (m == 0)
35537469Ssklower 				return ENOBUFS;
35637469Ssklower 			isop->isop_faddr = mtod(m, struct sockaddr_iso *);
35737469Ssklower 		}
35837469Ssklower 	}
35937469Ssklower 	bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len);
36036389Ssklower 	IFDEBUG(D_ISO)
36136389Ssklower 		printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n",
36236389Ssklower 			isop, isop->isop_socket);
36336389Ssklower 		printf("iso_pcbconnect connected to addr:\n");
36437469Ssklower 		dump_isoaddr(isop->isop_faddr);
36536389Ssklower 		printf("iso_pcbconnect end: src addr:\n");
36637469Ssklower 		dump_isoaddr(isop->isop_laddr);
36736389Ssklower 	ENDDEBUG
36836389Ssklower 	return 0;
36936389Ssklower }
37036389Ssklower 
37136389Ssklower /*
37236389Ssklower  * FUNCTION:		iso_pcbdisconnect()
37336389Ssklower  *
37436389Ssklower  * PURPOSE:			washes away the peer address info so the socket
37536389Ssklower  *					appears to be disconnected.
37636389Ssklower  *					If there's no file descriptor associated with the socket
37736389Ssklower  *					it detaches the pcb.
37836389Ssklower  *
37936389Ssklower  * RETURNS:			Nada.
38036389Ssklower  *
38136389Ssklower  * SIDE EFFECTS:	May detach the pcb.
38236389Ssklower  *
38336389Ssklower  * NOTES:
38436389Ssklower  */
38536389Ssklower void
38636389Ssklower iso_pcbdisconnect(isop)
38736389Ssklower 	struct isopcb *isop;
38836389Ssklower {
38936389Ssklower 	void iso_pcbdetach();
39039934Ssklower 	register struct sockaddr_iso *siso;
39136389Ssklower 
39236389Ssklower 	IFDEBUG(D_ISO)
39336389Ssklower 		printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
39436389Ssklower 	ENDDEBUG
39537469Ssklower 	/*
39637469Ssklower 	 * Preserver binding infnormation if already bound.
39737469Ssklower 	 */
39839934Ssklower 	if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) {
39939934Ssklower 		caddr_t otsel = TSEL(siso);
40039934Ssklower 		siso->siso_nlen = 0;
40139934Ssklower 		ovbcopy(otsel, TSEL(siso), siso->siso_tlen);
40239934Ssklower 	}
40337469Ssklower 	if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
40437469Ssklower 		m_freem(dtom(isop->isop_faddr));
40537469Ssklower 	isop->isop_faddr = 0;
40636389Ssklower 	if (isop->isop_socket->so_state & SS_NOFDREF)
40736389Ssklower 		iso_pcbdetach(isop);
40836389Ssklower }
40936389Ssklower 
41036389Ssklower /*
41136389Ssklower  * FUNCTION:		iso_pcbdetach
41236389Ssklower  *
41336389Ssklower  * PURPOSE:			detach the pcb at *(isop) from it's socket and free
41436389Ssklower  *					the mbufs associated with the pcb..
41536389Ssklower  *					Dequeues (isop) from its head.
41636389Ssklower  *
41736389Ssklower  * RETURNS:			Nada.
41836389Ssklower  *
41936389Ssklower  * SIDE EFFECTS:
42036389Ssklower  *
42136389Ssklower  * NOTES:
42236389Ssklower  */
42336389Ssklower void
42436389Ssklower iso_pcbdetach(isop)
42536389Ssklower 	struct isopcb *isop;
42636389Ssklower {
42736389Ssklower 	struct socket *so = isop->isop_socket;
42836389Ssklower 
42936389Ssklower 	IFDEBUG(D_ISO)
43036389Ssklower 		printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n",
43136389Ssklower 			isop, isop->isop_socket, so);
43236389Ssklower 	ENDDEBUG
43348737Ssklower #ifdef TPCONS
43448737Ssklower 	if (isop->isop_refcnt) {
43548737Ssklower 		register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
43648737Ssklower 		if (--isop->isop_refcnt > 0)
43748737Ssklower 			return;
43848737Ssklower 		if (lcp && lcp->lcd_state == DATA_TRANSFER)
43948737Ssklower 			pk_disconnect(lcp);
44048737Ssklower 		isop->isop_chan = 0;
44148737Ssklower 	}
44248737Ssklower #endif
44348737Ssklower 	if (so) { /* in the x.25 domain, we sometimes have no socket */
44436389Ssklower 		so->so_pcb = 0;
44536389Ssklower 		sofree(so);
44636389Ssklower 	}
44736389Ssklower 	IFDEBUG(D_ISO)
44836389Ssklower 		printf("iso_pcbdetach 2 \n");
44936389Ssklower 	ENDDEBUG
45036389Ssklower 	if (isop->isop_options)
45136389Ssklower 		(void)m_free(isop->isop_options);
45236389Ssklower 	IFDEBUG(D_ISO)
45336389Ssklower 		printf("iso_pcbdetach 3 \n");
45436389Ssklower 	ENDDEBUG
45536389Ssklower 	if (isop->isop_route.ro_rt)
45636389Ssklower 		rtfree(isop->isop_route.ro_rt);
45736389Ssklower 	IFDEBUG(D_ISO)
45836389Ssklower 		printf("iso_pcbdetach 3.1\n");
45936389Ssklower 	ENDDEBUG
46036389Ssklower 	if (isop->isop_clnpcache != NULL) {
46136389Ssklower 		struct clnp_cache *clcp =
46236389Ssklower 			mtod(isop->isop_clnpcache, struct clnp_cache *);
46336389Ssklower 		IFDEBUG(D_ISO)
46436389Ssklower 			printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n",
46536389Ssklower 				clcp, clcp->clc_hdr);
46636389Ssklower 		ENDDEBUG
46736389Ssklower 		if (clcp->clc_hdr != NULL)
46836389Ssklower 			m_free(clcp->clc_hdr);
46936389Ssklower 		IFDEBUG(D_ISO)
47036389Ssklower 			printf("iso_pcbdetach 3.3: freeing cache x%x\n",
47136389Ssklower 				isop->isop_clnpcache);
47236389Ssklower 		ENDDEBUG
47336389Ssklower 		m_free(isop->isop_clnpcache);
47436389Ssklower 	}
47536389Ssklower 	IFDEBUG(D_ISO)
47636389Ssklower 		printf("iso_pcbdetach 4 \n");
47736389Ssklower 	ENDDEBUG
47836389Ssklower 	remque(isop);
47936389Ssklower 	IFDEBUG(D_ISO)
48036389Ssklower 		printf("iso_pcbdetach 5 \n");
48136389Ssklower 	ENDDEBUG
48237469Ssklower 	if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
48337469Ssklower 		m_freem(dtom(isop->isop_laddr));
48440951Ssklower 	free((caddr_t)isop, M_PCB);
48536389Ssklower }
48636389Ssklower 
48736389Ssklower 
48836389Ssklower /*
48936389Ssklower  * FUNCTION:		iso_pcbnotify
49036389Ssklower  *
49136389Ssklower  * PURPOSE:			notify all connections in this protocol's queue (head)
49236389Ssklower  *					that have peer address (dst) of the problem (errno)
49336389Ssklower  *					by calling (notify) on the connections' isopcbs.
49436389Ssklower  *
49536389Ssklower  * RETURNS:			Rien.
49636389Ssklower  *
49736389Ssklower  * SIDE EFFECTS:
49836389Ssklower  *
49936389Ssklower  * NOTES:			(notify) is called at splimp!
50036389Ssklower  */
50136389Ssklower void
50239934Ssklower iso_pcbnotify(head, siso, errno, notify)
50336389Ssklower 	struct isopcb *head;
50439934Ssklower 	register struct sockaddr_iso *siso;
50536389Ssklower 	int errno, (*notify)();
50636389Ssklower {
50739934Ssklower 	register struct isopcb *isop;
50836389Ssklower 	int s = splimp();
50936389Ssklower 
51036389Ssklower 	IFDEBUG(D_ISO)
51136389Ssklower 		printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
51236389Ssklower 	ENDDEBUG
51339934Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
51439934Ssklower 		if (isop->isop_socket == 0 || isop->isop_faddr == 0 ||
51539934Ssklower 			!SAME_ISOADDR(siso, isop->isop_faddr)) {
51636389Ssklower 			IFDEBUG(D_ISO)
51736389Ssklower 				printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
51836389Ssklower 					isop, isop->isop_socket);
51939934Ssklower 				printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr);
52037469Ssklower 				dump_isoaddr(isop->isop_faddr);
52136389Ssklower 			ENDDEBUG
52236389Ssklower 			continue;
52336389Ssklower 		}
52436389Ssklower 		if (errno)
52536389Ssklower 			isop->isop_socket->so_error = errno;
52636389Ssklower 		if (notify)
52739934Ssklower 			(*notify)(isop);
52836389Ssklower 	}
52936389Ssklower 	splx(s);
53036389Ssklower 	IFDEBUG(D_ISO)
53136389Ssklower 		printf("END OF iso_pcbnotify\n" );
53236389Ssklower 	ENDDEBUG
53336389Ssklower }
53436389Ssklower 
53536389Ssklower 
53636389Ssklower /*
53736389Ssklower  * FUNCTION:		iso_pcblookup
53836389Ssklower  *
53936389Ssklower  * PURPOSE:			looks for a given combination of (faddr), (fport),
54036389Ssklower  *					(lport), (laddr) in the queue named by (head).
54136389Ssklower  *					Argument (flags) is ignored.
54236389Ssklower  *
54336389Ssklower  * RETURNS:			ptr to the isopcb if it finds a connection matching
54436389Ssklower  *					these arguments, o.w. returns zero.
54536389Ssklower  *
54636389Ssklower  * SIDE EFFECTS:
54736389Ssklower  *
54836389Ssklower  * NOTES:
54936389Ssklower  */
55036389Ssklower struct isopcb *
55137469Ssklower iso_pcblookup(head, fportlen, fport, laddr)
55236389Ssklower 	struct isopcb *head;
55337469Ssklower 	register struct sockaddr_iso *laddr;
55437469Ssklower 	caddr_t fport;
55537469Ssklower 	int fportlen;
55636389Ssklower {
55736389Ssklower 	register struct isopcb *isop;
55837469Ssklower 	register caddr_t lp = TSEL(laddr);
55938841Ssklower 	unsigned int llen = laddr->siso_tlen;
56036389Ssklower 
56136389Ssklower 	IFDEBUG(D_ISO)
56237469Ssklower 		printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n",
56337469Ssklower 			head, laddr, fport);
56436389Ssklower 	ENDDEBUG
56536389Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
56637469Ssklower 		if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
56736389Ssklower 			continue;
56838841Ssklower 		if (isop->isop_laddr->siso_tlen != llen)
56936389Ssklower 			continue;
57037469Ssklower 		if (bcmp(lp, TSEL(isop->isop_laddr), llen))
57137469Ssklower 			continue;
57237469Ssklower 		if (fportlen && isop->isop_faddr &&
57337469Ssklower 			bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen))
57437469Ssklower 			continue;
57536389Ssklower 		/*	PHASE2
57636389Ssklower 		 *	addrmatch1 should be iso_addrmatch(a, b, mask)
57736389Ssklower 		 *	where mask is taken from isop->isop_laddrmask (new field)
57836389Ssklower 		 *	isop_lnetmask will also be available in isop
57936389Ssklower 		if (laddr != &zeroiso_addr &&
58036389Ssklower 			!iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr)))
58136389Ssklower 			continue;
58237469Ssklower 		*/
58337469Ssklower 		if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr)))
58437469Ssklower 			continue;
58536389Ssklower 		return (isop);
58636389Ssklower 	}
58736389Ssklower 	return (struct isopcb *)0;
58836389Ssklower }
58936389Ssklower #endif ISO
590