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