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) 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.c
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD: releng/5.3/sys/netipx/ipx.c 136588 2004-10-16 08:43:07Z cvs2svn $");
   39 
   40 #include <sys/param.h>
   41 #include <sys/kernel.h>
   42 #include <sys/systm.h>
   43 #include <sys/malloc.h>
   44 #include <sys/sockio.h>
   45 #include <sys/socket.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_var.h>
   53 
   54 NET_NEEDS_GIANT("ipx");
   55 
   56 /*
   57  * XXXRW: Requires synchronization.
   58  */
   59 struct ipx_ifaddr *ipx_ifaddr;
   60 
   61 static  void ipx_ifscrub(struct ifnet *ifp, struct ipx_ifaddr *ia);
   62 static  int ipx_ifinit(struct ifnet *ifp, struct ipx_ifaddr *ia,
   63                        struct sockaddr_ipx *sipx, int scrub);
   64 
   65 /*
   66  * Generic internet control operations (ioctl's).
   67  */
   68 int
   69 ipx_control(so, cmd, data, ifp, td)
   70         struct socket *so;
   71         u_long cmd;
   72         caddr_t data;
   73         register struct ifnet *ifp;
   74         struct thread *td;
   75 {
   76         register struct ifreq *ifr = (struct ifreq *)data;
   77         register struct ipx_aliasreq *ifra = (struct ipx_aliasreq *)data;
   78         register struct ipx_ifaddr *ia;
   79         struct ifaddr *ifa;
   80         struct ipx_ifaddr *oia;
   81         int dstIsNew, hostIsNew;
   82         int error = 0;
   83 
   84         /*
   85          * Find address for this interface, if it exists.
   86          */
   87         if (ifp == NULL)
   88                 return (EADDRNOTAVAIL);
   89         for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next)
   90                 if (ia->ia_ifp == ifp)
   91                         break;
   92 
   93         switch (cmd) {
   94 
   95         case SIOCGIFADDR:
   96                 if (ia == NULL)
   97                         return (EADDRNOTAVAIL);
   98                 *(struct sockaddr_ipx *)&ifr->ifr_addr = ia->ia_addr;
   99                 return (0);
  100 
  101         case SIOCGIFBRDADDR:
  102                 if (ia == NULL)
  103                         return (EADDRNOTAVAIL);
  104                 if ((ifp->if_flags & IFF_BROADCAST) == 0)
  105                         return (EINVAL);
  106                 *(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_broadaddr;
  107                 return (0);
  108 
  109         case SIOCGIFDSTADDR:
  110                 if (ia == NULL)
  111                         return (EADDRNOTAVAIL);
  112                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  113                         return (EINVAL);
  114                 *(struct sockaddr_ipx *)&ifr->ifr_dstaddr = ia->ia_dstaddr;
  115                 return (0);
  116         }
  117 
  118         if (td && (error = suser(td)) != 0)
  119                 return (error);
  120 
  121         switch (cmd) {
  122         case SIOCAIFADDR:
  123         case SIOCDIFADDR:
  124                 if (ifra->ifra_addr.sipx_family == AF_IPX)
  125                     for (oia = ia; ia != NULL; ia = ia->ia_next) {
  126                         if (ia->ia_ifp == ifp  &&
  127                             ipx_neteq(ia->ia_addr.sipx_addr,
  128                                   ifra->ifra_addr.sipx_addr))
  129                             break;
  130                     }
  131                 if (cmd == SIOCDIFADDR && ia == NULL)
  132                         return (EADDRNOTAVAIL);
  133                 /* FALLTHROUGH */
  134 
  135         case SIOCSIFADDR:
  136         case SIOCSIFDSTADDR:
  137                 if (ia == NULL) {
  138                         oia = (struct ipx_ifaddr *)
  139                                 malloc(sizeof(*ia), M_IFADDR,
  140                                 M_WAITOK | M_ZERO);
  141                         if (oia == NULL)
  142                                 return (ENOBUFS);
  143                         if ((ia = ipx_ifaddr) != NULL) {
  144                                 for ( ; ia->ia_next != NULL; ia = ia->ia_next)
  145                                         ;
  146                                 ia->ia_next = oia;
  147                         } else
  148                                 ipx_ifaddr = oia;
  149                         ia = oia;
  150                         ifa = (struct ifaddr *)ia;
  151                         IFA_LOCK_INIT(ifa);
  152                         ifa->ifa_refcnt = 1;
  153                         TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
  154                         ia->ia_ifp = ifp;
  155                         ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
  156 
  157                         ifa->ifa_netmask = (struct sockaddr *)&ipx_netmask;
  158 
  159                         ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
  160                         if (ifp->if_flags & IFF_BROADCAST) {
  161                                 ia->ia_broadaddr.sipx_family = AF_IPX;
  162                                 ia->ia_broadaddr.sipx_len = sizeof(ia->ia_addr);
  163                                 ia->ia_broadaddr.sipx_addr.x_host = ipx_broadhost;
  164                         }
  165                 }
  166         }
  167 
  168         switch (cmd) {
  169 
  170         case SIOCSIFDSTADDR:
  171                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  172                         return (EINVAL);
  173                 if (ia->ia_flags & IFA_ROUTE) {
  174                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  175                         ia->ia_flags &= ~IFA_ROUTE;
  176                 }
  177                 if (ifp->if_ioctl) {
  178                         error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, (void *)ia);
  179                         if (error)
  180                                 return (error);
  181                 }
  182                 *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr;
  183                 return (0);
  184 
  185         case SIOCSIFADDR:
  186                 return (ipx_ifinit(ifp, ia,
  187                                 (struct sockaddr_ipx *)&ifr->ifr_addr, 1));
  188 
  189         case SIOCDIFADDR:
  190                 ipx_ifscrub(ifp, ia);
  191                 ifa = (struct ifaddr *)ia;
  192                 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
  193                 oia = ia;
  194                 if (oia == (ia = ipx_ifaddr)) {
  195                         ipx_ifaddr = ia->ia_next;
  196                 } else {
  197                         while (ia->ia_next && (ia->ia_next != oia)) {
  198                                 ia = ia->ia_next;
  199                         }
  200                         if (ia->ia_next)
  201                             ia->ia_next = oia->ia_next;
  202                         else
  203                                 printf("Didn't unlink ipxifadr from list\n");
  204                 }
  205                 IFAFREE((&oia->ia_ifa));
  206                 return (0);
  207         
  208         case SIOCAIFADDR:
  209                 dstIsNew = 0;
  210                 hostIsNew = 1;
  211                 if (ia->ia_addr.sipx_family == AF_IPX) {
  212                         if (ifra->ifra_addr.sipx_len == 0) {
  213                                 ifra->ifra_addr = ia->ia_addr;
  214                                 hostIsNew = 0;
  215                         } else if (ipx_neteq(ifra->ifra_addr.sipx_addr,
  216                                          ia->ia_addr.sipx_addr))
  217                                 hostIsNew = 0;
  218                 }
  219                 if ((ifp->if_flags & IFF_POINTOPOINT) &&
  220                     (ifra->ifra_dstaddr.sipx_family == AF_IPX)) {
  221                         if (hostIsNew == 0)
  222                                 ipx_ifscrub(ifp, ia);
  223                         ia->ia_dstaddr = ifra->ifra_dstaddr;
  224                         dstIsNew  = 1;
  225                 }
  226                 if (ifra->ifra_addr.sipx_family == AF_IPX &&
  227                                             (hostIsNew || dstIsNew))
  228                         error = ipx_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  229                 return (error);
  230 
  231         default:
  232                 if (ifp->if_ioctl == NULL)
  233                         return (EOPNOTSUPP);
  234                 return ((*ifp->if_ioctl)(ifp, cmd, data));
  235         }
  236 }
  237 
  238 /*
  239 * Delete any previous route for an old address.
  240 */
  241 static void
  242 ipx_ifscrub(ifp, ia)
  243         register struct ifnet *ifp;
  244         register struct ipx_ifaddr *ia; 
  245 {
  246         if (ia->ia_flags & IFA_ROUTE) {
  247                 if (ifp->if_flags & IFF_POINTOPOINT) {
  248                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  249                 } else
  250                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
  251                 ia->ia_flags &= ~IFA_ROUTE;
  252         }
  253 }
  254 /*
  255  * Initialize an interface's internet address
  256  * and routing table entry.
  257  */
  258 static int
  259 ipx_ifinit(ifp, ia, sipx, scrub)
  260         register struct ifnet *ifp;
  261         register struct ipx_ifaddr *ia;
  262         register struct sockaddr_ipx *sipx;
  263         int scrub;
  264 {
  265         struct sockaddr_ipx oldaddr;
  266         int s = splimp(), error;
  267 
  268         /*
  269          * Set up new addresses.
  270          */
  271         oldaddr = ia->ia_addr;
  272         ia->ia_addr = *sipx;
  273 
  274         /*
  275          * The convention we shall adopt for naming is that
  276          * a supplied address of zero means that "we don't care".
  277          * Use the MAC address of the interface. If it is an
  278          * interface without a MAC address, like a serial line, the
  279          * address must be supplied.
  280          *
  281          * Give the interface a chance to initialize
  282          * if this is its first address,
  283          * and to validate the address if necessary.
  284          */
  285         if (ifp->if_ioctl != NULL &&
  286             (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (void *)ia))) {
  287                 ia->ia_addr = oldaddr;
  288                 splx(s);
  289                 return (error);
  290         }
  291         splx(s);
  292         ia->ia_ifa.ifa_metric = ifp->if_metric;
  293         /*
  294          * Add route for the network.
  295          */
  296         if (scrub) {
  297                 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
  298                 ipx_ifscrub(ifp, ia);
  299                 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  300         }
  301         if (ifp->if_flags & IFF_POINTOPOINT)
  302                 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  303         else {
  304                 ia->ia_broadaddr.sipx_addr.x_net = ia->ia_addr.sipx_addr.x_net;
  305                 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
  306         }
  307         ia->ia_flags |= IFA_ROUTE;
  308         return (0);
  309 }
  310 
  311 /*
  312  * Return address info for specified internet network.
  313  */
  314 struct ipx_ifaddr *
  315 ipx_iaonnetof(dst)
  316         register struct ipx_addr *dst;
  317 {
  318         register struct ipx_ifaddr *ia;
  319         register struct ipx_addr *compare;
  320         register struct ifnet *ifp;
  321         struct ipx_ifaddr *ia_maybe = NULL;
  322         union ipx_net net = dst->x_net;
  323 
  324         for (ia = ipx_ifaddr; ia != NULL; ia = ia->ia_next) {
  325                 if ((ifp = ia->ia_ifp) != NULL) {
  326                         if (ifp->if_flags & IFF_POINTOPOINT) {
  327                                 compare = &satoipx_addr(ia->ia_dstaddr);
  328                                 if (ipx_hosteq(*dst, *compare))
  329                                         return (ia);
  330                                 if (ipx_neteqnn(net, ia->ia_addr.sipx_addr.x_net))
  331                                         ia_maybe = ia;
  332                         } else {
  333                                 if (ipx_neteqnn(net, ia->ia_addr.sipx_addr.x_net))
  334                                         return (ia);
  335                         }
  336                 }
  337         }
  338         return (ia_maybe);
  339 }
  340 
  341 
  342 void
  343 ipx_printhost(addr)
  344 register struct ipx_addr *addr;
  345 {
  346         u_short port;
  347         struct ipx_addr work = *addr;
  348         register char *p; register u_char *q;
  349         register char *net = "", *host = "";
  350         char cport[10], chost[15], cnet[15];
  351 
  352         port = ntohs(work.x_port);
  353 
  354         if (ipx_nullnet(work) && ipx_nullhost(work)) {
  355 
  356                 if (port)
  357                         printf("*.%x", port);
  358                 else
  359                         printf("*.*");
  360 
  361                 return;
  362         }
  363 
  364         if (ipx_wildnet(work))
  365                 net = "any";
  366         else if (ipx_nullnet(work))
  367                 net = "*";
  368         else {
  369                 q = work.x_net.c_net;
  370                 snprintf(cnet, sizeof(cnet), "%x%x%x%x",
  371                         q[0], q[1], q[2], q[3]);
  372                 for (p = cnet; *p == '' && p < cnet + 8; p++)
  373                         continue;
  374                 net = p;
  375         }
  376 
  377         if (ipx_wildhost(work))
  378                 host = "any";
  379         else if (ipx_nullhost(work))
  380                 host = "*";
  381         else {
  382                 q = work.x_host.c_host;
  383                 snprintf(chost, sizeof(chost), "%x%x%x%x%x%x",
  384                         q[0], q[1], q[2], q[3], q[4], q[5]);
  385                 for (p = chost; *p == '' && p < chost + 12; p++)
  386                         continue;
  387                 host = p;
  388         }
  389 
  390         if (port) {
  391                 if (strcmp(host, "*") == 0) {
  392                         host = "";
  393                         snprintf(cport, sizeof(cport), "%x", port);
  394                 } else
  395                         snprintf(cport, sizeof(cport), ".%x", port);
  396         } else
  397                 *cport = 0;
  398 
  399         printf("%s.%s%s", net, host, cport);
  400 }

Cache object: 4864f6908b526b086a8a27d7870d0c00


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