xref: /csrg-svn/sys/netiso/iso_pcb.c (revision 36389)
1*36389Ssklower /***********************************************************
2*36389Ssklower 		Copyright IBM Corporation 1987
3*36389Ssklower 
4*36389Ssklower                       All Rights Reserved
5*36389Ssklower 
6*36389Ssklower Permission to use, copy, modify, and distribute this software and its
7*36389Ssklower documentation for any purpose and without fee is hereby granted,
8*36389Ssklower provided that the above copyright notice appear in all copies and that
9*36389Ssklower both that copyright notice and this permission notice appear in
10*36389Ssklower supporting documentation, and that the name of IBM not be
11*36389Ssklower used in advertising or publicity pertaining to distribution of the
12*36389Ssklower software without specific, written prior permission.
13*36389Ssklower 
14*36389Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15*36389Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16*36389Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17*36389Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18*36389Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19*36389Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*36389Ssklower SOFTWARE.
21*36389Ssklower 
22*36389Ssklower ******************************************************************/
23*36389Ssklower 
24*36389Ssklower /*
25*36389Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26*36389Ssklower  */
27*36389Ssklower /*
28*36389Ssklower  * $Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $
29*36389Ssklower  * $Source: /usr/argo/sys/netiso/RCS/iso_pcb.c,v $
30*36389Ssklower  *
31*36389Ssklower  * Iso address family net-layer(s) pcb stuff. NEH 1/29/87
32*36389Ssklower  */
33*36389Ssklower #ifndef lint
34*36389Ssklower static char *rcsid = "$Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $";
35*36389Ssklower #endif
36*36389Ssklower 
37*36389Ssklower #ifdef ISO
38*36389Ssklower 
39*36389Ssklower #include "param.h"
40*36389Ssklower #include "systm.h"
41*36389Ssklower #include "dir.h"
42*36389Ssklower #include "user.h"
43*36389Ssklower #include "mbuf.h"
44*36389Ssklower #include "../h/socket.h"
45*36389Ssklower #include "../h/socketvar.h"
46*36389Ssklower #include "../netiso/argo_debug.h"
47*36389Ssklower #include "../netiso/iso.h"
48*36389Ssklower #include "../netiso/clnp.h"
49*36389Ssklower #include "../netinet/in_systm.h"
50*36389Ssklower #include "../net/if.h"
51*36389Ssklower #include "../net/route.h"
52*36389Ssklower #include "../netiso/iso_pcb.h"
53*36389Ssklower #include "../netiso/iso_var.h"
54*36389Ssklower #include "protosw.h"
55*36389Ssklower 
56*36389Ssklower #define PCBNULL (struct isopcb *)0
57*36389Ssklower struct	iso_addr zeroiso_addr = {
58*36389Ssklower 	0
59*36389Ssklower };
60*36389Ssklower 
61*36389Ssklower 
62*36389Ssklower /*
63*36389Ssklower  * FUNCTION:		iso_pcballoc
64*36389Ssklower  *
65*36389Ssklower  * PURPOSE:			creates an isopcb structure in an mbuf,
66*36389Ssklower  *					with socket (so), and
67*36389Ssklower  *					puts it in the queue with head (head)
68*36389Ssklower  *
69*36389Ssklower  * RETURNS:			0 if OK, ENOBUFS if can't alloc the necessary mbuf
70*36389Ssklower  */
71*36389Ssklower int
72*36389Ssklower iso_pcballoc(so, head)
73*36389Ssklower 	struct socket *so;
74*36389Ssklower 	struct isopcb *head;
75*36389Ssklower {
76*36389Ssklower 	struct mbuf *m;
77*36389Ssklower 	register struct isopcb *isop;
78*36389Ssklower 
79*36389Ssklower 	IFDEBUG(D_ISO)
80*36389Ssklower 		printf("iso_pcballoc(so 0x%x)\n", so);
81*36389Ssklower 	ENDDEBUG
82*36389Ssklower 	m = m_getclr(M_DONTWAIT, MT_PCB);
83*36389Ssklower 	if (m == NULL)
84*36389Ssklower 		return ENOBUFS;
85*36389Ssklower 	isop = mtod(m, struct isopcb *);
86*36389Ssklower 	isop->isop_head = head;
87*36389Ssklower 	isop->isop_socket = so;
88*36389Ssklower 	insque(isop, head);
89*36389Ssklower 	so->so_pcb = (caddr_t)isop;
90*36389Ssklower 	return 0;
91*36389Ssklower }
92*36389Ssklower 
93*36389Ssklower /*
94*36389Ssklower  * FUNCTION:		iso_pcbbind
95*36389Ssklower  *
96*36389Ssklower  * PURPOSE:			binds the address given in *(nam) to the socket
97*36389Ssklower  *					specified by the isopcb in *(isop)
98*36389Ssklower  *					If the given address is zero, it makes sure the
99*36389Ssklower  *					address isn't already in use and if it's got a network
100*36389Ssklower  *					portion, we look for an interface with that network
101*36389Ssklower  *					address.  If the address given is zero, we allocate
102*36389Ssklower  *					a port and stuff it in the (nam) structure.
103*36389Ssklower  *
104*36389Ssklower  * RETURNS:			errno E* or 0 if ok.
105*36389Ssklower  *
106*36389Ssklower  * SIDE EFFECTS:	increments head->isop_lport if it allocates a port #
107*36389Ssklower  *
108*36389Ssklower  * NOTES:
109*36389Ssklower  */
110*36389Ssklower int
111*36389Ssklower iso_pcbbind(isop, nam)
112*36389Ssklower 	register struct isopcb *isop;
113*36389Ssklower 	struct mbuf *nam;
114*36389Ssklower {
115*36389Ssklower 	register struct isopcb *head = isop->isop_head;
116*36389Ssklower 	register struct sockaddr_iso *siso;
117*36389Ssklower 	struct ifaddr *ia;
118*36389Ssklower 	u_short suf = 0;
119*36389Ssklower 
120*36389Ssklower 	IFDEBUG(D_ISO)
121*36389Ssklower 		printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam);
122*36389Ssklower 	ENDDEBUG
123*36389Ssklower 	if (iso_ifaddr == 0) /* any interfaces attached? */
124*36389Ssklower 		return EADDRNOTAVAIL;
125*36389Ssklower 	if (isop->isop_lport)  /* already bound */
126*36389Ssklower 		return EADDRINUSE;
127*36389Ssklower 	if(nam == (struct mbuf *)0)
128*36389Ssklower 		goto noname;
129*36389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
130*36389Ssklower 	IFDEBUG(D_ISO)
131*36389Ssklower 		printf("iso_pcbbind(name len 0x%x)\n", nam->m_len);
132*36389Ssklower 		printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr));
133*36389Ssklower 	ENDDEBUG
134*36389Ssklower 	/*
135*36389Ssklower 	 * We would like sort of length check but since some OSI addrs
136*36389Ssklower 	 * do not have fixed length, we can't really do much.
137*36389Ssklower 	 * The ONLY thing we can say is that an osi addr has to have
138*36389Ssklower 	 * at LEAST an afi and one more byte and had better fit into
139*36389Ssklower 	 * a struct iso_addr.
140*36389Ssklower 	 * However, in fact the size of the whole thing is a struct
141*36389Ssklower 	 * sockaddr_iso, so probably this is what we should check for.
142*36389Ssklower 	 */
143*36389Ssklower 	if( (nam->m_len < 2) || (nam->m_len > sizeof(struct sockaddr_iso))) {
144*36389Ssklower 			return ENAMETOOLONG;
145*36389Ssklower 	}
146*36389Ssklower 	suf = siso->siso_tsuffix;
147*36389Ssklower 
148*36389Ssklower 	if (bcmp(&siso->siso_addr,&zeroiso_addr, 1)) {
149*36389Ssklower 		/* non-zero net addr- better match one of our interfaces */
150*36389Ssklower 		IFDEBUG(D_ISO)
151*36389Ssklower 			printf("iso_pcbbind: bind to NOT zeroisoaddr\n");
152*36389Ssklower 		ENDDEBUG
153*36389Ssklower 		siso->siso_tsuffix = 0;		/* yech... */
154*36389Ssklower 		/* PHASE 2: this call is ok */
155*36389Ssklower 		if ((ia = ifa_ifwithaddr((struct sockaddr *)siso))
156*36389Ssklower 											== (struct ifaddr *)0)
157*36389Ssklower 			return EADDRNOTAVAIL;
158*36389Ssklower 		/* copy to the inpcb */
159*36389Ssklower 		bcopy( (caddr_t)&((struct sockaddr_iso *)&(ia->ifa_addr))->siso_addr,
160*36389Ssklower 			(caddr_t)&(isop->isop_laddr.siso_addr),
161*36389Ssklower 			sizeof(struct sockaddr_iso) );
162*36389Ssklower 		isop->isop_laddr.siso_tsuffix = suf;
163*36389Ssklower 		/* copy also to the nam parameter */
164*36389Ssklower 		bcopy( (caddr_t)&(isop->isop_laddr.siso_addr),
165*36389Ssklower 			(caddr_t)&(siso->siso_addr), sizeof(struct sockaddr_iso));
166*36389Ssklower 		siso->siso_tsuffix = suf;
167*36389Ssklower 	}
168*36389Ssklower 	if (suf) {
169*36389Ssklower 		if((suf < ISO_PORT_RESERVED) && (u.u_uid != 0))
170*36389Ssklower 			return EACCES;
171*36389Ssklower 		if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
172*36389Ssklower 			iso_pcblookup(head, 0, &(isop->isop_laddr.siso_addr), suf, 0) )
173*36389Ssklower 			return EADDRINUSE;
174*36389Ssklower 	}
175*36389Ssklower 	/* copy the if addr to the result (siso) and to the isopcb */
176*36389Ssklower noname:
177*36389Ssklower 	IFDEBUG(D_ISO)
178*36389Ssklower 		printf("iso_pcbbind noname\n");
179*36389Ssklower 	ENDDEBUG
180*36389Ssklower 	if (suf == 0)
181*36389Ssklower 		do {
182*36389Ssklower 			if (head->isop_lport++ < ISO_PORT_RESERVED ||
183*36389Ssklower 			    head->isop_lport > ISO_PORT_USERRESERVED)
184*36389Ssklower 				head->isop_lport = ISO_PORT_RESERVED;
185*36389Ssklower 			suf = head->isop_lport;
186*36389Ssklower 		} while (iso_pcblookup(head, 0, &(isop->isop_laddr.siso_addr), suf, 0));
187*36389Ssklower 	isop->isop_lport = suf;
188*36389Ssklower 	IFDEBUG(D_ISO)
189*36389Ssklower 		printf("iso_pcbbind returns 0, suf 0x%x\n", suf);
190*36389Ssklower 	ENDDEBUG
191*36389Ssklower 	return 0;
192*36389Ssklower }
193*36389Ssklower 
194*36389Ssklower /*
195*36389Ssklower  * FUNCTION:		iso_pcbconnect
196*36389Ssklower  *
197*36389Ssklower  * PURPOSE:			Make the isopcb (isop) look like it's connected.
198*36389Ssklower  *					In other words, give it the peer address given in
199*36389Ssklower  *					the mbuf * (nam).   Make sure such a combination
200*36389Ssklower  *					of local, peer addresses doesn't already exist
201*36389Ssklower  *					for this protocol.  Internet mentality prevails here,
202*36389Ssklower  *					wherein a src,dst pair uniquely identifies a connection.
203*36389Ssklower  * 					Both net address and port must be specified in argument
204*36389Ssklower  *					(nam).
205*36389Ssklower  * 					If we don't have a local address for this socket yet,
206*36389Ssklower  *					we pick one by calling iso_pcbbind().
207*36389Ssklower  *
208*36389Ssklower  * RETURNS:			errno E* or 0 if ok.
209*36389Ssklower  *
210*36389Ssklower  * SIDE EFFECTS:	Looks up a route, which may cause one to be left
211*36389Ssklower  *					in the isopcb.
212*36389Ssklower  *
213*36389Ssklower  * NOTES:
214*36389Ssklower  */
215*36389Ssklower #define	satosiso(sa)	((struct sockaddr_iso *)(sa))
216*36389Ssklower 
217*36389Ssklower int
218*36389Ssklower iso_pcbconnect(isop, nam)
219*36389Ssklower 	struct isopcb *isop;
220*36389Ssklower 	struct mbuf *nam;
221*36389Ssklower {
222*36389Ssklower 	struct	ifnet 					*ifp = (struct ifnet *)0;
223*36389Ssklower 	struct sockaddr_iso				ifaddr;
224*36389Ssklower 	register struct sockaddr_iso	*siso = mtod(nam, struct sockaddr_iso *);
225*36389Ssklower 	int								local_zero = 0;
226*36389Ssklower 
227*36389Ssklower 	IFDEBUG(D_ISO)
228*36389Ssklower 		printf(
229*36389Ssklower 	"iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x nam->m_len 0x%x), addr:\n",
230*36389Ssklower 			isop, isop->isop_socket, nam, nam->m_len);
231*36389Ssklower 		dump_isoaddr(siso);
232*36389Ssklower 	ENDDEBUG
233*36389Ssklower 	if (nam->m_len > sizeof (*siso))
234*36389Ssklower 		return ENAMETOOLONG; /* not great but better than EINVAL! */
235*36389Ssklower 	if (siso->siso_family != AF_ISO)
236*36389Ssklower 		return EAFNOSUPPORT;
237*36389Ssklower #ifdef notdef
238*36389Ssklower 	/* removed for the sake of extended tsels -
239*36389Ssklower 	 * user may setsockopt for extended tsel (foreign) and then
240*36389Ssklower 	 * connect to nsap w/ tsuffix zero
241*36389Ssklower 	 */
242*36389Ssklower 	if (siso->siso_tsuffix == 0)
243*36389Ssklower 		return EADDRNOTAVAIL;
244*36389Ssklower 	local_zero = iso_addrmatch1(&(isop->isop_laddr.siso_addr), &zeroiso_addr);
245*36389Ssklower #endif notdef
246*36389Ssklower 	local_zero = !bcmp(&(isop->isop_laddr.siso_addr), &zeroiso_addr, 1);
247*36389Ssklower 
248*36389Ssklower #ifdef	PHASEONE
249*36389Ssklower 	if (local_zero) {
250*36389Ssklower 		/*
251*36389Ssklower 		 *	We need to get the local nsap address.
252*36389Ssklower 		 *	First, route to the destination. This will provide us with
253*36389Ssklower 		 *	an ifp. Second, determine which local address linked on
254*36389Ssklower 		 *	that ifp is appropriate
255*36389Ssklower 		 */
256*36389Ssklower 		struct sockaddr_iso	*first_hop;		/* filled by clnp_route */
257*36389Ssklower 		struct ifnet	*ifp;			/* filled by clnp_route */
258*36389Ssklower 		int				err;
259*36389Ssklower 		struct iso_addr	*localaddr;
260*36389Ssklower 
261*36389Ssklower 		if (err = clnp_route(&siso->siso_addr, &isop->isop_route, /* flags */0,
262*36389Ssklower 			&first_hop, &ifp))
263*36389Ssklower 			return(err);
264*36389Ssklower 
265*36389Ssklower 		/* determine local address based upon ifp */
266*36389Ssklower 		if ((localaddr = clnp_srcaddr(ifp, &first_hop->siso_addr)) == NULL)
267*36389Ssklower 			return(ENETUNREACH);
268*36389Ssklower 
269*36389Ssklower 		ifaddr.siso_family = AF_ISO;
270*36389Ssklower 		ifaddr.siso_addr = *localaddr;
271*36389Ssklower 
272*36389Ssklower 		if (isop->isop_lport == 0)
273*36389Ssklower 			(void)iso_pcbbind(isop, (struct mbuf *)0);
274*36389Ssklower 		isop->isop_laddr = ifaddr;
275*36389Ssklower 	}
276*36389Ssklower #else
277*36389Ssklower 	if (local_zero) {
278*36389Ssklower 		struct iso_ifaddr 		*ia;
279*36389Ssklower 		register struct route *ro;
280*36389Ssklower 
281*36389Ssklower 		IFDEBUG(D_ISO)
282*36389Ssklower 			printf("iso_pcbconnect localzero 1\n");
283*36389Ssklower 		ENDDEBUG
284*36389Ssklower 		ia = (struct iso_ifaddr *)0;
285*36389Ssklower 		/*
286*36389Ssklower 		 * If route is known or can be allocated now,
287*36389Ssklower 		 * our src addr is taken from the i/f, else punt.
288*36389Ssklower 		 */
289*36389Ssklower 		ro = &isop->isop_route;
290*36389Ssklower 		IFDEBUG(D_ISO)
291*36389Ssklower 			printf("iso_pcbconnect rtalloc 1.1, ro->ro_rt 0x%x\n",
292*36389Ssklower 				ro->ro_rt);
293*36389Ssklower 		ENDDEBUG
294*36389Ssklower 		if (ro->ro_rt && ! iso_addrmatch1( &(satosiso(&ro->ro_dst)->siso_addr),
295*36389Ssklower 					&siso->siso_addr)) {
296*36389Ssklower 			RTFREE(ro->ro_rt);
297*36389Ssklower 			ro->ro_rt = (struct rtentry *)0;
298*36389Ssklower 		}
299*36389Ssklower 		/*
300*36389Ssklower 		 *	TODO: it seems this code has a lot in common with clnp_route.
301*36389Ssklower 		 *	Maybe they could be combined? (RAH)
302*36389Ssklower 		 */
303*36389Ssklower 		if ((isop->isop_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
304*36389Ssklower 		    (ro->ro_rt == (struct rtentry *)0 ||
305*36389Ssklower 		    (ifp = ro->ro_rt->rt_ifp) == (struct ifnet *)0)) {
306*36389Ssklower 				/* No route yet, so try to acquire one */
307*36389Ssklower 				ro->ro_dst.sa_family = AF_ISO;
308*36389Ssklower 				((struct sockaddr_iso *) &ro->ro_dst)->siso_addr =
309*36389Ssklower 					siso->siso_addr;
310*36389Ssklower 				rtalloc(ro);
311*36389Ssklower 				IFDEBUG(D_ISO)
312*36389Ssklower 					printf("iso_pcbconnect rtalloc 1.5, ro->ro_rt 0x%x\n",
313*36389Ssklower 						ro->ro_rt);
314*36389Ssklower 					if (ro->ro_rt != NULL) {
315*36389Ssklower 						printf("ro->ro_rt->rt_refcnt %d\n",
316*36389Ssklower 							ro->ro_rt->rt_refcnt);
317*36389Ssklower 						printf("rt entry rt_gateway (as sockaddr):\n");
318*36389Ssklower 						dump_buf(&ro->ro_rt->rt_gateway,
319*36389Ssklower 							sizeof (struct sockaddr));
320*36389Ssklower 					}
321*36389Ssklower 				ENDDEBUG
322*36389Ssklower 				/*
323*36389Ssklower 				 * If we found a route, use the address
324*36389Ssklower 				 * corresponding to the outgoing interface
325*36389Ssklower 				 * unless it is the loopback (in case a route
326*36389Ssklower 				 * to our address on another net goes to loopback).
327*36389Ssklower 				 *
328*36389Ssklower 				 *	We must check to use the address that is of the
329*36389Ssklower 				 *	same type (in the case where the interface has more
330*36389Ssklower 				 *	than one type associated with it). (ie ecn0 has
331*36389Ssklower 				 *	both t37 and osinet addresses.
332*36389Ssklower 				 */
333*36389Ssklower 				if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp) &&
334*36389Ssklower 					(ifp->if_flags & IFF_LOOPBACK) == 0)
335*36389Ssklower 					for (ia = iso_ifaddr; ia; ia = ia->ia_next) {
336*36389Ssklower 						struct iso_addr *isoap = &IA_SIS(ia)->siso_addr;
337*36389Ssklower 
338*36389Ssklower 						IFDEBUG(D_ISO)
339*36389Ssklower 							printf("iso_pcbconnect: ia x%x yields: %s\n",
340*36389Ssklower 								ia, clnp_iso_addrp(isoap));
341*36389Ssklower 						ENDDEBUG
342*36389Ssklower 
343*36389Ssklower 						if ((ia->ia_ifp == ifp) &&
344*36389Ssklower 							(iso_eqtype(&siso->siso_addr, isoap)))
345*36389Ssklower 							break;
346*36389Ssklower 					}
347*36389Ssklower 		}
348*36389Ssklower 		IFDEBUG(D_ISO)
349*36389Ssklower 			printf("iso_pcbconnect localzero 2: ia x%x\n", ia);
350*36389Ssklower 		ENDDEBUG
351*36389Ssklower 		if (ia == 0) {
352*36389Ssklower 			ia = (struct iso_ifaddr *)
353*36389Ssklower 			    ifa_ifwithdstaddr((struct sockaddr *)siso);
354*36389Ssklower 			if (ia == 0)
355*36389Ssklower 				ia = iso_iaonnetof(siso);
356*36389Ssklower 			if (ia == 0)
357*36389Ssklower 				return EADDRNOTAVAIL;
358*36389Ssklower 		}
359*36389Ssklower 		ifaddr = *(struct sockaddr_iso *)&ia->ia_addr;
360*36389Ssklower 	}
361*36389Ssklower 	IFDEBUG(D_ISO)
362*36389Ssklower 		printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n",
363*36389Ssklower 			isop, isop->isop_socket);
364*36389Ssklower 	ENDDEBUG
365*36389Ssklower 	if (local_zero) {
366*36389Ssklower 		if (isop->isop_lport == 0)
367*36389Ssklower 			(void)iso_pcbbind(isop, (struct mbuf *)0);
368*36389Ssklower 		isop->isop_laddr.siso_addr = ifaddr.siso_addr;
369*36389Ssklower 		isop->isop_laddr.siso_family = AF_ISO;
370*36389Ssklower 	}
371*36389Ssklower #endif	PHASEONE
372*36389Ssklower 	IFDEBUG(D_ISO)
373*36389Ssklower 		printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n",
374*36389Ssklower 			isop, isop->isop_socket);
375*36389Ssklower 	ENDDEBUG
376*36389Ssklower 	bcopy((caddr_t) &(siso->siso_addr), (caddr_t) &(isop->isop_faddr.siso_addr),
377*36389Ssklower 		sizeof(struct iso_addr));
378*36389Ssklower 	IFDEBUG(D_ISO)
379*36389Ssklower 		printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n",
380*36389Ssklower 			isop, isop->isop_socket);
381*36389Ssklower 	ENDDEBUG
382*36389Ssklower 	isop->isop_faddr.siso_family = AF_ISO;
383*36389Ssklower 	isop->isop_fport = siso->siso_tsuffix;
384*36389Ssklower 	IFDEBUG(D_ISO)
385*36389Ssklower 		printf("in iso_pcbconnect end isop 0x%x isop->sock 0x%x\n",
386*36389Ssklower 			isop, isop->isop_socket);
387*36389Ssklower 		printf("iso_pcbconnect connected to addr:\n");
388*36389Ssklower 		dump_isoaddr(&isop->isop_faddr);
389*36389Ssklower 		printf("iso_pcbconnect end: src addr:\n");
390*36389Ssklower 		dump_isoaddr(&isop->isop_laddr);
391*36389Ssklower 	ENDDEBUG
392*36389Ssklower 	return 0;
393*36389Ssklower }
394*36389Ssklower 
395*36389Ssklower /*
396*36389Ssklower  * FUNCTION:		iso_pcbdisconnect()
397*36389Ssklower  *
398*36389Ssklower  * PURPOSE:			washes away the peer address info so the socket
399*36389Ssklower  *					appears to be disconnected.
400*36389Ssklower  *					If there's no file descriptor associated with the socket
401*36389Ssklower  *					it detaches the pcb.
402*36389Ssklower  *
403*36389Ssklower  * RETURNS:			Nada.
404*36389Ssklower  *
405*36389Ssklower  * SIDE EFFECTS:	May detach the pcb.
406*36389Ssklower  *
407*36389Ssklower  * NOTES:
408*36389Ssklower  */
409*36389Ssklower void
410*36389Ssklower iso_pcbdisconnect(isop)
411*36389Ssklower 	struct isopcb *isop;
412*36389Ssklower {
413*36389Ssklower 	void iso_pcbdetach();
414*36389Ssklower 
415*36389Ssklower 	IFDEBUG(D_ISO)
416*36389Ssklower 		printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
417*36389Ssklower 	ENDDEBUG
418*36389Ssklower 	isop->isop_laddr.siso_addr = zeroiso_addr;
419*36389Ssklower 	isop->isop_fport = 0;
420*36389Ssklower 	if (isop->isop_socket->so_state & SS_NOFDREF)
421*36389Ssklower 		iso_pcbdetach(isop);
422*36389Ssklower }
423*36389Ssklower 
424*36389Ssklower /*
425*36389Ssklower  * FUNCTION:		iso_pcbdetach
426*36389Ssklower  *
427*36389Ssklower  * PURPOSE:			detach the pcb at *(isop) from it's socket and free
428*36389Ssklower  *					the mbufs associated with the pcb..
429*36389Ssklower  *					Dequeues (isop) from its head.
430*36389Ssklower  *
431*36389Ssklower  * RETURNS:			Nada.
432*36389Ssklower  *
433*36389Ssklower  * SIDE EFFECTS:
434*36389Ssklower  *
435*36389Ssklower  * NOTES:
436*36389Ssklower  */
437*36389Ssklower void
438*36389Ssklower iso_pcbdetach(isop)
439*36389Ssklower 	struct isopcb *isop;
440*36389Ssklower {
441*36389Ssklower 	struct socket *so = isop->isop_socket;
442*36389Ssklower 
443*36389Ssklower 	IFDEBUG(D_ISO)
444*36389Ssklower 		printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n",
445*36389Ssklower 			isop, isop->isop_socket, so);
446*36389Ssklower 	ENDDEBUG
447*36389Ssklower 	if (so ) { /* in the x.25 domain, we sometimes have no socket */
448*36389Ssklower 		so->so_pcb = 0;
449*36389Ssklower 		sofree(so);
450*36389Ssklower 	}
451*36389Ssklower 	IFDEBUG(D_ISO)
452*36389Ssklower 		printf("iso_pcbdetach 2 \n");
453*36389Ssklower 	ENDDEBUG
454*36389Ssklower 	if (isop->isop_options)
455*36389Ssklower 		(void)m_free(isop->isop_options);
456*36389Ssklower 	IFDEBUG(D_ISO)
457*36389Ssklower 		printf("iso_pcbdetach 3 \n");
458*36389Ssklower 	ENDDEBUG
459*36389Ssklower 	if (isop->isop_route.ro_rt)
460*36389Ssklower 		rtfree(isop->isop_route.ro_rt);
461*36389Ssklower 	IFDEBUG(D_ISO)
462*36389Ssklower 		printf("iso_pcbdetach 3.1\n");
463*36389Ssklower 	ENDDEBUG
464*36389Ssklower 	if (isop->isop_clnpcache != NULL) {
465*36389Ssklower 		struct clnp_cache *clcp =
466*36389Ssklower 			mtod(isop->isop_clnpcache, struct clnp_cache *);
467*36389Ssklower 		IFDEBUG(D_ISO)
468*36389Ssklower 			printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n",
469*36389Ssklower 				clcp, clcp->clc_hdr);
470*36389Ssklower 		ENDDEBUG
471*36389Ssklower 		if (clcp->clc_hdr != NULL)
472*36389Ssklower 			m_free(clcp->clc_hdr);
473*36389Ssklower 		IFDEBUG(D_ISO)
474*36389Ssklower 			printf("iso_pcbdetach 3.3: freeing cache x%x\n",
475*36389Ssklower 				isop->isop_clnpcache);
476*36389Ssklower 		ENDDEBUG
477*36389Ssklower 		m_free(isop->isop_clnpcache);
478*36389Ssklower 	}
479*36389Ssklower 	IFDEBUG(D_ISO)
480*36389Ssklower 		printf("iso_pcbdetach 4 \n");
481*36389Ssklower 	ENDDEBUG
482*36389Ssklower 	remque(isop);
483*36389Ssklower 	IFDEBUG(D_ISO)
484*36389Ssklower 		printf("iso_pcbdetach 5 \n");
485*36389Ssklower 	ENDDEBUG
486*36389Ssklower 	(void) m_free(dtom(isop));
487*36389Ssklower }
488*36389Ssklower 
489*36389Ssklower #ifdef notdef
490*36389Ssklower /* NEEDED? */
491*36389Ssklower void
492*36389Ssklower iso_setsockaddr(isop, nam)
493*36389Ssklower 	register struct isopcb *isop;
494*36389Ssklower 	struct mbuf *nam;
495*36389Ssklower {
496*36389Ssklower 	register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
497*36389Ssklower 
498*36389Ssklower 	nam->m_len = sizeof (*siso);
499*36389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
500*36389Ssklower 	bzero((caddr_t)siso, sizeof (*siso));
501*36389Ssklower 	siso->siso_family = AF_ISO;
502*36389Ssklower 	siso->siso_tsuffix = isop->isop_lport;
503*36389Ssklower 	siso->siso_addr = isop->isop_laddr.siso_addr;
504*36389Ssklower }
505*36389Ssklower 
506*36389Ssklower /* NEEDED? */
507*36389Ssklower void
508*36389Ssklower iso_setpeeraddr(isop, nam)
509*36389Ssklower 	register struct isopcb *isop;
510*36389Ssklower 	struct mbuf *nam;
511*36389Ssklower {
512*36389Ssklower 	register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
513*36389Ssklower 
514*36389Ssklower 	nam->m_len = sizeof (*siso);
515*36389Ssklower 	siso = mtod(nam, struct sockaddr_iso *);
516*36389Ssklower 	bzero((caddr_t)siso, sizeof (*siso));
517*36389Ssklower 	siso->siso_family = AF_ISO;
518*36389Ssklower 	siso->siso_tsuffix = isop->isop_fport;
519*36389Ssklower 	siso->siso_addr = isop->isop_faddr.siso_addr;
520*36389Ssklower }
521*36389Ssklower #endif notdef
522*36389Ssklower 
523*36389Ssklower /*
524*36389Ssklower  * FUNCTION:		iso_pcbnotify
525*36389Ssklower  *
526*36389Ssklower  * PURPOSE:			notify all connections in this protocol's queue (head)
527*36389Ssklower  *					that have peer address (dst) of the problem (errno)
528*36389Ssklower  *					by calling (notify) on the connections' isopcbs.
529*36389Ssklower  *
530*36389Ssklower  * RETURNS:			Rien.
531*36389Ssklower  *
532*36389Ssklower  * SIDE EFFECTS:
533*36389Ssklower  *
534*36389Ssklower  * NOTES:			(notify) is called at splimp!
535*36389Ssklower  */
536*36389Ssklower void
537*36389Ssklower iso_pcbnotify(head, dst, errno, notify)
538*36389Ssklower 	struct isopcb *head;
539*36389Ssklower 	register struct iso_addr *dst;
540*36389Ssklower 	int errno, (*notify)();
541*36389Ssklower {
542*36389Ssklower 	register struct isopcb *isop, *oisop;
543*36389Ssklower 	int s = splimp();
544*36389Ssklower 
545*36389Ssklower 	IFDEBUG(D_ISO)
546*36389Ssklower 		printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
547*36389Ssklower 	ENDDEBUG
548*36389Ssklower 	for (isop = head->isop_next; isop != head;) {
549*36389Ssklower 		if (!iso_addrmatch1(&(isop->isop_faddr.siso_addr), dst) ||
550*36389Ssklower 		    isop->isop_socket == 0) {
551*36389Ssklower 			IFDEBUG(D_ISO)
552*36389Ssklower 				printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
553*36389Ssklower 					isop, isop->isop_socket);
554*36389Ssklower 				printf("addrmatch cmp'd with (0x%x):\n",
555*36389Ssklower 					&(isop->isop_faddr.siso_addr));
556*36389Ssklower 				dump_isoaddr(&isop->isop_faddr);
557*36389Ssklower 			ENDDEBUG
558*36389Ssklower 			isop = isop->isop_next;
559*36389Ssklower 			continue;
560*36389Ssklower 		}
561*36389Ssklower 		if (errno)
562*36389Ssklower 			isop->isop_socket->so_error = errno;
563*36389Ssklower 		oisop = isop;
564*36389Ssklower 		isop = isop->isop_next;
565*36389Ssklower 		if (notify)
566*36389Ssklower 			(*notify)(oisop);
567*36389Ssklower 	}
568*36389Ssklower 	splx(s);
569*36389Ssklower 	IFDEBUG(D_ISO)
570*36389Ssklower 		printf("END OF iso_pcbnotify\n" );
571*36389Ssklower 	ENDDEBUG
572*36389Ssklower }
573*36389Ssklower 
574*36389Ssklower 
575*36389Ssklower /*
576*36389Ssklower  * FUNCTION:		iso_pcblookup
577*36389Ssklower  *
578*36389Ssklower  * PURPOSE:			looks for a given combination of (faddr), (fport),
579*36389Ssklower  *					(lport), (laddr) in the queue named by (head).
580*36389Ssklower  *					Argument (flags) is ignored.
581*36389Ssklower  *
582*36389Ssklower  * RETURNS:			ptr to the isopcb if it finds a connection matching
583*36389Ssklower  *					these arguments, o.w. returns zero.
584*36389Ssklower  *
585*36389Ssklower  * SIDE EFFECTS:
586*36389Ssklower  *
587*36389Ssklower  * NOTES:
588*36389Ssklower  */
589*36389Ssklower struct isopcb *
590*36389Ssklower iso_pcblookup(head, fport, laddr, lport, flags)
591*36389Ssklower 	struct isopcb *head;
592*36389Ssklower 	struct iso_addr *laddr;
593*36389Ssklower 	u_short fport, lport;
594*36389Ssklower 	int flags;
595*36389Ssklower {
596*36389Ssklower 	register struct isopcb *isop;
597*36389Ssklower 
598*36389Ssklower 	IFDEBUG(D_ISO)
599*36389Ssklower 		printf("iso_pcblookup(head 0x%x lport 0x%x fport 0x%x)\n",
600*36389Ssklower 			head, lport, fport);
601*36389Ssklower 	ENDDEBUG
602*36389Ssklower 	for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
603*36389Ssklower #ifdef notdef
604*36389Ssklower 	/*
605*36389Ssklower 	 * This should be changed to do bcmp on lsuffix in the tpcb instead
606*36389Ssklower 	 * since we should be ignoring the lport concept.
607*36389Ssklower 	 */
608*36389Ssklower #endif notdef
609*36389Ssklower 		if (isop->isop_lport != lport)
610*36389Ssklower 			continue;
611*36389Ssklower 		if (isop->isop_fport != fport)
612*36389Ssklower 			continue;
613*36389Ssklower 		/*	PHASE2
614*36389Ssklower 		 *	addrmatch1 should be iso_addrmatch(a, b, mask)
615*36389Ssklower 		 *	where mask is taken from isop->isop_laddrmask (new field)
616*36389Ssklower 		 *	isop_lnetmask will also be available in isop
617*36389Ssklower 		 */
618*36389Ssklower 		if (laddr != &zeroiso_addr &&
619*36389Ssklower 			!iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr)))
620*36389Ssklower 			continue;
621*36389Ssklower 		return (isop);
622*36389Ssklower 	}
623*36389Ssklower 	return (struct isopcb *)0;
624*36389Ssklower }
625*36389Ssklower #endif ISO
626