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: src/sys/netipx/ipx_pcb.c,v 1.5.4.2 1999/09/05 08:19:01 peter Exp $
   37  */
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/mbuf.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 struct  ipx_addr zeroipx_addr;
   55 
   56 int
   57 ipx_pcballoc(so, head)
   58         struct socket *so;
   59         struct ipxpcb *head;
   60 {
   61         struct mbuf *m;
   62         register struct ipxpcb *ipxp;
   63 
   64         m = m_getclr(M_DONTWAIT, MT_PCB);
   65         if (m == NULL)
   66                 return (ENOBUFS);
   67         ipxp = mtod(m, struct ipxpcb *);
   68         ipxp->ipxp_socket = so;
   69         insque(ipxp, head);
   70         so->so_pcb = (caddr_t)ipxp;
   71         return (0);
   72 }
   73         
   74 int
   75 ipx_pcbbind(ipxp, nam)
   76         register struct ipxpcb *ipxp;
   77         struct mbuf *nam;
   78 {
   79         register struct sockaddr_ipx *sipx;
   80         u_short lport = 0;
   81 
   82         if (ipxp->ipxp_lport || !ipx_nullhost(ipxp->ipxp_laddr))
   83                 return (EINVAL);
   84         if (nam == NULL)
   85                 goto noname;
   86         sipx = mtod(nam, struct sockaddr_ipx *);
   87         if (nam->m_len != sizeof(*sipx))
   88                 return (EINVAL);
   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 
  101                 if (aport < IPXPORT_RESERVED &&
  102                     (ipxp->ipxp_socket->so_state & SS_PRIV) == 0)
  103                         return (EACCES);
  104                 if (ipx_pcblookup(&zeroipx_addr, lport, 0))
  105                         return (EADDRINUSE);
  106         }
  107         ipxp->ipxp_laddr = sipx->sipx_addr;
  108 noname:
  109         if (lport == 0)
  110                 do {
  111                         ipxpcb.ipxp_lport++;
  112                         if ((ipxpcb.ipxp_lport < IPXPORT_RESERVED) ||
  113                             (ipxpcb.ipxp_lport >= IPXPORT_WELLKNOWN))
  114                                 ipxpcb.ipxp_lport = IPXPORT_RESERVED;
  115                         lport = htons(ipxpcb.ipxp_lport);
  116                 } while (ipx_pcblookup(&zeroipx_addr, lport, 0));
  117         ipxp->ipxp_lport = lport;
  118         return (0);
  119 }
  120 
  121 /*
  122  * Connect from a socket to a specified address.
  123  * Both address and port must be specified in argument sipx.
  124  * If don't have a local address for this socket yet,
  125  * then pick one.
  126  */
  127 int
  128 ipx_pcbconnect(ipxp, nam)
  129         struct ipxpcb *ipxp;
  130         struct mbuf *nam;
  131 {
  132         struct ipx_ifaddr *ia;
  133         register struct sockaddr_ipx *sipx = mtod(nam, struct sockaddr_ipx *);
  134         register struct ipx_addr *dst;
  135         register struct route *ro;
  136         struct ifnet *ifp;
  137 
  138         ia = NULL;
  139 
  140         if (nam->m_len != sizeof(*sipx))
  141                 return (EINVAL);
  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                         ipxp->ipxp_laddr.x_net = ipx_zeronet;
  174                 }
  175         }/* else cached route is ok; do nothing */
  176         ipxp->ipxp_lastdst = sipx->sipx_addr;
  177         if ((ipxp->ipxp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
  178             (ro->ro_rt == NULL || ro->ro_rt->rt_ifp == NULL)) {
  179                     /* No route yet, so try to acquire one */
  180                     ro->ro_dst.sa_family = AF_IPX;
  181                     ro->ro_dst.sa_len = sizeof(ro->ro_dst);
  182                     *dst = sipx->sipx_addr;
  183                     dst->x_port = 0;
  184                     rtalloc(ro);
  185         }
  186         if (ipx_neteqnn(ipxp->ipxp_laddr.x_net, ipx_zeronet)) {
  187                 /* 
  188                  * If route is known or can be allocated now,
  189                  * our src addr is taken from the i/f, else punt.
  190                  */
  191 
  192                 /*
  193                  * If we found a route, use the address
  194                  * corresponding to the outgoing interface
  195                  */
  196                 if (ro->ro_rt != NULL && (ifp = ro->ro_rt->rt_ifp) != NULL)
  197                         for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next)
  198                                 if (ia->ia_ifp == ifp)
  199                                         break;
  200                 if (ia == NULL) {
  201                         u_short fport = sipx->sipx_addr.x_port;
  202                         sipx->sipx_addr.x_port = 0;
  203                         ia = (struct ipx_ifaddr *)
  204                                 ifa_ifwithdstaddr((struct sockaddr *)sipx);
  205                         sipx->sipx_addr.x_port = fport;
  206                         if (ia == NULL)
  207                                 ia = ipx_iaonnetof(&sipx->sipx_addr);
  208                         if (ia == NULL)
  209                                 ia = ipx_ifaddr;
  210                         if (ia == NULL)
  211                                 return (EADDRNOTAVAIL);
  212                 }
  213                 ipxp->ipxp_laddr.x_net = satoipx_addr(ia->ia_addr).x_net;
  214         }
  215         if (ipx_nullhost(ipxp->ipxp_laddr)) {
  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_host = satoipx_addr(ia->ia_addr).x_host;
  243         }
  244         if (ipx_pcblookup(&sipx->sipx_addr, ipxp->ipxp_lport, 0))
  245                 return (EADDRINUSE);
  246         if (ipxp->ipxp_lport == 0)
  247                 ipx_pcbbind(ipxp, (struct mbuf *)NULL);
  248 
  249         /* XXX just leave it zero if we can't find a route */
  250 
  251         ipxp->ipxp_faddr = sipx->sipx_addr;
  252         /* Includes ipxp->ipxp_fport = sipx->sipx_port; */
  253         return (0);
  254 }
  255 
  256 void
  257 ipx_pcbdisconnect(ipxp)
  258         struct ipxpcb *ipxp;
  259 {
  260 
  261         ipxp->ipxp_faddr = zeroipx_addr;
  262         if (ipxp->ipxp_socket->so_state & SS_NOFDREF)
  263                 ipx_pcbdetach(ipxp);
  264 }
  265 
  266 void
  267 ipx_pcbdetach(ipxp)
  268         struct ipxpcb *ipxp;
  269 {
  270         struct socket *so = ipxp->ipxp_socket;
  271 
  272         so->so_pcb = 0;
  273         sofree(so);
  274         if (ipxp->ipxp_route.ro_rt != NULL)
  275                 rtfree(ipxp->ipxp_route.ro_rt);
  276         remque(ipxp);
  277         m_free(dtom(ipxp));
  278 }
  279 
  280 void
  281 ipx_setsockaddr(ipxp, nam)
  282         register struct ipxpcb *ipxp;
  283         struct mbuf *nam;
  284 {
  285         register struct sockaddr_ipx *sipx = mtod(nam, struct sockaddr_ipx *);
  286         
  287         nam->m_len = sizeof(*sipx);
  288         sipx = mtod(nam, struct sockaddr_ipx *);
  289         bzero((caddr_t)sipx, sizeof(*sipx));
  290         sipx->sipx_len = sizeof(*sipx);
  291         sipx->sipx_family = AF_IPX;
  292         sipx->sipx_addr = ipxp->ipxp_laddr;
  293 }
  294 
  295 void
  296 ipx_setpeeraddr(ipxp, nam)
  297         register struct ipxpcb *ipxp;
  298         struct mbuf *nam;
  299 {
  300         register struct sockaddr_ipx *sipx = mtod(nam, struct sockaddr_ipx *);
  301         
  302         nam->m_len = sizeof(*sipx);
  303         sipx = mtod(nam, struct sockaddr_ipx *);
  304         bzero((caddr_t)sipx, sizeof(*sipx));
  305         sipx->sipx_len = sizeof(*sipx);
  306         sipx->sipx_family = AF_IPX;
  307         sipx->sipx_addr = ipxp->ipxp_faddr;
  308 }
  309 
  310 /*
  311  * Pass some notification to all connections of a protocol
  312  * associated with address dst.  Call the
  313  * protocol specific routine to handle each connection.
  314  * Also pass an extra paramter via the ipxpcb. (which may in fact
  315  * be a parameter list!)
  316  */
  317 void
  318 ipx_pcbnotify(dst, errno, notify, param)
  319         register struct ipx_addr *dst;
  320         int errno;
  321         void (*notify)(struct ipxpcb *);
  322         long param;
  323 {
  324         register struct ipxpcb *ipxp, *oinp;
  325         int s = splimp();
  326 
  327         for (ipxp = (&ipxpcb)->ipxp_next; ipxp != (&ipxpcb);) {
  328                 if (!ipx_hosteq(*dst,ipxp->ipxp_faddr)) {
  329         next:
  330                         ipxp = ipxp->ipxp_next;
  331                         continue;
  332                 }
  333                 if (ipxp->ipxp_socket == 0)
  334                         goto next;
  335                 if (errno) 
  336                         ipxp->ipxp_socket->so_error = errno;
  337                 oinp = ipxp;
  338                 ipxp = ipxp->ipxp_next;
  339                 oinp->ipxp_notify_param = param;
  340                 (*notify)(oinp);
  341         }
  342         splx(s);
  343 }
  344 
  345 #ifdef notdef
  346 /*
  347  * After a routing change, flush old routing
  348  * and allocate a (hopefully) better one.
  349  */
  350 ipx_rtchange(ipxp)
  351         struct ipxpcb *ipxp;
  352 {
  353         if (ipxp->ipxp_route.ro_rt != NULL) {
  354                 rtfree(ipxp->ipxp_route.ro_rt);
  355                 ipxp->ipxp_route.ro_rt = NULL;
  356                 /*
  357                  * A new route can be allocated the next time
  358                  * output is attempted.
  359                  */
  360         }
  361         /* SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */
  362 }
  363 #endif
  364 
  365 struct ipxpcb *
  366 ipx_pcblookup(faddr, lport, wildp)
  367         struct ipx_addr *faddr;
  368         u_short lport;
  369         int wildp;
  370 {
  371         register struct ipxpcb *ipxp, *match = 0;
  372         int matchwild = 3, wildcard;
  373         u_short fport;
  374 
  375         fport = faddr->x_port;
  376         for (ipxp = (&ipxpcb)->ipxp_next; ipxp != (&ipxpcb); ipxp = ipxp->ipxp_next) {
  377                 if (ipxp->ipxp_lport != lport)
  378                         continue;
  379                 wildcard = 0;
  380                 if (ipx_nullhost(ipxp->ipxp_faddr)) {
  381                         if (!ipx_nullhost(*faddr))
  382                                 wildcard++;
  383                 } else {
  384                         if (ipx_nullhost(*faddr))
  385                                 wildcard++;
  386                         else {
  387                                 if (!ipx_hosteq(ipxp->ipxp_faddr, *faddr))
  388                                         continue;
  389                                 if (ipxp->ipxp_fport != fport) {
  390                                         if (ipxp->ipxp_fport != 0)
  391                                                 continue;
  392                                         else
  393                                                 wildcard++;
  394                                 }
  395                         }
  396                 }
  397                 if (wildcard && wildp == 0)
  398                         continue;
  399                 if (wildcard < matchwild) {
  400                         match = ipxp;
  401                         matchwild = wildcard;
  402                         if (wildcard == 0)
  403                                 break;
  404                 }
  405         }
  406         return (match);
  407 }

Cache object: a8d046d2ea45caaec6bd8a25f56273b8


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