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

Cache object: ee0280bf2c3d01b675160c4b410567c7


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