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/netns/ns.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 /*      $NetBSD: ns.c,v 1.24 2003/08/07 16:33:45 agc Exp $      */
    2 
    3 /*
    4  * Copyright (c) 1984, 1985, 1986, 1987, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)ns.c        8.5 (Berkeley) 2/9/95
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: ns.c,v 1.24 2003/08/07 16:33:45 agc Exp $");
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/mbuf.h>
   40 #include <sys/ioctl.h>
   41 #include <sys/protosw.h>
   42 #include <sys/errno.h>
   43 #include <sys/socket.h>
   44 #include <sys/socketvar.h>
   45 #include <sys/proc.h>
   46 
   47 #include <net/if.h>
   48 #include <net/route.h>
   49 
   50 #include <netns/ns.h>
   51 #include <netns/ns_if.h>
   52 #include <netns/ns_var.h>
   53 
   54 struct ns_ifaddrhead ns_ifaddr;
   55 int ns_interfaces;
   56 
   57 /*
   58  * Generic internet control operations (ioctl's).
   59  */
   60 /* ARGSUSED */
   61 int
   62 ns_control(so, cmd, data, ifp, p)
   63         struct socket *so;
   64         u_long cmd;
   65         caddr_t data;
   66         struct ifnet *ifp;
   67         struct proc *p;
   68 {
   69         struct ifreq *ifr = (struct ifreq *)data;
   70         struct ns_ifaddr *ia = 0;
   71         struct ns_aliasreq *ifra = (struct ns_aliasreq *)data;
   72         struct sockaddr_ns oldaddr;
   73         int error = 0, dstIsNew, hostIsNew;
   74 
   75         /*
   76          * Find address for this interface, if it exists.
   77          */
   78         if (ifp)
   79                 for (ia = ns_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next)
   80                         if (ia->ia_ifp == ifp)
   81                                 break;
   82 
   83         switch (cmd) {
   84 
   85         case SIOCAIFADDR:
   86         case SIOCDIFADDR:
   87                 if (ifra->ifra_addr.sns_family == AF_NS)
   88                         for (; ia; ia = ia->ia_list.tqe_next) {
   89                                 if (ia->ia_ifp == ifp  &&
   90                                     ns_neteq(ia->ia_addr.sns_addr, ifra->ifra_addr.sns_addr))
   91                                         break;
   92                         }
   93                 if (cmd == SIOCDIFADDR && ia == 0)
   94                         return (EADDRNOTAVAIL);
   95                 /* FALLTHROUGH */
   96         case SIOCSIFADDR:
   97         case SIOCSIFDSTADDR:
   98                 if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
   99                         return (EPERM);
  100 
  101                 if (ifp == 0)
  102                         panic("ns_control");
  103                 if (ia == 0) {
  104                         MALLOC(ia, struct ns_ifaddr *, sizeof(*ia),
  105                                M_IFADDR, M_WAITOK);
  106                         if (ia == 0)
  107                                 return (ENOBUFS);
  108                         bzero((caddr_t)ia, sizeof(*ia));
  109                         TAILQ_INSERT_TAIL(&ns_ifaddr, ia, ia_list);
  110                         IFAREF((struct ifaddr *)ia);
  111                         TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
  112                             ifa_list);
  113                         IFAREF((struct ifaddr *)ia);
  114                         ia->ia_ifa.ifa_addr = snstosa(&ia->ia_addr);
  115                         ia->ia_ifa.ifa_netmask = snstosa(&ns_netmask);
  116                         ia->ia_ifa.ifa_dstaddr = snstosa(&ia->ia_dstaddr);
  117                         if (ifp->if_flags & IFF_BROADCAST) {
  118                                 ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr);
  119                                 ia->ia_broadaddr.sns_family = AF_NS;
  120                                 ia->ia_broadaddr.sns_addr.x_host = ns_broadhost;
  121                         }
  122                         ia->ia_ifp = ifp;
  123                         if ((ifp->if_flags & IFF_LOOPBACK) == 0)
  124                                 ns_interfaces++;
  125                 }
  126                 break;
  127 
  128         case SIOCGIFADDR:
  129         case SIOCGIFDSTADDR:
  130         case SIOCGIFBRDADDR:
  131                 if (ia == 0)
  132                         return (EADDRNOTAVAIL);
  133                 break;
  134         }
  135         switch (cmd) {
  136 
  137         case SIOCGIFADDR:
  138                 *satosns(&ifr->ifr_addr) = ia->ia_addr;
  139                 break;
  140 
  141         case SIOCGIFBRDADDR:
  142                 if ((ifp->if_flags & IFF_BROADCAST) == 0)
  143                         return (EINVAL);
  144                 *satosns(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
  145                 break;
  146 
  147         case SIOCGIFDSTADDR:
  148                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  149                         return (EINVAL);
  150                 *satosns(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
  151                 break;
  152 
  153         case SIOCSIFDSTADDR:
  154                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  155                         return (EINVAL);
  156                 oldaddr = ia->ia_dstaddr;
  157                 ia->ia_dstaddr = *satosns(&ifr->ifr_dstaddr);
  158                 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
  159                                         (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
  160                         ia->ia_dstaddr = oldaddr;
  161                         return (error);
  162                 }
  163                 if (ia->ia_flags & IFA_ROUTE) {
  164                         ia->ia_ifa.ifa_dstaddr = snstosa(&oldaddr);
  165                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  166                         ia->ia_ifa.ifa_dstaddr = snstosa(&ia->ia_dstaddr);
  167                         rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  168                 }
  169                 break;
  170 
  171         case SIOCSIFADDR:
  172                 return (ns_ifinit(ifp, ia, satosns(&ifr->ifr_addr), 1));
  173         
  174         case SIOCAIFADDR:
  175                 dstIsNew = 0;
  176                 hostIsNew = 1;
  177                 if (ia->ia_addr.sns_family == AF_NS) {
  178                         if (ifra->ifra_addr.sns_len == 0) {
  179                                 ifra->ifra_addr = ia->ia_addr;
  180                                 hostIsNew = 0;
  181                         } else if (ns_neteq(ifra->ifra_addr.sns_addr, ia->ia_addr.sns_addr))
  182                                 hostIsNew = 0;
  183                 }
  184                 if ((ifp->if_flags & IFF_POINTOPOINT) &&
  185                     (ifra->ifra_dstaddr.sns_family == AF_NS)) {
  186                         ns_ifscrub(ifp, ia);
  187                         ia->ia_dstaddr = ifra->ifra_dstaddr;
  188                         dstIsNew  = 1;
  189                 }
  190                 if (ifra->ifra_addr.sns_family == AF_NS &&
  191                     (hostIsNew || dstIsNew))
  192                         error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  193                 return (error);
  194 
  195         case SIOCDIFADDR:
  196                 ns_purgeaddr(&ia->ia_ifa, ifp);
  197                 break;
  198 
  199         default:
  200                 if (ifp == 0 || ifp->if_ioctl == 0)
  201                         return (EOPNOTSUPP);
  202                 return ((*ifp->if_ioctl)(ifp, cmd, data));
  203         }
  204         return (0);
  205 }
  206 
  207 void
  208 ns_purgeaddr(ifa, ifp)
  209         struct ifaddr *ifa;
  210         struct ifnet *ifp;
  211 {
  212         struct ns_ifaddr *ia = (void *) ifa;
  213 
  214         ns_ifscrub(ifp, ia);
  215         TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
  216         IFAFREE(&ia->ia_ifa);
  217         TAILQ_REMOVE(&ns_ifaddr, ia, ia_list);
  218         IFAFREE((&ia->ia_ifa));
  219         if (0 == --ns_interfaces) {
  220                 /*
  221                  * We reset to virginity and start all over again
  222                  */
  223                 ns_thishost = ns_zerohost;
  224         }
  225 }
  226 
  227 void
  228 ns_purgeif(ifp)
  229         struct ifnet *ifp;
  230 {
  231         struct ifaddr *ifa, *nifa;
  232 
  233         for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) {
  234                 nifa = TAILQ_NEXT(ifa, ifa_list);
  235                 if (ifa->ifa_addr->sa_family != AF_NS)
  236                         continue;
  237                 ns_purgeaddr(ifa, ifp);
  238         }
  239 }
  240 
  241 /*
  242  * Delete any previous route for an old address.
  243  */
  244 void
  245 ns_ifscrub(ifp, ia)
  246         struct ifnet *ifp;
  247         struct ns_ifaddr *ia; 
  248 {
  249 
  250         if ((ia->ia_flags & IFA_ROUTE) == 0)
  251                 return;
  252         if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
  253                 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  254         else
  255                 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
  256         ia->ia_flags &= ~IFA_ROUTE;
  257 }
  258 /*
  259  * Initialize an interface's internet address
  260  * and routing table entry.
  261  */
  262 int
  263 ns_ifinit(ifp, ia, sns, scrub)
  264         struct ifnet *ifp;
  265         struct ns_ifaddr *ia;
  266         struct sockaddr_ns *sns;
  267         int scrub;
  268 {
  269         struct sockaddr_ns oldaddr;
  270         union ns_host *h = &ia->ia_addr.sns_addr.x_host;
  271         int s = splnet(), error;
  272 
  273         /*
  274          * Set up new addresses.
  275          */
  276         oldaddr = ia->ia_addr;
  277         ia->ia_addr = *sns;
  278         /*
  279          * The convention we shall adopt for naming is that
  280          * a supplied address of zero means that "we don't care".
  281          * if there is a single interface, use the address of that
  282          * interface as our 6 byte host address.
  283          * if there are multiple interfaces, use any address already
  284          * used.
  285          *
  286          * Give the interface a chance to initialize
  287          * if this is its first address,
  288          * and to validate the address if necessary.
  289          */
  290         if (ns_hosteqnh(ns_thishost, ns_zerohost)) {
  291                 if (ifp->if_ioctl &&
  292                      (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR,
  293                     (caddr_t)ia)))
  294                         goto bad;
  295                 ns_thishost = *h;
  296         } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
  297             || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
  298                 *h = ns_thishost;
  299                 if (ifp->if_ioctl &&
  300                      (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR,
  301                     (caddr_t)ia)))
  302                         goto bad;
  303                 if (!ns_hosteqnh(ns_thishost, *h)) {
  304                         error = EINVAL;
  305                         goto bad;
  306                 }
  307         } else {
  308                 error = EINVAL;
  309                 goto bad;
  310         }
  311         ia->ia_ifa.ifa_metric = ifp->if_metric;
  312         /*
  313          * Add route for the network.
  314          */
  315         if (scrub) {
  316                 ia->ia_ifa.ifa_addr = snstosa(&oldaddr);
  317                 ns_ifscrub(ifp, ia);
  318                 ia->ia_ifa.ifa_addr = snstosa(&ia->ia_addr);
  319         }
  320         if (ifp->if_flags & IFF_POINTOPOINT)
  321                 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  322         else {
  323                 ia->ia_broadaddr.sns_addr.x_net = ia->ia_addr.sns_addr.x_net;
  324                 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP);
  325         }
  326         ia->ia_flags |= IFA_ROUTE;
  327         splx(s);
  328         return (0);
  329 bad:
  330         ia->ia_addr = oldaddr;
  331         splx(s);
  332         return (error);
  333 }
  334 
  335 /*
  336  * Return address info for specified internet network.
  337  */
  338 struct ns_ifaddr *
  339 ns_iaonnetof(dst)
  340         struct ns_addr *dst;
  341 {
  342         struct ns_ifaddr *ia;
  343         struct ns_addr *compare;
  344         struct ifnet *ifp;
  345         struct ns_ifaddr *ia_maybe = 0;
  346         union ns_net net = dst->x_net;
  347 
  348         for (ia = ns_ifaddr.tqh_first; ia != 0; ia = ia->ia_list.tqe_next) {
  349                 if ((ifp = ia->ia_ifp) != NULL) {
  350                         if (ifp->if_flags & IFF_POINTOPOINT) {
  351                                 compare = &satons_addr(ia->ia_dstaddr);
  352                                 if (ns_hosteq(*dst, *compare))
  353                                         return (ia);
  354                                 if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net))
  355                                         ia_maybe = ia;
  356                         } else {
  357                                 if (ns_neteqnn(net, ia->ia_addr.sns_addr.x_net))
  358                                         return (ia);
  359                         }
  360                 }
  361         }
  362         return (ia_maybe);
  363 }

Cache object: bd876520e34a8dc27844b6706802548a


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