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

Cache object: 88d3b4676444c92bfbcb7597e7bf461a


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