FreeBSD/Linux Kernel Cross Reference
sys/netiso/iso_pcb.c
1 /* $NetBSD: iso_pcb.c,v 1.25 2003/10/30 01:43:10 simonb 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.25 2003/10/30 01:43:10 simonb 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
79 #include <netiso/argo_debug.h>
80 #include <netiso/iso.h>
81 #include <netiso/clnp.h>
82 #include <netinet/in_systm.h>
83 #include <net/if.h>
84 #include <net/route.h>
85 #include <netiso/iso_pcb.h>
86 #include <netiso/iso_var.h>
87 #include <sys/protosw.h>
88
89 #ifdef TPCONS
90 #include <netccitt/x25.h>
91 #include <netccitt/pk.h>
92 #include <netccitt/pk_var.h>
93 #include <netccitt/pk_extern.h>
94 #endif
95
96 struct iso_addr zeroiso_addr = {
97 0
98 };
99
100 #ifdef ARGO_DEBUG
101 unsigned char argo_debug[128];
102 #endif
103
104 /*
105 * FUNCTION: iso_pcballoc
106 *
107 * PURPOSE: creates an isopcb structure in an mbuf,
108 * with socket (so), and
109 * puts it in the queue with head (head)
110 *
111 * RETURNS: 0 if OK, ENOBUFS if can't alloc the necessary mbuf
112 */
113 int
114 iso_pcballoc(so, v)
115 struct socket *so;
116 void *v;
117 {
118 struct isopcb *head = v;
119 struct isopcb *isop;
120
121 #ifdef ARGO_DEBUG
122 if (argo_debug[D_ISO]) {
123 printf("iso_pcballoc(so %p)\n", so);
124 }
125 #endif
126 MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT);
127 if (isop == NULL)
128 return ENOBUFS;
129 bzero(isop, sizeof(*isop));
130 isop->isop_head = head;
131 isop->isop_socket = so;
132 insque(isop, head);
133 if (so)
134 so->so_pcb = isop;
135 return 0;
136 }
137
138 /*
139 * FUNCTION: iso_pcbbind
140 *
141 * PURPOSE: binds the address given in *(nam) to the socket
142 * specified by the isopcb in *(isop)
143 * If the given address is zero, it makes sure the
144 * address isn't already in use and if it's got a network
145 * portion, we look for an interface with that network
146 * address. If the address given is zero, we allocate
147 * a port and stuff it in the (nam) structure.
148 *
149 * RETURNS: errno E* or 0 if ok.
150 *
151 * SIDE EFFECTS: increments head->isop_lport if it allocates a port #
152 *
153 * NOTES:
154 */
155 int
156 iso_pcbbind(v, nam, p)
157 void *v;
158 struct mbuf *nam;
159 struct proc *p;
160 {
161 struct isopcb *isop = v;
162 struct isopcb *head = isop->isop_head;
163 struct sockaddr_iso *siso;
164 struct iso_ifaddr *ia;
165 union {
166 char data[2];
167 u_short s;
168 } suf;
169
170 #ifdef ARGO_DEBUG
171 if (argo_debug[D_ISO]) {
172 printf("iso_pcbbind(isop %p, nam %p)\n", isop, nam);
173 }
174 #endif
175 suf.s = 0;
176 if (iso_ifaddr.tqh_first == 0) /* any interfaces attached? */
177 return EADDRNOTAVAIL;
178 if (isop->isop_laddr) /* already bound */
179 return EADDRINUSE;
180 if (nam == (struct mbuf *) 0) {
181 isop->isop_laddr = &isop->isop_sladdr;
182 isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso);
183 isop->isop_sladdr.siso_family = AF_ISO;
184 isop->isop_sladdr.siso_tlen = 2;
185 isop->isop_sladdr.siso_nlen = 0;
186 isop->isop_sladdr.siso_slen = 0;
187 isop->isop_sladdr.siso_plen = 0;
188 goto noname;
189 }
190 siso = mtod(nam, struct sockaddr_iso *);
191 #ifdef ARGO_DEBUG
192 if (argo_debug[D_ISO]) {
193 printf("iso_pcbbind(name len 0x%x)\n", nam->m_len);
194 printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr));
195 }
196 #endif
197 /*
198 * We would like sort of length check but since some OSI addrs
199 * do not have fixed length, we can't really do much.
200 * The ONLY thing we can say is that an osi addr has to have
201 * at LEAST an afi and one more byte and had better fit into
202 * a struct iso_addr.
203 * However, in fact the size of the whole thing is a struct
204 * sockaddr_iso, so probably this is what we should check for.
205 */
206 if ((nam->m_len < 2) || (nam->m_len < siso->siso_len)) {
207 return ENAMETOOLONG;
208 }
209 if (siso->siso_nlen) {
210 /* non-zero net addr- better match one of our interfaces */
211 #ifdef ARGO_DEBUG
212 if (argo_debug[D_ISO]) {
213 printf("iso_pcbbind: bind to NOT zeroisoaddr\n");
214 }
215 #endif
216 for (ia = iso_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next)
217 if (SAME_ISOIFADDR(siso, &ia->ia_addr))
218 break;
219 if (ia == 0)
220 return EADDRNOTAVAIL;
221 }
222 if (siso->siso_len <= sizeof(isop->isop_sladdr)) {
223 isop->isop_laddr = &isop->isop_sladdr;
224 } else {
225 if ((nam = m_copy(nam, 0, (int) M_COPYALL)) == 0)
226 return ENOBUFS;
227 isop->isop_mladdr = nam;
228 isop->isop_laddr = mtod(nam, struct sockaddr_iso *);
229 }
230 bcopy((caddr_t) siso, (caddr_t) isop->isop_laddr, siso->siso_len);
231 if (siso->siso_tlen == 0)
232 goto noname;
233 if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
234 iso_pcblookup(head, 0, (caddr_t) 0, isop->isop_laddr))
235 return EADDRINUSE;
236 if (siso->siso_tlen <= 2) {
237 bcopy(TSEL(siso), suf.data, sizeof(suf.data));
238 suf.s = ntohs(suf.s);
239 if (suf.s < ISO_PORT_RESERVED &&
240 (p == 0 || suser(p->p_ucred, &p->p_acflag)))
241 return EACCES;
242 } else {
243 char *cp;
244 noname:
245 cp = TSEL(isop->isop_laddr);
246 isop->isop_laddr->siso_tlen = 2;
247 #ifdef ARGO_DEBUG
248 if (argo_debug[D_ISO]) {
249 printf("iso_pcbbind noname\n");
250 }
251 #endif
252 do {
253 if (head->isop_lport++ < ISO_PORT_RESERVED ||
254 head->isop_lport > ISO_PORT_USERRESERVED)
255 head->isop_lport = ISO_PORT_RESERVED;
256 suf.s = htons(head->isop_lport);
257 cp[0] = suf.data[0];
258 cp[1] = suf.data[1];
259 } while (iso_pcblookup(head, 0, (caddr_t) 0, isop->isop_laddr));
260 }
261 #ifdef ARGO_DEBUG
262 if (argo_debug[D_ISO]) {
263 printf("iso_pcbbind returns 0, suf 0x%x\n", suf.s);
264 }
265 #endif
266 return 0;
267 }
268 /*
269 * FUNCTION: iso_pcbconnect
270 *
271 * PURPOSE: Make the isopcb (isop) look like it's connected.
272 * In other words, give it the peer address given in
273 * the mbuf * (nam). Make sure such a combination
274 * of local, peer addresses doesn't already exist
275 * for this protocol. Internet mentality prevails here,
276 * wherein a src,dst pair uniquely identifies a connection.
277 * Both net address and port must be specified in argument
278 * (nam).
279 * If we don't have a local address for this socket yet,
280 * we pick one by calling iso_pcbbind().
281 *
282 * RETURNS: errno E* or 0 if ok.
283 *
284 * SIDE EFFECTS: Looks up a route, which may cause one to be left
285 * in the isopcb.
286 *
287 * NOTES:
288 */
289 int
290 iso_pcbconnect(v, nam)
291 void *v;
292 struct mbuf *nam;
293 {
294 struct isopcb *isop = v;
295 struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
296 int local_zero, error = 0;
297 struct iso_ifaddr *ia;
298
299 #ifdef ARGO_DEBUG
300 if (argo_debug[D_ISO]) {
301 printf("iso_pcbconnect(isop %p sock %p nam %p",
302 isop, isop->isop_socket, nam);
303 printf("nam->m_len 0x%x), addr:\n", nam->m_len);
304 dump_isoaddr(siso);
305 }
306 #endif
307 if (nam->m_len < siso->siso_len)
308 return EINVAL;
309 if (siso->siso_family != AF_ISO)
310 return EAFNOSUPPORT;
311 if (siso->siso_nlen == 0) {
312 if ((ia = iso_ifaddr.tqh_first) != NULL) {
313 int nlen = ia->ia_addr.siso_nlen;
314 memmove(nlen + TSEL(siso), TSEL(siso),
315 siso->siso_plen + siso->siso_tlen + siso->siso_slen);
316 bcopy((caddr_t) & ia->ia_addr.siso_addr,
317 (caddr_t) & siso->siso_addr, nlen + 1);
318 /* includes siso->siso_nlen = nlen; */
319 } else
320 return EADDRNOTAVAIL;
321 }
322 /*
323 * Local zero means either not bound, or bound to a TSEL, but no
324 * particular local interface. So, if we want to send somebody
325 * we need to choose a return address.
326 */
327 local_zero =
328 ((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0));
329 if (local_zero) {
330 int flags;
331
332 #ifdef ARGO_DEBUG
333 if (argo_debug[D_ISO]) {
334 printf("iso_pcbconnect localzero 1\n");
335 }
336 #endif
337 /*
338 * If route is known or can be allocated now, our src addr is
339 * taken from the i/f, else punt.
340 */
341 flags = isop->isop_socket->so_options & SO_DONTROUTE;
342 error = clnp_route(&siso->siso_addr, &isop->isop_route, flags,
343 NULL, &ia);
344 if (error)
345 return error;
346 #ifdef ARGO_DEBUG
347 if (argo_debug[D_ISO]) {
348 printf("iso_pcbconnect localzero 2, ro->ro_rt %p",
349 isop->isop_route.ro_rt);
350 printf(" ia %p\n", ia);
351 }
352 #endif
353 }
354 #ifdef ARGO_DEBUG
355 if (argo_debug[D_ISO]) {
356 printf("in iso_pcbconnect before lookup isop %p isop->sock %p\n",
357 isop, isop->isop_socket);
358 }
359 #endif
360 if (local_zero) {
361 int nlen, tlen, totlen;
362 caddr_t oldtsel, newtsel;
363 siso = isop->isop_laddr;
364 if (siso == 0 || siso->siso_tlen == 0)
365 (void) iso_pcbbind(isop, (struct mbuf *)0,
366 (struct proc *)0);
367 /*
368 * Here we have problem of squezeing in a definite network address
369 * into an existing sockaddr_iso, which in fact may not have room
370 * for it. This gets messy.
371 */
372 siso = isop->isop_laddr;
373 oldtsel = TSEL(siso);
374 tlen = siso->siso_tlen;
375 nlen = ia->ia_addr.siso_nlen;
376 totlen = tlen + nlen + offsetof(struct sockaddr_iso, siso_data[0]);
377 if ((siso == &isop->isop_sladdr) &&
378 (totlen > sizeof(isop->isop_sladdr))) {
379 struct mbuf *m = m_get(M_DONTWAIT, MT_SONAME);
380 if (m == 0)
381 return ENOBUFS;
382 m->m_len = totlen;
383 isop->isop_mladdr = m;
384 isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *);
385 }
386 siso->siso_nlen = ia->ia_addr.siso_nlen;
387 newtsel = TSEL(siso);
388 memmove(newtsel, oldtsel, tlen);
389 bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
390 siso->siso_tlen = tlen;
391 siso->siso_family = AF_ISO;
392 siso->siso_len = totlen;
393 siso = mtod(nam, struct sockaddr_iso *);
394 }
395 #ifdef ARGO_DEBUG
396 if (argo_debug[D_ISO]) {
397 printf("in iso_pcbconnect before bcopy isop %p isop->sock %p\n",
398 isop, isop->isop_socket);
399 }
400 #endif
401 /*
402 * If we had to allocate space to a previous big foreign address,
403 * and for some reason we didn't free it, we reuse it knowing
404 * that is going to be big enough, as sockaddrs are delivered in
405 * 128 byte mbufs.
406 * If the foreign address is small enough, we use default space;
407 * otherwise, we grab an mbuf to copy into.
408 */
409 if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) {
410 if (siso->siso_len <= sizeof(isop->isop_sfaddr))
411 isop->isop_faddr = &isop->isop_sfaddr;
412 else {
413 struct mbuf *m = m_get(M_DONTWAIT, MT_SONAME);
414 if (m == 0)
415 return ENOBUFS;
416 isop->isop_mfaddr = m;
417 isop->isop_faddr = mtod(m, struct sockaddr_iso *);
418 }
419 }
420 bcopy((caddr_t) siso, (caddr_t) isop->isop_faddr, siso->siso_len);
421 #ifdef ARGO_DEBUG
422 if (argo_debug[D_ISO]) {
423 printf("in iso_pcbconnect after bcopy isop %p isop->sock %p\n",
424 isop, isop->isop_socket);
425 printf("iso_pcbconnect connected to addr:\n");
426 dump_isoaddr(isop->isop_faddr);
427 printf("iso_pcbconnect end: src addr:\n");
428 dump_isoaddr(isop->isop_laddr);
429 }
430 #endif
431 return 0;
432 }
433
434 /*
435 * FUNCTION: iso_pcbdisconnect()
436 *
437 * PURPOSE: washes away the peer address info so the socket
438 * appears to be disconnected.
439 * If there's no file descriptor associated with the socket
440 * it detaches the pcb.
441 *
442 * RETURNS: Nada.
443 *
444 * SIDE EFFECTS: May detach the pcb.
445 *
446 * NOTES:
447 */
448 void
449 iso_pcbdisconnect(v)
450 void *v;
451 {
452 struct isopcb *isop = v;
453 struct sockaddr_iso *siso;
454
455 #ifdef ARGO_DEBUG
456 if (argo_debug[D_ISO]) {
457 printf("iso_pcbdisconnect(isop %p)\n", isop);
458 }
459 #endif
460 /*
461 * Preserver binding infnormation if already bound.
462 */
463 if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) {
464 caddr_t otsel = TSEL(siso);
465 siso->siso_nlen = 0;
466 memmove(TSEL(siso), otsel, siso->siso_tlen);
467 }
468 if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
469 m_freem(isop->isop_mfaddr);
470 isop->isop_faddr = 0;
471 if (isop->isop_socket->so_state & SS_NOFDREF)
472 iso_pcbdetach(isop);
473 }
474
475 /*
476 * FUNCTION: iso_pcbdetach
477 *
478 * PURPOSE: detach the pcb at *(isop) from it's socket and free
479 * the mbufs associated with the pcb..
480 * Dequeues (isop) from its head.
481 *
482 * RETURNS: Nada.
483 *
484 * SIDE EFFECTS:
485 *
486 * NOTES:
487 */
488 void
489 iso_pcbdetach(v)
490 void *v;
491 {
492 struct isopcb *isop = v;
493 struct socket *so = isop->isop_socket;
494
495 #ifdef ARGO_DEBUG
496 if (argo_debug[D_ISO]) {
497 printf("iso_pcbdetach(isop %p socket %p so %p)\n",
498 isop, isop->isop_socket, so);
499 }
500 #endif
501 #ifdef TPCONS
502 if (isop->isop_chan) {
503 struct pklcd *lcp = (struct pklcd *) isop->isop_chan;
504 if (--isop->isop_refcnt > 0)
505 return;
506 if (lcp && lcp->lcd_state == DATA_TRANSFER) {
507 lcp->lcd_upper = 0;
508 lcp->lcd_upnext = 0;
509 pk_disconnect(lcp);
510 }
511 isop->isop_chan = 0;
512 }
513 #endif
514 if (so) { /* in the x.25 domain, we sometimes have no
515 * socket */
516 so->so_pcb = 0;
517 sofree(so);
518 }
519 #ifdef ARGO_DEBUG
520 if (argo_debug[D_ISO]) {
521 printf("iso_pcbdetach 2 \n");
522 }
523 #endif
524 if (isop->isop_options)
525 (void) m_free(isop->isop_options);
526 #ifdef ARGO_DEBUG
527 if (argo_debug[D_ISO]) {
528 printf("iso_pcbdetach 3 \n");
529 }
530 #endif
531 if (isop->isop_route.ro_rt)
532 rtfree(isop->isop_route.ro_rt);
533 #ifdef ARGO_DEBUG
534 if (argo_debug[D_ISO]) {
535 printf("iso_pcbdetach 3.1\n");
536 }
537 #endif
538 if (isop->isop_clnpcache != NULL) {
539 struct clnp_cache *clcp =
540 mtod(isop->isop_clnpcache, struct clnp_cache *);
541 #ifdef ARGO_DEBUG
542 if (argo_debug[D_ISO]) {
543 printf("iso_pcbdetach 3.2: clcp %p freeing clc_hdr %p\n",
544 clcp, clcp->clc_hdr);
545 }
546 #endif
547 if (clcp->clc_hdr != NULL)
548 m_free(clcp->clc_hdr);
549 #ifdef ARGO_DEBUG
550 if (argo_debug[D_ISO]) {
551 printf("iso_pcbdetach 3.3: freeing cache %p\n",
552 isop->isop_clnpcache);
553 }
554 #endif
555 m_free(isop->isop_clnpcache);
556 }
557 #ifdef ARGO_DEBUG
558 if (argo_debug[D_ISO]) {
559 printf("iso_pcbdetach 4 \n");
560 }
561 #endif
562 remque(isop);
563 #ifdef ARGO_DEBUG
564 if (argo_debug[D_ISO]) {
565 printf("iso_pcbdetach 5 \n");
566 }
567 #endif
568 if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
569 m_freem(isop->isop_mladdr);
570 free((caddr_t) isop, M_PCB);
571 }
572
573
574 /*
575 * FUNCTION: iso_pcbnotify
576 *
577 * PURPOSE: notify all connections in this protocol's queue (head)
578 * that have peer address (dst) of the problem (errno)
579 * by calling (notify) on the connections' isopcbs.
580 *
581 * RETURNS: Rien.
582 *
583 * SIDE EFFECTS:
584 *
585 * NOTES: (notify) is called at splnet!
586 */
587 void
588 iso_pcbnotify(head, siso, errno, notify)
589 struct isopcb *head;
590 struct sockaddr_iso *siso;
591 int errno;
592 void (*notify) __P((struct isopcb *));
593 {
594 struct isopcb *isop;
595 int s = splnet();
596
597 #ifdef ARGO_DEBUG
598 if (argo_debug[D_ISO]) {
599 printf("iso_pcbnotify(head %p, notify %p) dst:\n",
600 head, notify);
601 }
602 #endif
603 for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
604 if (isop->isop_socket == 0 || isop->isop_faddr == 0 ||
605 !SAME_ISOADDR(siso, isop->isop_faddr)) {
606 #ifdef ARGO_DEBUG
607 if (argo_debug[D_ISO]) {
608 printf("iso_pcbnotify: CONTINUE isop %p, sock %p\n",
609 isop, isop->isop_socket);
610 printf("addrmatch cmp'd with (%p):\n",
611 isop->isop_faddr);
612 dump_isoaddr(isop->isop_faddr);
613 }
614 #endif
615 continue;
616 }
617 if (errno)
618 isop->isop_socket->so_error = errno;
619 if (notify)
620 (*notify) (isop);
621 }
622 splx(s);
623 #ifdef ARGO_DEBUG
624 if (argo_debug[D_ISO]) {
625 printf("END OF iso_pcbnotify\n");
626 }
627 #endif
628 }
629
630
631 /*
632 * FUNCTION: iso_pcblookup
633 *
634 * PURPOSE: looks for a given combination of (faddr), (fport),
635 * (lport), (laddr) in the queue named by (head).
636 * Argument (flags) is ignored.
637 *
638 * RETURNS: ptr to the isopcb if it finds a connection matching
639 * these arguments, o.w. returns zero.
640 *
641 * SIDE EFFECTS:
642 *
643 * NOTES:
644 */
645 struct isopcb *
646 iso_pcblookup(head, fportlen, fport, laddr)
647 struct isopcb *head;
648 struct sockaddr_iso *laddr;
649 caddr_t fport;
650 int fportlen;
651 {
652 struct isopcb *isop;
653 caddr_t lp = TSEL(laddr);
654 unsigned int llen = laddr->siso_tlen;
655
656 #ifdef ARGO_DEBUG
657 if (argo_debug[D_ISO]) {
658 printf("iso_pcblookup(head %p laddr %p fport %p)\n",
659 head, laddr, fport);
660 }
661 #endif
662 for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
663 if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
664 continue;
665 if (isop->isop_laddr->siso_tlen != llen)
666 continue;
667 if (bcmp(lp, TSEL(isop->isop_laddr), llen))
668 continue;
669 if (fportlen && isop->isop_faddr &&
670 bcmp(fport, TSEL(isop->isop_faddr), (unsigned) fportlen))
671 continue;
672 /*
673 * PHASE2 addrmatch1 should be iso_addrmatch(a, b, mask)
674 * where mask is taken from isop->isop_laddrmask (new field)
675 * isop_lnetmask will also be available in isop if (laddr !=
676 * &zeroiso_addr && !iso_addrmatch1(laddr,
677 * &(isop->isop_laddr.siso_addr))) continue;
678 */
679 if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr)))
680 continue;
681 return (isop);
682 }
683 return (struct isopcb *) 0;
684 }
685 #endif /* ISO */
Cache object: ee0280bf2c3d01b675160c4b410567c7
|