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