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.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.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 4. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * Copyright (c) 1995, Mike Mitchell
   30  *
   31  * Redistribution and use in source and binary forms, with or without
   32  * modification, are permitted provided that the following conditions
   33  * are met:
   34  * 1. Redistributions of source code must retain the above copyright
   35  *    notice, this list of conditions and the following disclaimer.
   36  * 2. Redistributions in binary form must reproduce the above copyright
   37  *    notice, this list of conditions and the following disclaimer in the
   38  *    documentation and/or other materials provided with the distribution.
   39  * 3. All advertising materials mentioning features or use of this software
   40  *    must display the following acknowledgement:
   41  *      This product includes software developed by the University of
   42  *      California, Berkeley and its contributors.
   43  * 4. Neither the name of the University nor the names of its contributors
   44  *    may be used to endorse or promote products derived from this software
   45  *    without specific prior written permission.
   46  *
   47  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   57  * SUCH DAMAGE.
   58  *
   59  *      @(#)ipx.c
   60  */
   61 
   62 #include <sys/cdefs.h>
   63 __FBSDID("$FreeBSD$");
   64 
   65 #include <sys/param.h>
   66 #include <sys/kernel.h>
   67 #include <sys/systm.h>
   68 #include <sys/malloc.h>
   69 #include <sys/priv.h>
   70 #include <sys/sockio.h>
   71 #include <sys/socket.h>
   72 
   73 #include <net/if.h>
   74 #include <net/route.h>
   75 
   76 #include <netipx/ipx.h>
   77 #include <netipx/ipx_if.h>
   78 #include <netipx/ipx_var.h>
   79 
   80 /*
   81  * XXXRW: Requires synchronization.
   82  */
   83 struct ipx_ifaddr *ipx_ifaddr;
   84 
   85 static  void ipx_ifscrub(struct ifnet *ifp, struct ipx_ifaddr *ia);
   86 static  int ipx_ifinit(struct ifnet *ifp, struct ipx_ifaddr *ia,
   87                        struct sockaddr_ipx *sipx, int scrub);
   88 
   89 /*
   90  * Generic internet control operations (ioctl's).
   91  */
   92 int
   93 ipx_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
   94     struct thread *td)
   95 {
   96         struct ifreq *ifr = (struct ifreq *)data;
   97         struct ipx_aliasreq *ifra = (struct ipx_aliasreq *)data;
   98         struct ipx_ifaddr *ia;
   99         struct ifaddr *ifa;
  100         struct ipx_ifaddr *oia;
  101         int dstIsNew, hostIsNew;
  102         int error = 0;
  103 
  104         /*
  105          * Find address for this interface, if it exists.
  106          */
  107         if (ifp == NULL)
  108                 return (EADDRNOTAVAIL);
  109         for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next)
  110                 if (ia->ia_ifp == ifp)
  111                         break;
  112 
  113         switch (cmd) {
  114 
  115         case SIOCGIFADDR:
  116                 if (ia == NULL)
  117                         return (EADDRNOTAVAIL);
  118                 *(struct sockaddr_ipx *)&ifr->ifr_addr = ia->ia_addr;
  119                 return (0);
  120 
  121         case SIOCGIFBRDADDR:
  122                 if (ia == NULL)
  123                         return (EADDRNOTAVAIL);
  124                 if ((ifp->if_flags & IFF_BROADCAST) == 0)
  125                         return (EINVAL);
  126                 *(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
  127                 return (0);
  128 
  129         case SIOCGIFDSTADDR:
  130                 if (ia == NULL)
  131                         return (EADDRNOTAVAIL);
  132                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  133                         return (EINVAL);
  134                 *(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
  135                 return (0);
  136         }
  137 
  138         if (td && (error = suser(td)) != 0)
  139                 return (error);
  140 
  141         switch (cmd) {
  142         case SIOCAIFADDR:
  143         case SIOCDIFADDR:
  144                 if (ifra->ifra_addr.sipx_family == AF_IPX)
  145                     for (oia = ia; ia != NULL; ia = ia->ia_next) {
  146                         if (ia->ia_ifp == ifp  &&
  147                             ipx_neteq(ia->ia_addr.sipx_addr,
  148                                   ifra->ifra_addr.sipx_addr))
  149                             break;
  150                     }
  151                 if (cmd == SIOCDIFADDR && ia == NULL)
  152                         return (EADDRNOTAVAIL);
  153                 /* FALLTHROUGH */
  154 
  155         case SIOCSIFADDR:
  156         case SIOCSIFDSTADDR:
  157                 if (ia == NULL) {
  158                         oia = (struct ipx_ifaddr *)
  159                                 malloc(sizeof(*ia), M_IFADDR,
  160                                 M_WAITOK | M_ZERO);
  161                         if (oia == NULL)
  162                                 return (ENOBUFS);
  163                         if ((ia = ipx_ifaddr) != NULL) {
  164                                 for ( ; ia->ia_next != NULL; ia = ia->ia_next)
  165                                         ;
  166                                 ia->ia_next = oia;
  167                         } else
  168                                 ipx_ifaddr = oia;
  169                         ia = oia;
  170                         ifa = (struct ifaddr *)ia;
  171                         IFA_LOCK_INIT(ifa);
  172                         ifa->ifa_refcnt = 1;
  173                         TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
  174                         ia->ia_ifp = ifp;
  175                         ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
  176 
  177                         ifa->ifa_netmask = (struct sockaddr *)&ipx_netmask;
  178 
  179                         ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
  180                         if (ifp->if_flags & IFF_BROADCAST) {
  181                                 ia->ia_broadaddr.sipx_family = AF_IPX;
  182                                 ia->ia_broadaddr.sipx_len = sizeof(ia->ia_addr);
  183                                 ia->ia_broadaddr.sipx_addr.x_host = ipx_broadhost;
  184                         }
  185                 }
  186         }
  187 
  188         switch (cmd) {
  189 
  190         case SIOCSIFDSTADDR:
  191                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  192                         return (EINVAL);
  193                 if (ia->ia_flags & IFA_ROUTE) {
  194                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  195                         ia->ia_flags &= ~IFA_ROUTE;
  196                 }
  197                 if (ifp->if_ioctl) {
  198                         error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, (void *)ia);
  199                         if (error)
  200                                 return (error);
  201                 }
  202                 *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
  203                 return (0);
  204 
  205         case SIOCSIFADDR:
  206                 return (ipx_ifinit(ifp, ia,
  207                                 (struct sockaddr_ipx *)&ifr->ifr_addr, 1));
  208 
  209         case SIOCDIFADDR:
  210                 ipx_ifscrub(ifp, ia);
  211                 ifa = (struct ifaddr *)ia;
  212                 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
  213                 oia = ia;
  214                 if (oia == (ia = ipx_ifaddr)) {
  215                         ipx_ifaddr = ia->ia_next;
  216                 } else {
  217                         while (ia->ia_next && (ia->ia_next != oia)) {
  218                                 ia = ia->ia_next;
  219                         }
  220                         if (ia->ia_next)
  221                             ia->ia_next = oia->ia_next;
  222                         else
  223                                 printf("Didn't unlink ipxifadr from list\n");
  224                 }
  225                 IFAFREE((&oia->ia_ifa));
  226                 return (0);
  227 
  228         case SIOCAIFADDR:
  229                 dstIsNew = 0;
  230                 hostIsNew = 1;
  231                 if (ia->ia_addr.sipx_family == AF_IPX) {
  232                         if (ifra->ifra_addr.sipx_len == 0) {
  233                                 ifra->ifra_addr = ia->ia_addr;
  234                                 hostIsNew = 0;
  235                         } else if (ipx_neteq(ifra->ifra_addr.sipx_addr,
  236                                          ia->ia_addr.sipx_addr))
  237                                 hostIsNew = 0;
  238                 }
  239                 if ((ifp->if_flags & IFF_POINTOPOINT) &&
  240                     (ifra->ifra_dstaddr.sipx_family == AF_IPX)) {
  241                         if (hostIsNew == 0)
  242                                 ipx_ifscrub(ifp, ia);
  243                         ia->ia_dstaddr = ifra->ifra_dstaddr;
  244                         dstIsNew  = 1;
  245                 }
  246                 if (ifra->ifra_addr.sipx_family == AF_IPX &&
  247                                             (hostIsNew || dstIsNew))
  248                         error = ipx_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  249                 return (error);
  250 
  251         default:
  252                 if (ifp->if_ioctl == NULL)
  253                         return (EOPNOTSUPP);
  254                 return ((*ifp->if_ioctl)(ifp, cmd, data));
  255         }
  256 }
  257 
  258 /*
  259 * Delete any previous route for an old address.
  260 */
  261 static void
  262 ipx_ifscrub(struct ifnet *ifp, struct ipx_ifaddr *ia)
  263 {
  264 
  265         if (ia->ia_flags & IFA_ROUTE) {
  266                 if (ifp->if_flags & IFF_POINTOPOINT) {
  267                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  268                 } else
  269                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
  270                 ia->ia_flags &= ~IFA_ROUTE;
  271         }
  272 }
  273 /*
  274  * Initialize an interface's internet address
  275  * and routing table entry.
  276  */
  277 static int
  278 ipx_ifinit(struct ifnet *ifp, struct ipx_ifaddr *ia,
  279     struct sockaddr_ipx *sipx, int scrub)
  280 {
  281         struct sockaddr_ipx oldaddr;
  282         int s = splimp(), error;
  283 
  284         /*
  285          * Set up new addresses.
  286          */
  287         oldaddr = ia->ia_addr;
  288         ia->ia_addr = *sipx;
  289 
  290         /*
  291          * The convention we shall adopt for naming is that
  292          * a supplied address of zero means that "we don't care".
  293          * Use the MAC address of the interface. If it is an
  294          * interface without a MAC address, like a serial line, the
  295          * address must be supplied.
  296          *
  297          * Give the interface a chance to initialize
  298          * if this is its first address,
  299          * and to validate the address if necessary.
  300          */
  301         if (ifp->if_ioctl != NULL &&
  302             (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (void *)ia))) {
  303                 ia->ia_addr = oldaddr;
  304                 splx(s);
  305                 return (error);
  306         }
  307         splx(s);
  308         ia->ia_ifa.ifa_metric = ifp->if_metric;
  309         /*
  310          * Add route for the network.
  311          */
  312         if (scrub) {
  313                 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
  314                 ipx_ifscrub(ifp, ia);
  315                 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  316         }
  317         if (ifp->if_flags & IFF_POINTOPOINT)
  318                 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  319         else {
  320                 ia->ia_broadaddr.sipx_addr.x_net = ia->ia_addr.sipx_addr.x_net;
  321                 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
  322         }
  323         ia->ia_flags |= IFA_ROUTE;
  324         return (0);
  325 }
  326 
  327 /*
  328  * Return address info for specified internet network.
  329  */
  330 struct ipx_ifaddr *
  331 ipx_iaonnetof(struct ipx_addr *dst)
  332 {
  333         struct ipx_ifaddr *ia;
  334         struct ipx_addr *compare;
  335         struct ifnet *ifp;
  336         struct ipx_ifaddr *ia_maybe = NULL;
  337         union ipx_net net = dst->x_net;
  338 
  339         for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) {
  340                 if ((ifp = ia->ia_ifp) != NULL) {
  341                         if (ifp->if_flags & IFF_POINTOPOINT) {
  342                                 compare = &satoipx_addr(ia->ia_dstaddr);
  343                                 if (ipx_hosteq(*dst, *compare))
  344                                         return (ia);
  345                                 if (ipx_neteqnn(net, ia->ia_addr.sipx_addr.x_net))
  346                                         ia_maybe = ia;
  347                         } else {
  348                                 if (ipx_neteqnn(net, ia->ia_addr.sipx_addr.x_net))
  349                                         return (ia);
  350                         }
  351                 }
  352         }
  353         return (ia_maybe);
  354 }
  355 
  356 
  357 void
  358 ipx_printhost(struct ipx_addr *addr)
  359 {
  360         u_short port;
  361         struct ipx_addr work = *addr;
  362         char *p; u_char *q;
  363         char *net = "", *host = "";
  364         char cport[10], chost[15], cnet[15];
  365 
  366         port = ntohs(work.x_port);
  367 
  368         if (ipx_nullnet(work) && ipx_nullhost(work)) {
  369 
  370                 if (port)
  371                         printf("*.%x", port);
  372                 else
  373                         printf("*.*");
  374 
  375                 return;
  376         }
  377 
  378         if (ipx_wildnet(work))
  379                 net = "any";
  380         else if (ipx_nullnet(work))
  381                 net = "*";
  382         else {
  383                 q = work.x_net.c_net;
  384                 snprintf(cnet, sizeof(cnet), "%x%x%x%x",
  385                         q[0], q[1], q[2], q[3]);
  386                 for (p = cnet; *p == '' && p < cnet + 8; p++)
  387                         continue;
  388                 net = p;
  389         }
  390 
  391         if (ipx_wildhost(work))
  392                 host = "any";
  393         else if (ipx_nullhost(work))
  394                 host = "*";
  395         else {
  396                 q = work.x_host.c_host;
  397                 snprintf(chost, sizeof(chost), "%x%x%x%x%x%x",
  398                         q[0], q[1], q[2], q[3], q[4], q[5]);
  399                 for (p = chost; *p == '' && p < chost + 12; p++)
  400                         continue;
  401                 host = p;
  402         }
  403 
  404         if (port) {
  405                 if (strcmp(host, "*") == 0) {
  406                         host = "";
  407                         snprintf(cport, sizeof(cport), "%x", port);
  408                 } else
  409                         snprintf(cport, sizeof(cport), ".%x", port);
  410         } else
  411                 *cport = 0;
  412 
  413         printf("%s.%s%s", net, host, cport);
  414 }

Cache object: c30aeb3ffaf6f65de43552aade988aa3


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