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