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

Cache object: ca316f57a3f8813dc3d3201f6ac373a7


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