1/* $NetBSD: iso_pcb.c,v 1.48 2009/04/16 21:37:17 elad 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 39Permission to use, copy, modify, and distribute this software and its 40documentation for any purpose and without fee is hereby granted, 41provided that the above copyright notice appear in all copies and that 42both that copyright notice and this permission notice appear in 43supporting documentation, and that the name of IBM not be 44used in advertising or publicity pertaining to distribution of the 45software without specific, written prior permission. 46 47IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 48ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 49IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 50ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 51WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 52ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 53SOFTWARE. 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.48 2009/04/16 21:37:17 elad 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 90const struct iso_addr zeroiso_addr; 91 92#ifdef ARGO_DEBUG 93unsigned 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 */ 105int 106iso_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 isop = malloc(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 iso_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 */ 144int 145iso_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 memcpy((void *) isop->isop_laddr, (void *) siso, 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, (void *) 0, isop->isop_laddr)) 221 return EADDRINUSE; 222 if (siso->siso_tlen <= 2) { 223 memcpy(suf.data, TSEL(siso), sizeof(suf.data)); 224 suf.s = ntohs(suf.s); 225 if (suf.s < ISO_PORT_RESERVED) { 226 int error; 227 228 if (l == NULL) 229 error = EACCES; 230 else 231 error = kauth_authorize_network(l->l_cred, 232 KAUTH_NETWORK_BIND, 233 KAUTH_REQ_NETWORK_BIND_PRIVPORT, 234 isop->isop_socket, siso, NULL); 235 236 if (error) 237 return (error); 238 } 239 } else { 240 char *cp; 241noname: 242 cp = WRITABLE_TSEL(isop->isop_laddr); 243 isop->isop_laddr->siso_tlen = 2; 244#ifdef ARGO_DEBUG 245 if (argo_debug[D_ISO]) { 246 printf("iso_pcbbind noname\n"); 247 } 248#endif 249 do { 250 if (head->isop_lport++ < ISO_PORT_RESERVED || 251 head->isop_lport > ISO_PORT_USERRESERVED) 252 head->isop_lport = ISO_PORT_RESERVED; 253 suf.s = htons(head->isop_lport); 254 cp[0] = suf.data[0]; 255 cp[1] = suf.data[1]; 256 } while (iso_pcblookup(head, 0, (void *) 0, isop->isop_laddr)); 257 } 258#ifdef ARGO_DEBUG 259 if (argo_debug[D_ISO]) { 260 printf("iso_pcbbind returns 0, suf 0x%x\n", suf.s); 261 } 262#endif 263 return 0; 264} 265/* 266 * FUNCTION: iso_pcbconnect 267 * 268 * PURPOSE: Make the isopcb (isop) look like it's connected. 269 * In other words, give it the peer address given in 270 * the mbuf * (nam). Make sure such a combination 271 * of local, peer addresses doesn't already exist 272 * for this protocol. Internet mentality prevails here, 273 * wherein a src,dst pair uniquely identifies a connection. 274 * Both net address and port must be specified in argument 275 * (nam). 276 * If we don't have a local address for this socket yet, 277 * we pick one by calling iso_pcbbind(). 278 * 279 * RETURNS: errno E* or 0 if ok. 280 * 281 * SIDE EFFECTS: Looks up a route, which may cause one to be left 282 * in the isopcb. 283 * 284 * NOTES: 285 */ 286int 287iso_pcbconnect(void *v, struct mbuf *nam, struct lwp *l) 288{ 289 struct isopcb *isop = v; 290 struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 291 int local_zero, error = 0; 292 struct iso_ifaddr *ia; 293 294#ifdef ARGO_DEBUG 295 if (argo_debug[D_ISO]) { 296 printf("iso_pcbconnect(isop %p sock %p nam %p", 297 isop, isop->isop_socket, nam); 298 printf("nam->m_len 0x%x), addr:\n", nam->m_len); 299 dump_isoaddr(siso); 300 } 301#endif 302 if (nam->m_len < siso->siso_len) 303 return EINVAL; 304 if (siso->siso_family != AF_ISO) 305 return EAFNOSUPPORT; 306 if (siso->siso_nlen == 0) { 307 if ((ia = iso_ifaddr.tqh_first) != NULL) { 308 int nlen = ia->ia_addr.siso_nlen; 309 char *tmp; 310 tmp = WRITABLE_TSEL(siso); 311 memmove(tmp + nlen, TSEL(siso), 312 siso->siso_plen + siso->siso_tlen + 313 siso->siso_slen); 314 bcopy((void *) & ia->ia_addr.siso_addr, 315 (void *) & siso->siso_addr, nlen + 1); 316 /* includes siso->siso_nlen = nlen; */ 317 } else 318 return EADDRNOTAVAIL; 319 } 320 /* 321 * Local zero means either not bound, or bound to a TSEL, but no 322 * particular local interface. So, if we want to send somebody 323 * we need to choose a return address. 324 */ 325 local_zero = 326 ((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0)); 327 if (local_zero) { 328 int flags; 329 330#ifdef ARGO_DEBUG 331 if (argo_debug[D_ISO]) { 332 printf("iso_pcbconnect localzero 1\n"); 333 } 334#endif 335 /* 336 * If route is known or can be allocated now, our src addr is 337 * taken from the i/f, else punt. 338 */ 339 flags = isop->isop_socket->so_options & SO_DONTROUTE; 340 error = clnp_route(&siso->siso_addr, &isop->isop_route, flags, 341 NULL, &ia); 342 if (error) 343 return error; 344#ifdef ARGO_DEBUG 345 if (argo_debug[D_ISO]) { 346 printf("iso_pcbconnect localzero 2, rt %p", 347 rtcache_validate(&isop->isop_route)); 348 printf(" ia %p\n", ia); 349 } 350#endif 351 } 352#ifdef ARGO_DEBUG 353 if (argo_debug[D_ISO]) { 354 printf("in iso_pcbconnect before lookup isop %p isop->sock %p\n", 355 isop, isop->isop_socket); 356 } 357#endif 358 if (local_zero) { 359 int nlen, tlen, totlen; 360 void *newtsel; 361 const void *oldtsel; 362 siso = isop->isop_laddr; 363 if (siso == 0 || siso->siso_tlen == 0) 364 (void) iso_pcbbind(isop, (struct mbuf *)0, 365 (struct lwp *)0); 366 /* 367 * Here we have problem of squezeing in a definite network address 368 * into an existing sockaddr_iso, which in fact may not have room 369 * for it. This gets messy. 370 */ 371 siso = isop->isop_laddr; 372 oldtsel = TSEL(siso); 373 tlen = siso->siso_tlen; 374 nlen = ia->ia_addr.siso_nlen; 375 totlen = tlen + nlen + offsetof(struct sockaddr_iso, siso_data[0]); 376 if ((siso == &isop->isop_sladdr) && 377 (totlen > sizeof(isop->isop_sladdr))) { 378 struct mbuf *m = m_get(M_DONTWAIT, MT_SONAME); 379 if (m == 0) 380 return ENOBUFS; 381 m->m_len = totlen; 382 isop->isop_mladdr = m; 383 isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *); 384 } 385 siso->siso_nlen = ia->ia_addr.siso_nlen; 386 newtsel = WRITABLE_TSEL(siso); 387 memmove(newtsel, oldtsel, tlen); 388 memcpy(siso->siso_data, ia->ia_addr.siso_data, nlen); 389 siso->siso_tlen = tlen; 390 siso->siso_family = AF_ISO; 391 siso->siso_len = totlen; 392 siso = mtod(nam, struct sockaddr_iso *); 393 } 394#ifdef ARGO_DEBUG 395 if (argo_debug[D_ISO]) { 396 printf("in iso_pcbconnect before bcopy isop %p isop->sock %p\n", 397 isop, isop->isop_socket); 398 } 399#endif 400 /* 401 * If we had to allocate space to a previous big foreign address, 402 * and for some reason we didn't free it, we reuse it knowing 403 * that is going to be big enough, as sockaddrs are delivered in 404 * 128 byte mbufs. 405 * If the foreign address is small enough, we use default space; 406 * otherwise, we grab an mbuf to copy into. 407 */ 408 if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) { 409 if (siso->siso_len <= sizeof(isop->isop_sfaddr)) 410 isop->isop_faddr = &isop->isop_sfaddr; 411 else { 412 struct mbuf *m = m_get(M_DONTWAIT, MT_SONAME); 413 if (m == 0) 414 return ENOBUFS; 415 isop->isop_mfaddr = m; 416 isop->isop_faddr = mtod(m, struct sockaddr_iso *); 417 } 418 } 419 memcpy((void *) isop->isop_faddr, (void *) siso, siso->siso_len); 420#ifdef ARGO_DEBUG 421 if (argo_debug[D_ISO]) { 422 printf("in iso_pcbconnect after bcopy isop %p isop->sock %p\n", 423 isop, isop->isop_socket); 424 printf("iso_pcbconnect connected to addr:\n"); 425 dump_isoaddr(isop->isop_faddr); 426 printf("iso_pcbconnect end: src addr:\n"); 427 dump_isoaddr(isop->isop_laddr); 428 } 429#endif 430 return 0; 431} 432 433/* 434 * FUNCTION: iso_pcbdisconnect() 435 * 436 * PURPOSE: washes away the peer address info so the socket 437 * appears to be disconnected. 438 * If there's no file descriptor associated with the socket 439 * it detaches the pcb. 440 * 441 * RETURNS: Nada. 442 * 443 * SIDE EFFECTS: May detach the pcb. 444 * 445 * NOTES: 446 */ 447void 448iso_pcbdisconnect(void *v) 449{ 450 struct isopcb *isop = v; 451 struct sockaddr_iso *siso; 452 453#ifdef ARGO_DEBUG 454 if (argo_debug[D_ISO]) { 455 printf("iso_pcbdisconnect(isop %p)\n", isop); 456 } 457#endif 458 /* 459 * Preserver binding infnormation if already bound. 460 */ 461 if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) { 462 const void *otsel = TSEL(siso); 463 siso->siso_nlen = 0; 464 memmove(WRITABLE_TSEL(siso), otsel, siso->siso_tlen); 465 } 466 if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr) 467 m_freem(isop->isop_mfaddr); 468 isop->isop_faddr = 0; 469 if (isop->isop_socket->so_state & SS_NOFDREF) 470 iso_pcbdetach(isop); 471} 472 473/* 474 * FUNCTION: iso_pcbdetach 475 * 476 * PURPOSE: detach the pcb at *(isop) from it's socket and free 477 * the mbufs associated with the pcb.. 478 * Dequeues (isop) from its head. 479 * 480 * RETURNS: Nada. 481 * 482 * SIDE EFFECTS: 483 * 484 * NOTES: 485 */ 486void 487iso_pcbdetach(void *v) 488{ 489 struct isopcb *isop = v; 490 struct socket *so = isop->isop_socket; 491 492#ifdef ARGO_DEBUG 493 if (argo_debug[D_ISO]) { 494 printf("iso_pcbdetach(isop %p socket %p so %p)\n", 495 isop, isop->isop_socket, so); 496 } 497#endif 498 if (so) { /* in the x.25 domain, we sometimes have no 499 * socket */ 500 so->so_pcb = 0; 501 /* sofree drops the lock */ 502 sofree(so); 503 mutex_enter(softnet_lock); 504 } 505#ifdef ARGO_DEBUG 506 if (argo_debug[D_ISO]) { 507 printf("iso_pcbdetach 2 \n"); 508 } 509#endif 510 if (isop->isop_options) 511 (void) m_free(isop->isop_options); 512#ifdef ARGO_DEBUG 513 if (argo_debug[D_ISO]) { 514 printf("iso_pcbdetach 3 \n"); 515 } 516#endif 517 rtcache_free(&isop->isop_route); 518#ifdef ARGO_DEBUG 519 if (argo_debug[D_ISO]) { 520 printf("iso_pcbdetach 3.1\n"); 521 } 522#endif 523 if (isop->isop_clnpcache != NULL) { 524 struct clnp_cache *clcp = 525 mtod(isop->isop_clnpcache, struct clnp_cache *); 526#ifdef ARGO_DEBUG 527 if (argo_debug[D_ISO]) { 528 printf("iso_pcbdetach 3.2: clcp %p freeing clc_hdr %p\n", 529 clcp, clcp->clc_hdr); 530 } 531#endif 532 if (clcp->clc_hdr != NULL) 533 m_free(clcp->clc_hdr); 534#ifdef ARGO_DEBUG 535 if (argo_debug[D_ISO]) { 536 printf("iso_pcbdetach 3.3: freeing cache %p\n", 537 isop->isop_clnpcache); 538 } 539#endif 540 m_free(isop->isop_clnpcache); 541 } 542#ifdef ARGO_DEBUG 543 if (argo_debug[D_ISO]) { 544 printf("iso_pcbdetach 4 \n"); 545 } 546#endif 547 iso_remque(isop); 548#ifdef ARGO_DEBUG 549 if (argo_debug[D_ISO]) { 550 printf("iso_pcbdetach 5 \n"); 551 } 552#endif 553 if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr)) 554 m_freem(isop->isop_mladdr); 555 free((void *) isop, M_PCB); 556} 557 558 559/* 560 * FUNCTION: iso_pcbnotify 561 * 562 * PURPOSE: notify all connections in this protocol's queue (head) 563 * that have peer address (dst) of the problem (errno) 564 * by calling (notify) on the connections' isopcbs. 565 * 566 * RETURNS: Rien. 567 * 568 * SIDE EFFECTS: 569 * 570 * NOTES: (notify) is called at splnet! 571 */ 572void 573iso_pcbnotify(struct isopcb *head, const struct sockaddr_iso *siso, int errno, 574 void (*notify) (struct isopcb *)) 575{ 576 struct isopcb *isop; 577 int s = splnet(); 578 579#ifdef ARGO_DEBUG 580 if (argo_debug[D_ISO]) { 581 printf("iso_pcbnotify(head %p, notify %p) dst:\n", 582 head, notify); 583 } 584#endif 585 for (isop = head->isop_next; isop != head; isop = isop->isop_next) { 586 if (isop->isop_socket == 0 || isop->isop_faddr == 0 || 587 !SAME_ISOADDR(siso, isop->isop_faddr)) { 588#ifdef ARGO_DEBUG 589 if (argo_debug[D_ISO]) { 590 printf("iso_pcbnotify: CONTINUE isop %p, sock %p\n", 591 isop, isop->isop_socket); 592 printf("addrmatch cmp'd with (%p):\n", 593 isop->isop_faddr); 594 dump_isoaddr(isop->isop_faddr); 595 } 596#endif 597 continue; 598 } 599 if (errno) 600 isop->isop_socket->so_error = errno; 601 if (notify) 602 (*notify) (isop); 603 } 604 splx(s); 605#ifdef ARGO_DEBUG 606 if (argo_debug[D_ISO]) { 607 printf("END OF iso_pcbnotify\n"); 608 } 609#endif 610} 611 612 613/* 614 * FUNCTION: iso_pcblookup 615 * 616 * PURPOSE: looks for a given combination of (faddr), (fport), 617 * (lport), (laddr) in the queue named by (head). 618 * Argument (flags) is ignored. 619 * 620 * RETURNS: ptr to the isopcb if it finds a connection matching 621 * these arguments, o.w. returns zero. 622 * 623 * SIDE EFFECTS: 624 * 625 * NOTES: 626 */ 627struct isopcb * 628iso_pcblookup( 629 struct isopcb *head, 630 int fportlen, 631 void * fport, 632 const struct sockaddr_iso *laddr) 633{ 634 struct isopcb *isop; 635 const void *lp = TSEL(laddr); 636 unsigned int llen = laddr->siso_tlen; 637 638#ifdef ARGO_DEBUG 639 if (argo_debug[D_ISO]) { 640 printf("iso_pcblookup(head %p laddr %p fport %p)\n", 641 head, laddr, fport); 642 } 643#endif 644 for (isop = head->isop_next; isop != head; isop = isop->isop_next) { 645 if (isop->isop_laddr == 0 || isop->isop_laddr == laddr) 646 continue; 647 if (isop->isop_laddr->siso_tlen != llen) 648 continue; 649 if (memcmp(lp, TSEL(isop->isop_laddr), llen)) 650 continue; 651 if (fportlen && isop->isop_faddr && 652 memcmp(fport, TSEL(isop->isop_faddr), (unsigned) fportlen)) 653 continue; 654 /* 655 * PHASE2 addrmatch1 should be iso_addrmatch(a, b, mask) 656 * where mask is taken from isop->isop_laddrmask (new field) 657 * isop_lnetmask will also be available in isop if (laddr != 658 * &zeroiso_addr && !iso_addrmatch1(laddr, 659 * &(isop->isop_laddr.siso_addr))) continue; 660 */ 661 if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr))) 662 continue; 663 return (isop); 664 } 665 return (struct isopcb *) 0; 666} 667#endif /* ISO */ 668