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

Cache object: ccf1da4fc909e9fb74f93a35c51aec4f


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