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/netipx/ipx_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 /*-
    2  * Copyright (c) 2004-2005 Robert N. M. Watson
    3  * Copyright (c) 1995, Mike Mitchell
    4  * Copyright (c) 1984, 1985, 1986, 1987, 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. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by the University of
   18  *      California, Berkeley and its contributors.
   19  * 4. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  *      @(#)ipx_pcb.c
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD: releng/6.1/sys/netipx/ipx_pcb.c 139928 2005-01-09 05:10:43Z rwatson $");
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/malloc.h>
   44 #include <sys/socket.h>
   45 #include <sys/socketvar.h>
   46 
   47 #include <net/if.h>
   48 #include <net/route.h>
   49 
   50 #include <netipx/ipx.h>
   51 #include <netipx/ipx_if.h>
   52 #include <netipx/ipx_pcb.h>
   53 #include <netipx/ipx_var.h>
   54 
   55 static struct   ipx_addr zeroipx_addr;
   56 static u_short  ipxpcb_lport_cache;
   57 
   58 int
   59 ipx_pcballoc(so, head, td)
   60         struct socket *so;
   61         struct ipxpcbhead *head;
   62         struct thread *td;
   63 {
   64         register struct ipxpcb *ipxp;
   65 
   66         IPX_LIST_LOCK_ASSERT();
   67 
   68         MALLOC(ipxp, struct ipxpcb *, sizeof *ipxp, M_PCB, M_NOWAIT | M_ZERO);
   69         if (ipxp == NULL)
   70                 return (ENOBUFS);
   71         IPX_LOCK_INIT(ipxp);
   72         ipxp->ipxp_socket = so;
   73         if (ipxcksum)
   74                 ipxp->ipxp_flags |= IPXP_CHECKSUM;
   75         LIST_INSERT_HEAD(head, ipxp, ipxp_list);
   76         so->so_pcb = (caddr_t)ipxp;
   77         return (0);
   78 }
   79 
   80 int
   81 ipx_pcbbind(ipxp, nam, td)
   82         register struct ipxpcb *ipxp;
   83         struct sockaddr *nam;
   84         struct thread *td;
   85 {
   86         register struct sockaddr_ipx *sipx;
   87         u_short lport = 0;
   88 
   89         IPX_LIST_LOCK_ASSERT();
   90         IPX_LOCK_ASSERT(ipxp);
   91 
   92         if (ipxp->ipxp_lport || !ipx_nullhost(ipxp->ipxp_laddr))
   93                 return (EINVAL);
   94         if (nam == NULL)
   95                 goto noname;
   96         sipx = (struct sockaddr_ipx *)nam;
   97         if (!ipx_nullhost(sipx->sipx_addr)) {
   98                 int tport = sipx->sipx_port;
   99 
  100                 sipx->sipx_port = 0;            /* yech... */
  101                 if (ifa_ifwithaddr((struct sockaddr *)sipx) == NULL)
  102                         return (EADDRNOTAVAIL);
  103                 sipx->sipx_port = tport;
  104         }
  105         lport = sipx->sipx_port;
  106         if (lport) {
  107                 u_short aport = ntohs(lport);
  108                 int error;
  109 
  110                 if (aport < IPXPORT_RESERVED &&
  111                     td != NULL && (error = suser(td)) != 0)
  112                         return (error);
  113                 if (ipx_pcblookup(&zeroipx_addr, lport, 0))
  114                         return (EADDRINUSE);
  115         }
  116         ipxp->ipxp_laddr = sipx->sipx_addr;
  117 noname:
  118         if (lport == 0)
  119                 do {
  120                         ipxpcb_lport_cache++;
  121                         if ((ipxpcb_lport_cache < IPXPORT_RESERVED) ||
  122                             (ipxpcb_lport_cache >= IPXPORT_WELLKNOWN))
  123                                 ipxpcb_lport_cache = IPXPORT_RESERVED;
  124                         lport = htons(ipxpcb_lport_cache);
  125                 } while (ipx_pcblookup(&zeroipx_addr, lport, 0));
  126         ipxp->ipxp_lport = lport;
  127         return (0);
  128 }
  129 
  130 /*
  131  * Connect from a socket to a specified address.
  132  * Both address and port must be specified in argument sipx.
  133  * If don't have a local address for this socket yet,
  134  * then pick one.
  135  */
  136 int
  137 ipx_pcbconnect(ipxp, nam, td)
  138         struct ipxpcb *ipxp;
  139         struct sockaddr *nam;
  140         struct thread *td;
  141 {
  142         struct ipx_ifaddr *ia;
  143         register struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)nam;
  144         register struct ipx_addr *dst;
  145         register struct route *ro;
  146         struct ifnet *ifp;
  147 
  148         IPX_LIST_LOCK_ASSERT();
  149         IPX_LOCK_ASSERT(ipxp);
  150 
  151         ia = NULL;
  152 
  153         if (sipx->sipx_family != AF_IPX)
  154                 return (EAFNOSUPPORT);
  155         if (sipx->sipx_port == 0 || ipx_nullhost(sipx->sipx_addr))
  156                 return (EADDRNOTAVAIL);
  157         /*
  158          * If we haven't bound which network number to use as ours,
  159          * we will use the number of the outgoing interface.
  160          * This depends on having done a routing lookup, which
  161          * we will probably have to do anyway, so we might
  162          * as well do it now.  On the other hand if we are
  163          * sending to multiple destinations we may have already
  164          * done the lookup, so see if we can use the route
  165          * from before.  In any case, we only
  166          * chose a port number once, even if sending to multiple
  167          * destinations.
  168          */
  169         ro = &ipxp->ipxp_route;
  170         dst = &satoipx_addr(ro->ro_dst);
  171         if (ipxp->ipxp_socket->so_options & SO_DONTROUTE)
  172                 goto flush;
  173         if (!ipx_neteq(ipxp->ipxp_lastdst, sipx->sipx_addr))
  174                 goto flush;
  175         if (!ipx_hosteq(ipxp->ipxp_lastdst, sipx->sipx_addr)) {
  176                 if (ro->ro_rt != NULL && !(ro->ro_rt->rt_flags & RTF_HOST)) {
  177                         /* can patch route to avoid rtalloc */
  178                         *dst = sipx->sipx_addr;
  179                 } else {
  180         flush:
  181                         if (ro->ro_rt != NULL)
  182                                 RTFREE(ro->ro_rt);
  183                         ro->ro_rt = NULL;
  184                 }
  185         }/* else cached route is ok; do nothing */
  186         ipxp->ipxp_lastdst = sipx->sipx_addr;
  187         if ((ipxp->ipxp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
  188             (ro->ro_rt == NULL || ro->ro_rt->rt_ifp == NULL)) {
  189                     /* No route yet, so try to acquire one */
  190                     ro->ro_dst.sa_family = AF_IPX;
  191                     ro->ro_dst.sa_len = sizeof(ro->ro_dst);
  192                     *dst = sipx->sipx_addr;
  193                     dst->x_port = 0;
  194                     rtalloc_ign(ro, 0);
  195         }
  196         if (ipx_neteqnn(ipxp->ipxp_laddr.x_net, ipx_zeronet)) {
  197                 /*
  198                  * If route is known or can be allocated now,
  199                  * our src addr is taken from the i/f, else punt.
  200                  */
  201 
  202                 /*
  203                  * If we found a route, use the address
  204                  * corresponding to the outgoing interface
  205                  */
  206                 if (ro->ro_rt != NULL && (ifp = ro->ro_rt->rt_ifp) != NULL)
  207                         for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next)
  208                                 if (ia->ia_ifp == ifp)
  209                                         break;
  210                 if (ia == NULL) {
  211                         u_short fport = sipx->sipx_addr.x_port;
  212                         sipx->sipx_addr.x_port = 0;
  213                         ia = (struct ipx_ifaddr *)
  214                                 ifa_ifwithdstaddr((struct sockaddr *)sipx);
  215                         sipx->sipx_addr.x_port = fport;
  216                         if (ia == NULL)
  217                                 ia = ipx_iaonnetof(&sipx->sipx_addr);
  218                         if (ia == NULL)
  219                                 ia = ipx_ifaddr;
  220                         if (ia == NULL)
  221                                 return (EADDRNOTAVAIL);
  222                 }
  223                 ipxp->ipxp_laddr.x_net = satoipx_addr(ia->ia_addr).x_net;
  224         }
  225         if (ipx_nullhost(ipxp->ipxp_laddr)) {
  226                 /*
  227                  * If route is known or can be allocated now,
  228                  * our src addr is taken from the i/f, else punt.
  229                  */
  230 
  231                 /*
  232                  * If we found a route, use the address
  233                  * corresponding to the outgoing interface
  234                  */
  235                 if (ro->ro_rt != NULL && (ifp = ro->ro_rt->rt_ifp) != NULL)
  236                         for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next)
  237                                 if (ia->ia_ifp == ifp)
  238                                         break;
  239                 if (ia == NULL) {
  240                         u_short fport = sipx->sipx_addr.x_port;
  241                         sipx->sipx_addr.x_port = 0;
  242                         ia = (struct ipx_ifaddr *)
  243                                 ifa_ifwithdstaddr((struct sockaddr *)sipx);
  244                         sipx->sipx_addr.x_port = fport;
  245                         if (ia == NULL)
  246                                 ia = ipx_iaonnetof(&sipx->sipx_addr);
  247                         if (ia == NULL)
  248                                 ia = ipx_ifaddr;
  249                         if (ia == NULL)
  250                                 return (EADDRNOTAVAIL);
  251                 }
  252                 ipxp->ipxp_laddr.x_host = satoipx_addr(ia->ia_addr).x_host;
  253         }
  254         if (ipx_pcblookup(&sipx->sipx_addr, ipxp->ipxp_lport, 0))
  255                 return (EADDRINUSE);
  256         if (ipxp->ipxp_lport == 0)
  257                 ipx_pcbbind(ipxp, (struct sockaddr *)NULL, td);
  258 
  259         /* XXX just leave it zero if we can't find a route */
  260 
  261         ipxp->ipxp_faddr = sipx->sipx_addr;
  262         /* Includes ipxp->ipxp_fport = sipx->sipx_port; */
  263         return (0);
  264 }
  265 
  266 void
  267 ipx_pcbdisconnect(ipxp)
  268         struct ipxpcb *ipxp;
  269 {
  270 
  271         IPX_LIST_LOCK_ASSERT();
  272         IPX_LOCK_ASSERT(ipxp);
  273 
  274         ipxp->ipxp_faddr = zeroipx_addr;
  275         if (ipxp->ipxp_socket->so_state & SS_NOFDREF)
  276                 ipx_pcbdetach(ipxp);
  277 }
  278 
  279 void
  280 ipx_pcbdetach(ipxp)
  281         struct ipxpcb *ipxp;
  282 {
  283         struct socket *so = ipxp->ipxp_socket;
  284 
  285         IPX_LIST_LOCK_ASSERT();
  286         IPX_LOCK_ASSERT(ipxp);
  287 
  288         ACCEPT_LOCK();
  289         SOCK_LOCK(so);
  290         so->so_pcb = NULL;
  291         sotryfree(so);
  292         if (ipxp->ipxp_route.ro_rt != NULL)
  293                 RTFREE(ipxp->ipxp_route.ro_rt);
  294         LIST_REMOVE(ipxp, ipxp_list);
  295         IPX_LOCK_DESTROY(ipxp);
  296         FREE(ipxp, M_PCB);
  297 }
  298 
  299 void
  300 ipx_setsockaddr(ipxp, nam)
  301         register struct ipxpcb *ipxp;
  302         struct sockaddr **nam;
  303 {
  304         struct sockaddr_ipx *sipx, ssipx;
  305 
  306         sipx = &ssipx;
  307         bzero((caddr_t)sipx, sizeof(*sipx));
  308         sipx->sipx_len = sizeof(*sipx);
  309         sipx->sipx_family = AF_IPX;
  310         IPX_LOCK(ipxp);
  311         sipx->sipx_addr = ipxp->ipxp_laddr;
  312         IPX_UNLOCK(ipxp);
  313         *nam = sodupsockaddr((struct sockaddr *)sipx, M_WAITOK);
  314 }
  315 
  316 void
  317 ipx_setpeeraddr(ipxp, nam)
  318         register struct ipxpcb *ipxp;
  319         struct sockaddr **nam;
  320 {
  321         struct sockaddr_ipx *sipx, ssipx;
  322 
  323         sipx = &ssipx;
  324         bzero(sipx, sizeof(*sipx));
  325         sipx->sipx_len = sizeof(*sipx);
  326         sipx->sipx_family = AF_IPX;
  327         IPX_LOCK(ipxp);
  328         sipx->sipx_addr = ipxp->ipxp_faddr;
  329         IPX_UNLOCK(ipxp);
  330         *nam = sodupsockaddr((struct sockaddr *)sipx, M_WAITOK);
  331 }
  332 
  333 struct ipxpcb *
  334 ipx_pcblookup(faddr, lport, wildp)
  335         struct ipx_addr *faddr;
  336         u_short lport;
  337         int wildp;
  338 {
  339         register struct ipxpcb *ipxp, *match = NULL;
  340         int matchwild = 3, wildcard;
  341         u_short fport;
  342 
  343         IPX_LIST_LOCK_ASSERT();
  344 
  345         fport = faddr->x_port;
  346         LIST_FOREACH(ipxp, &ipxpcb_list, ipxp_list) {
  347                 if (ipxp->ipxp_lport != lport)
  348                         continue;
  349                 wildcard = 0;
  350                 if (ipx_nullhost(ipxp->ipxp_faddr)) {
  351                         if (!ipx_nullhost(*faddr))
  352                                 wildcard++;
  353                 } else {
  354                         if (ipx_nullhost(*faddr))
  355                                 wildcard++;
  356                         else {
  357                                 if (!ipx_hosteq(ipxp->ipxp_faddr, *faddr))
  358                                         continue;
  359                                 if (ipxp->ipxp_fport != fport) {
  360                                         if (ipxp->ipxp_fport != 0)
  361                                                 continue;
  362                                         else
  363                                                 wildcard++;
  364                                 }
  365                         }
  366                 }
  367                 if (wildcard && wildp == 0)
  368                         continue;
  369                 if (wildcard < matchwild) {
  370                         match = ipxp;
  371                         matchwild = wildcard;
  372                         if (wildcard == 0)
  373                                 break;
  374                 }
  375         }
  376         return (match);
  377 }

Cache object: f189a82b3a366b8d3717fed13a57245f


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