The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netiso/iso_pcb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.