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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    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


[ 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.