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/netinet/in.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) 1982, 1986, 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  * Copyright (C) 2001 WIDE Project.  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  * 4. Neither the name of the University nor the names of its contributors
   15  *    may be used to endorse or promote products derived from this software
   16  *    without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  *
   30  *      @(#)in.c        8.4 (Berkeley) 1/9/95
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include "opt_carp.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/sockio.h>
   41 #include <sys/malloc.h>
   42 #include <sys/priv.h>
   43 #include <sys/socket.h>
   44 #include <sys/jail.h>
   45 #include <sys/kernel.h>
   46 #include <sys/proc.h>
   47 #include <sys/sysctl.h>
   48 
   49 #include <net/if.h>
   50 #include <net/if_types.h>
   51 #include <net/route.h>
   52 
   53 #include <netinet/in.h>
   54 #include <netinet/in_var.h>
   55 #include <netinet/in_pcb.h>
   56 #include <netinet/ip_var.h>
   57 
   58 static int in_mask2len(struct in_addr *);
   59 static void in_len2mask(struct in_addr *, int);
   60 static int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
   61         struct ifnet *, struct thread *);
   62 
   63 static int      in_addprefix(struct in_ifaddr *, int);
   64 static int      in_scrubprefix(struct in_ifaddr *);
   65 static void     in_socktrim(struct sockaddr_in *);
   66 static int      in_ifinit(struct ifnet *,
   67             struct in_ifaddr *, struct sockaddr_in *, int);
   68 static void     in_purgemaddrs(struct ifnet *);
   69 
   70 static int subnetsarelocal = 0;
   71 SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
   72         &subnetsarelocal, 0, "Treat all subnets as directly connected");
   73 static int sameprefixcarponly = 0;
   74 SYSCTL_INT(_net_inet_ip, OID_AUTO, same_prefix_carp_only, CTLFLAG_RW,
   75         &sameprefixcarponly, 0,
   76         "Refuse to create same prefixes on different interfaces");
   77 
   78 extern struct inpcbinfo ripcbinfo;
   79 extern struct inpcbinfo udbinfo;
   80 
   81 /*
   82  * Return 1 if an internet address is for a ``local'' host
   83  * (one to which we have a connection).  If subnetsarelocal
   84  * is true, this includes other subnets of the local net.
   85  * Otherwise, it includes only the directly-connected (sub)nets.
   86  */
   87 int
   88 in_localaddr(struct in_addr in)
   89 {
   90         register u_long i = ntohl(in.s_addr);
   91         register struct in_ifaddr *ia;
   92 
   93         if (subnetsarelocal) {
   94                 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link)
   95                         if ((i & ia->ia_netmask) == ia->ia_net)
   96                                 return (1);
   97         } else {
   98                 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link)
   99                         if ((i & ia->ia_subnetmask) == ia->ia_subnet)
  100                                 return (1);
  101         }
  102         return (0);
  103 }
  104 
  105 /*
  106  * Return 1 if an internet address is for the local host and configured
  107  * on one of its interfaces.
  108  */
  109 int
  110 in_localip(struct in_addr in)
  111 {
  112         struct in_ifaddr *ia;
  113 
  114         LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
  115                 if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr)
  116                         return 1;
  117         }
  118         return 0;
  119 }
  120 
  121 /*
  122  * Determine whether an IP address is in a reserved set of addresses
  123  * that may not be forwarded, or whether datagrams to that destination
  124  * may be forwarded.
  125  */
  126 int
  127 in_canforward(struct in_addr in)
  128 {
  129         register u_long i = ntohl(in.s_addr);
  130         register u_long net;
  131 
  132         if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i))
  133                 return (0);
  134         if (IN_CLASSA(i)) {
  135                 net = i & IN_CLASSA_NET;
  136                 if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
  137                         return (0);
  138         }
  139         return (1);
  140 }
  141 
  142 /*
  143  * Trim a mask in a sockaddr
  144  */
  145 static void
  146 in_socktrim(struct sockaddr_in *ap)
  147 {
  148     register char *cplim = (char *) &ap->sin_addr;
  149     register char *cp = (char *) (&ap->sin_addr + 1);
  150 
  151     ap->sin_len = 0;
  152     while (--cp >= cplim)
  153         if (*cp) {
  154             (ap)->sin_len = cp - (char *) (ap) + 1;
  155             break;
  156         }
  157 }
  158 
  159 static int
  160 in_mask2len(mask)
  161         struct in_addr *mask;
  162 {
  163         int x, y;
  164         u_char *p;
  165 
  166         p = (u_char *)mask;
  167         for (x = 0; x < sizeof(*mask); x++) {
  168                 if (p[x] != 0xff)
  169                         break;
  170         }
  171         y = 0;
  172         if (x < sizeof(*mask)) {
  173                 for (y = 0; y < 8; y++) {
  174                         if ((p[x] & (0x80 >> y)) == 0)
  175                                 break;
  176                 }
  177         }
  178         return x * 8 + y;
  179 }
  180 
  181 static void
  182 in_len2mask(struct in_addr *mask, int len)
  183 {
  184         int i;
  185         u_char *p;
  186 
  187         p = (u_char *)mask;
  188         bzero(mask, sizeof(*mask));
  189         for (i = 0; i < len / 8; i++)
  190                 p[i] = 0xff;
  191         if (len % 8)
  192                 p[i] = (0xff00 >> (len % 8)) & 0xff;
  193 }
  194 
  195 /*
  196  * Generic internet control operations (ioctl's).
  197  * Ifp is 0 if not an interface-specific ioctl.
  198  */
  199 /* ARGSUSED */
  200 int
  201 in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
  202     struct thread *td)
  203 {
  204         register struct ifreq *ifr = (struct ifreq *)data;
  205         register struct in_ifaddr *ia = 0, *iap;
  206         register struct ifaddr *ifa;
  207         struct in_addr allhosts_addr;
  208         struct in_addr dst;
  209         struct in_ifaddr *oia;
  210         struct in_aliasreq *ifra = (struct in_aliasreq *)data;
  211         struct sockaddr_in oldaddr;
  212         int error, hostIsNew, iaIsNew, maskIsNew, s;
  213         int iaIsFirst;
  214 
  215         iaIsFirst = 0;
  216         iaIsNew = 0;
  217         allhosts_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
  218 
  219         switch (cmd) {
  220         case SIOCALIFADDR:
  221                 if (td != NULL) {
  222                         error = priv_check(td, PRIV_NET_ADDIFADDR);
  223                         if (error)
  224                                 return (error);
  225                 }
  226                 if (!ifp)
  227                         return EINVAL;
  228                 return in_lifaddr_ioctl(so, cmd, data, ifp, td);
  229 
  230         case SIOCDLIFADDR:
  231                 if (td != NULL) {
  232                         error = priv_check(td, PRIV_NET_DELIFADDR);
  233                         if (error)
  234                                 return (error);
  235                 }
  236                 if (!ifp)
  237                         return EINVAL;
  238                 return in_lifaddr_ioctl(so, cmd, data, ifp, td);
  239 
  240         case SIOCGLIFADDR:
  241                 if (!ifp)
  242                         return EINVAL;
  243                 return in_lifaddr_ioctl(so, cmd, data, ifp, td);
  244         }
  245 
  246         /*
  247          * Find address for this interface, if it exists.
  248          *
  249          * If an alias address was specified, find that one instead of
  250          * the first one on the interface, if possible.
  251          */
  252         if (ifp) {
  253                 dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
  254                 LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash)
  255                         if (iap->ia_ifp == ifp &&
  256                             iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
  257                                 if (td == NULL || prison_check_ip4(
  258                                     td->td_ucred, &dst) == 0)
  259                                         ia = iap;
  260                                 break;
  261                         }
  262                 if (ia == NULL)
  263                         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
  264                                 iap = ifatoia(ifa);
  265                                 if (iap->ia_addr.sin_family == AF_INET) {
  266                                         if (td != NULL &&
  267                                             prison_check_ip4(td->td_ucred,
  268                                             &iap->ia_addr.sin_addr) != 0)
  269                                                 continue;
  270                                         ia = iap;
  271                                         break;
  272                                 }
  273                         }
  274                 if (ia == NULL)
  275                         iaIsFirst = 1;
  276         }
  277 
  278         switch (cmd) {
  279 
  280         case SIOCAIFADDR:
  281         case SIOCDIFADDR:
  282                 if (ifp == 0)
  283                         return (EADDRNOTAVAIL);
  284                 if (ifra->ifra_addr.sin_family == AF_INET) {
  285                         for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) {
  286                                 if (ia->ia_ifp == ifp  &&
  287                                     ia->ia_addr.sin_addr.s_addr ==
  288                                     ifra->ifra_addr.sin_addr.s_addr)
  289                                         break;
  290                         }
  291                         if ((ifp->if_flags & IFF_POINTOPOINT)
  292                             && (cmd == SIOCAIFADDR)
  293                             && (ifra->ifra_dstaddr.sin_addr.s_addr
  294                                 == INADDR_ANY)) {
  295                                 return EDESTADDRREQ;
  296                         }
  297                 }
  298                 if (cmd == SIOCDIFADDR && ia == 0)
  299                         return (EADDRNOTAVAIL);
  300                 /* FALLTHROUGH */
  301         case SIOCSIFADDR:
  302         case SIOCSIFNETMASK:
  303         case SIOCSIFDSTADDR:
  304                 if (td != NULL) {
  305                         error = priv_check(td, (cmd == SIOCDIFADDR) ? 
  306                             PRIV_NET_DELIFADDR : PRIV_NET_ADDIFADDR);
  307                         if (error)
  308                                 return (error);
  309                 }
  310 
  311                 if (ifp == 0)
  312                         return (EADDRNOTAVAIL);
  313                 if (ia == (struct in_ifaddr *)0) {
  314                         ia = (struct in_ifaddr *)
  315                                 malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
  316                         if (ia == (struct in_ifaddr *)NULL)
  317                                 return (ENOBUFS);
  318                         /*
  319                          * Protect from ipintr() traversing address list
  320                          * while we're modifying it.
  321                          */
  322                         s = splnet();
  323                         ifa = &ia->ia_ifa;
  324                         IFA_LOCK_INIT(ifa);
  325                         ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
  326                         ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
  327                         ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
  328                         ifa->ifa_refcnt = 1;
  329                         TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
  330 
  331                         ia->ia_sockmask.sin_len = 8;
  332                         ia->ia_sockmask.sin_family = AF_INET;
  333                         if (ifp->if_flags & IFF_BROADCAST) {
  334                                 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
  335                                 ia->ia_broadaddr.sin_family = AF_INET;
  336                         }
  337                         ia->ia_ifp = ifp;
  338 
  339                         TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
  340                         splx(s);
  341                         iaIsNew = 1;
  342                 }
  343                 break;
  344 
  345         case SIOCSIFBRDADDR:
  346                 if (td != NULL) {
  347                         error = priv_check(td, PRIV_NET_ADDIFADDR);
  348                         if (error)
  349                                 return (error);
  350                 }
  351                 /* FALLTHROUGH */
  352 
  353         case SIOCGIFADDR:
  354         case SIOCGIFNETMASK:
  355         case SIOCGIFDSTADDR:
  356         case SIOCGIFBRDADDR:
  357                 if (ia == (struct in_ifaddr *)0)
  358                         return (EADDRNOTAVAIL);
  359                 break;
  360         }
  361         switch (cmd) {
  362 
  363         case SIOCGIFADDR:
  364                 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
  365                 return (0);
  366 
  367         case SIOCGIFBRDADDR:
  368                 if ((ifp->if_flags & IFF_BROADCAST) == 0)
  369                         return (EINVAL);
  370                 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
  371                 return (0);
  372 
  373         case SIOCGIFDSTADDR:
  374                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  375                         return (EINVAL);
  376                 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
  377                 return (0);
  378 
  379         case SIOCGIFNETMASK:
  380                 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
  381                 return (0);
  382 
  383         case SIOCSIFDSTADDR:
  384                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  385                         return (EINVAL);
  386                 oldaddr = ia->ia_dstaddr;
  387                 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
  388                 if (ifp->if_ioctl) {
  389                         IFF_LOCKGIANT(ifp);
  390                         error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
  391                             (caddr_t)ia);
  392                         IFF_UNLOCKGIANT(ifp);
  393                         if (error) {
  394                                 ia->ia_dstaddr = oldaddr;
  395                                 return (error);
  396                         }
  397                 }
  398                 if (ia->ia_flags & IFA_ROUTE) {
  399                         ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
  400                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  401                         ia->ia_ifa.ifa_dstaddr =
  402                                         (struct sockaddr *)&ia->ia_dstaddr;
  403                         rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  404                 }
  405                 return (0);
  406 
  407         case SIOCSIFBRDADDR:
  408                 if ((ifp->if_flags & IFF_BROADCAST) == 0)
  409                         return (EINVAL);
  410                 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
  411                 return (0);
  412 
  413         case SIOCSIFADDR:
  414                 error = in_ifinit(ifp, ia,
  415                     (struct sockaddr_in *) &ifr->ifr_addr, 1);
  416                 if (error != 0 && iaIsNew)
  417                         break;
  418                 if (error == 0) {
  419                         if (iaIsFirst && (ifp->if_flags & IFF_MULTICAST) != 0)
  420                                 in_addmulti(&allhosts_addr, ifp);
  421                         EVENTHANDLER_INVOKE(ifaddr_event, ifp);
  422                 }
  423                 return (0);
  424 
  425         case SIOCSIFNETMASK:
  426                 ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr;
  427                 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr);
  428                 return (0);
  429 
  430         case SIOCAIFADDR:
  431                 maskIsNew = 0;
  432                 hostIsNew = 1;
  433                 error = 0;
  434                 if (ia->ia_addr.sin_family == AF_INET) {
  435                         if (ifra->ifra_addr.sin_len == 0) {
  436                                 ifra->ifra_addr = ia->ia_addr;
  437                                 hostIsNew = 0;
  438                         } else if (ifra->ifra_addr.sin_addr.s_addr ==
  439                                                ia->ia_addr.sin_addr.s_addr)
  440                                 hostIsNew = 0;
  441                 }
  442                 if (ifra->ifra_mask.sin_len) {
  443                         in_ifscrub(ifp, ia);
  444                         ia->ia_sockmask = ifra->ifra_mask;
  445                         ia->ia_sockmask.sin_family = AF_INET;
  446                         ia->ia_subnetmask =
  447                              ntohl(ia->ia_sockmask.sin_addr.s_addr);
  448                         maskIsNew = 1;
  449                 }
  450                 if ((ifp->if_flags & IFF_POINTOPOINT) &&
  451                     (ifra->ifra_dstaddr.sin_family == AF_INET)) {
  452                         in_ifscrub(ifp, ia);
  453                         ia->ia_dstaddr = ifra->ifra_dstaddr;
  454                         maskIsNew  = 1; /* We lie; but the effect's the same */
  455                 }
  456                 if (ifra->ifra_addr.sin_family == AF_INET &&
  457                     (hostIsNew || maskIsNew))
  458                         error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  459                 if (error != 0 && iaIsNew)
  460                         break;
  461 
  462                 if ((ifp->if_flags & IFF_BROADCAST) &&
  463                     (ifra->ifra_broadaddr.sin_family == AF_INET))
  464                         ia->ia_broadaddr = ifra->ifra_broadaddr;
  465                 if (error == 0) {
  466                         if (iaIsFirst && (ifp->if_flags & IFF_MULTICAST) != 0)
  467                                 in_addmulti(&allhosts_addr, ifp);
  468                         EVENTHANDLER_INVOKE(ifaddr_event, ifp);
  469                 }
  470                 return (error);
  471 
  472         case SIOCDIFADDR:
  473                 /*
  474                  * in_ifscrub kills the interface route.
  475                  */
  476                 in_ifscrub(ifp, ia);
  477                 /*
  478                  * in_ifadown gets rid of all the rest of
  479                  * the routes.  This is not quite the right
  480                  * thing to do, but at least if we are running
  481                  * a routing process they will come back.
  482                  */
  483                 in_ifadown(&ia->ia_ifa, 1);
  484                 EVENTHANDLER_INVOKE(ifaddr_event, ifp);
  485                 error = 0;
  486                 break;
  487 
  488         default:
  489                 if (ifp == 0 || ifp->if_ioctl == 0)
  490                         return (EOPNOTSUPP);
  491                 IFF_LOCKGIANT(ifp);
  492                 error = (*ifp->if_ioctl)(ifp, cmd, data);
  493                 IFF_UNLOCKGIANT(ifp);
  494                 return (error);
  495         }
  496 
  497         /*
  498          * Protect from ipintr() traversing address list while we're modifying
  499          * it.
  500          */
  501         s = splnet();
  502         TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
  503         TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
  504         if (ia->ia_addr.sin_family == AF_INET) {
  505                 LIST_REMOVE(ia, ia_hash);
  506                 /*
  507                  * If this is the last IPv4 address configured on this
  508                  * interface, leave the all-hosts group.
  509                  * XXX: This is quite ugly because of locking and structure.
  510                  */
  511                 oia = NULL;
  512                 IFP_TO_IA(ifp, oia);
  513                 if (oia == NULL) {
  514                         struct in_multi *inm;
  515 
  516                         IFF_LOCKGIANT(ifp);
  517                         IN_MULTI_LOCK();
  518                         IN_LOOKUP_MULTI(allhosts_addr, ifp, inm);
  519                         if (inm != NULL)
  520                                 in_delmulti_locked(inm);
  521                         IN_MULTI_UNLOCK();
  522                         IFF_UNLOCKGIANT(ifp);
  523                 }
  524         }
  525         IFAFREE(&ia->ia_ifa);
  526         splx(s);
  527 
  528         return (error);
  529 }
  530 
  531 /*
  532  * SIOC[GAD]LIFADDR.
  533  *      SIOCGLIFADDR: get first address. (?!?)
  534  *      SIOCGLIFADDR with IFLR_PREFIX:
  535  *              get first address that matches the specified prefix.
  536  *      SIOCALIFADDR: add the specified address.
  537  *      SIOCALIFADDR with IFLR_PREFIX:
  538  *              EINVAL since we can't deduce hostid part of the address.
  539  *      SIOCDLIFADDR: delete the specified address.
  540  *      SIOCDLIFADDR with IFLR_PREFIX:
  541  *              delete the first address that matches the specified prefix.
  542  * return values:
  543  *      EINVAL on invalid parameters
  544  *      EADDRNOTAVAIL on prefix match failed/specified address not found
  545  *      other values may be returned from in_ioctl()
  546  */
  547 static int
  548 in_lifaddr_ioctl(struct socket *so, u_long cmd, caddr_t data,
  549     struct ifnet *ifp, struct thread *td)
  550 {
  551         struct if_laddrreq *iflr = (struct if_laddrreq *)data;
  552         struct ifaddr *ifa;
  553 
  554         /* sanity checks */
  555         if (!data || !ifp) {
  556                 panic("invalid argument to in_lifaddr_ioctl");
  557                 /*NOTRECHED*/
  558         }
  559 
  560         switch (cmd) {
  561         case SIOCGLIFADDR:
  562                 /* address must be specified on GET with IFLR_PREFIX */
  563                 if ((iflr->flags & IFLR_PREFIX) == 0)
  564                         break;
  565                 /*FALLTHROUGH*/
  566         case SIOCALIFADDR:
  567         case SIOCDLIFADDR:
  568                 /* address must be specified on ADD and DELETE */
  569                 if (iflr->addr.ss_family != AF_INET)
  570                         return EINVAL;
  571                 if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
  572                         return EINVAL;
  573                 /* XXX need improvement */
  574                 if (iflr->dstaddr.ss_family
  575                  && iflr->dstaddr.ss_family != AF_INET)
  576                         return EINVAL;
  577                 if (iflr->dstaddr.ss_family
  578                  && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
  579                         return EINVAL;
  580                 break;
  581         default: /*shouldn't happen*/
  582                 return EOPNOTSUPP;
  583         }
  584         if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
  585                 return EINVAL;
  586 
  587         switch (cmd) {
  588         case SIOCALIFADDR:
  589             {
  590                 struct in_aliasreq ifra;
  591 
  592                 if (iflr->flags & IFLR_PREFIX)
  593                         return EINVAL;
  594 
  595                 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
  596                 bzero(&ifra, sizeof(ifra));
  597                 bcopy(iflr->iflr_name, ifra.ifra_name,
  598                         sizeof(ifra.ifra_name));
  599 
  600                 bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
  601 
  602                 if (iflr->dstaddr.ss_family) {  /*XXX*/
  603                         bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
  604                                 iflr->dstaddr.ss_len);
  605                 }
  606 
  607                 ifra.ifra_mask.sin_family = AF_INET;
  608                 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
  609                 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
  610 
  611                 return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, td);
  612             }
  613         case SIOCGLIFADDR:
  614         case SIOCDLIFADDR:
  615             {
  616                 struct in_ifaddr *ia;
  617                 struct in_addr mask, candidate, match;
  618                 struct sockaddr_in *sin;
  619 
  620                 bzero(&mask, sizeof(mask));
  621                 bzero(&match, sizeof(match));
  622                 if (iflr->flags & IFLR_PREFIX) {
  623                         /* lookup a prefix rather than address. */
  624                         in_len2mask(&mask, iflr->prefixlen);
  625 
  626                         sin = (struct sockaddr_in *)&iflr->addr;
  627                         match.s_addr = sin->sin_addr.s_addr;
  628                         match.s_addr &= mask.s_addr;
  629 
  630                         /* if you set extra bits, that's wrong */
  631                         if (match.s_addr != sin->sin_addr.s_addr)
  632                                 return EINVAL;
  633 
  634                 } else {
  635                         /* on getting an address, take the 1st match */
  636                         /* on deleting an address, do exact match */
  637                         if (cmd != SIOCGLIFADDR) {
  638                                 in_len2mask(&mask, 32);
  639                                 sin = (struct sockaddr_in *)&iflr->addr;
  640                                 match.s_addr = sin->sin_addr.s_addr;
  641                         }
  642                 }
  643 
  644                 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
  645                         if (ifa->ifa_addr->sa_family != AF_INET6)
  646                                 continue;
  647                         if (match.s_addr == 0)
  648                                 break;
  649                         candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
  650                         candidate.s_addr &= mask.s_addr;
  651                         if (candidate.s_addr == match.s_addr)
  652                                 break;
  653                 }
  654                 if (!ifa)
  655                         return EADDRNOTAVAIL;
  656                 ia = (struct in_ifaddr *)ifa;
  657 
  658                 if (cmd == SIOCGLIFADDR) {
  659                         /* fill in the if_laddrreq structure */
  660                         bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
  661 
  662                         if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
  663                                 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
  664                                         ia->ia_dstaddr.sin_len);
  665                         } else
  666                                 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
  667 
  668                         iflr->prefixlen =
  669                                 in_mask2len(&ia->ia_sockmask.sin_addr);
  670 
  671                         iflr->flags = 0;        /*XXX*/
  672 
  673                         return 0;
  674                 } else {
  675                         struct in_aliasreq ifra;
  676 
  677                         /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
  678                         bzero(&ifra, sizeof(ifra));
  679                         bcopy(iflr->iflr_name, ifra.ifra_name,
  680                                 sizeof(ifra.ifra_name));
  681 
  682                         bcopy(&ia->ia_addr, &ifra.ifra_addr,
  683                                 ia->ia_addr.sin_len);
  684                         if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
  685                                 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
  686                                         ia->ia_dstaddr.sin_len);
  687                         }
  688                         bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
  689                                 ia->ia_sockmask.sin_len);
  690 
  691                         return in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
  692                                           ifp, td);
  693                 }
  694             }
  695         }
  696 
  697         return EOPNOTSUPP;      /*just for safety*/
  698 }
  699 
  700 /*
  701  * Delete any existing route for an interface.
  702  */
  703 void
  704 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
  705 {
  706 
  707         in_scrubprefix(ia);
  708 }
  709 
  710 /*
  711  * Initialize an interface's internet address
  712  * and routing table entry.
  713  */
  714 static int
  715 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
  716     int scrub)
  717 {
  718         register u_long i = ntohl(sin->sin_addr.s_addr);
  719         struct sockaddr_in oldaddr;
  720         int s = splimp(), flags = RTF_UP, error = 0;
  721 
  722         oldaddr = ia->ia_addr;
  723         if (oldaddr.sin_family == AF_INET)
  724                 LIST_REMOVE(ia, ia_hash);
  725         ia->ia_addr = *sin;
  726         if (ia->ia_addr.sin_family == AF_INET)
  727                 LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
  728                     ia, ia_hash);
  729         /*
  730          * Give the interface a chance to initialize
  731          * if this is its first address,
  732          * and to validate the address if necessary.
  733          */
  734         if (ifp->if_ioctl) {
  735                 IFF_LOCKGIANT(ifp);
  736                 error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
  737                 IFF_UNLOCKGIANT(ifp);
  738                 if (error) {
  739                         splx(s);
  740                         /* LIST_REMOVE(ia, ia_hash) is done in in_control */
  741                         ia->ia_addr = oldaddr;
  742                         if (ia->ia_addr.sin_family == AF_INET)
  743                                 LIST_INSERT_HEAD(INADDR_HASH(
  744                                     ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
  745                         else 
  746                                 /* 
  747                                  * If oldaddr family is not AF_INET (e.g. 
  748                                  * interface has been just created) in_control 
  749                                  * does not call LIST_REMOVE, and we end up 
  750                                  * with bogus ia entries in hash
  751                                  */
  752                                 LIST_REMOVE(ia, ia_hash);
  753                         return (error);
  754                 }
  755         }
  756         splx(s);
  757         if (scrub) {
  758                 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
  759                 in_ifscrub(ifp, ia);
  760                 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
  761         }
  762         if (IN_CLASSA(i))
  763                 ia->ia_netmask = IN_CLASSA_NET;
  764         else if (IN_CLASSB(i))
  765                 ia->ia_netmask = IN_CLASSB_NET;
  766         else
  767                 ia->ia_netmask = IN_CLASSC_NET;
  768         /*
  769          * The subnet mask usually includes at least the standard network part,
  770          * but may may be smaller in the case of supernetting.
  771          * If it is set, we believe it.
  772          */
  773         if (ia->ia_subnetmask == 0) {
  774                 ia->ia_subnetmask = ia->ia_netmask;
  775                 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
  776         } else
  777                 ia->ia_netmask &= ia->ia_subnetmask;
  778         ia->ia_net = i & ia->ia_netmask;
  779         ia->ia_subnet = i & ia->ia_subnetmask;
  780         in_socktrim(&ia->ia_sockmask);
  781 #ifdef DEV_CARP
  782         /*
  783          * XXX: carp(4) does not have interface route
  784          */
  785         if (ifp->if_type == IFT_CARP)
  786                 return (0);
  787 #endif
  788         /*
  789          * Add route for the network.
  790          */
  791         ia->ia_ifa.ifa_metric = ifp->if_metric;
  792         if (ifp->if_flags & IFF_BROADCAST) {
  793                 ia->ia_broadaddr.sin_addr.s_addr =
  794                         htonl(ia->ia_subnet | ~ia->ia_subnetmask);
  795                 ia->ia_netbroadcast.s_addr =
  796                         htonl(ia->ia_net | ~ ia->ia_netmask);
  797         } else if (ifp->if_flags & IFF_LOOPBACK) {
  798                 ia->ia_dstaddr = ia->ia_addr;
  799                 flags |= RTF_HOST;
  800         } else if (ifp->if_flags & IFF_POINTOPOINT) {
  801                 if (ia->ia_dstaddr.sin_family != AF_INET)
  802                         return (0);
  803                 flags |= RTF_HOST;
  804         }
  805         if ((error = in_addprefix(ia, flags)) != 0)
  806                 return (error);
  807 
  808         return (error);
  809 }
  810 
  811 #define rtinitflags(x) \
  812         ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
  813             ? RTF_HOST : 0)
  814 /*
  815  * Check if we have a route for the given prefix already or add one accordingly.
  816  */
  817 static int
  818 in_addprefix(struct in_ifaddr *target, int flags)
  819 {
  820         struct in_ifaddr *ia;
  821         struct in_addr prefix, mask, p, m;
  822         int error;
  823 
  824         if ((flags & RTF_HOST) != 0) {
  825                 prefix = target->ia_dstaddr.sin_addr;
  826                 mask.s_addr = 0;
  827         } else {
  828                 prefix = target->ia_addr.sin_addr;
  829                 mask = target->ia_sockmask.sin_addr;
  830                 prefix.s_addr &= mask.s_addr;
  831         }
  832 
  833         TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
  834                 if (rtinitflags(ia)) {
  835                         p = ia->ia_addr.sin_addr;
  836 
  837                         if (prefix.s_addr != p.s_addr)
  838                                 continue;
  839                 } else {
  840                         p = ia->ia_addr.sin_addr;
  841                         m = ia->ia_sockmask.sin_addr;
  842                         p.s_addr &= m.s_addr;
  843 
  844                         if (prefix.s_addr != p.s_addr ||
  845                             mask.s_addr != m.s_addr)
  846                                 continue;
  847                 }
  848 
  849                 /*
  850                  * If we got a matching prefix route inserted by other
  851                  * interface address, we are done here.
  852                  */
  853                 if (ia->ia_flags & IFA_ROUTE) {
  854                         if (sameprefixcarponly &&
  855                             target->ia_ifp->if_type != IFT_CARP &&
  856                             ia->ia_ifp->if_type != IFT_CARP)
  857                                 return (EEXIST);
  858                         else
  859                                 return (0);
  860                 }
  861         }
  862 
  863         /*
  864          * No-one seem to have this prefix route, so we try to insert it.
  865          */
  866         error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
  867         if (!error)
  868                 target->ia_flags |= IFA_ROUTE;
  869         return error;
  870 }
  871 
  872 /*
  873  * If there is no other address in the system that can serve a route to the
  874  * same prefix, remove the route.  Hand over the route to the new address
  875  * otherwise.
  876  */
  877 static int
  878 in_scrubprefix(struct in_ifaddr *target)
  879 {
  880         struct in_ifaddr *ia;
  881         struct in_addr prefix, mask, p;
  882         int error;
  883 
  884         if ((target->ia_flags & IFA_ROUTE) == 0)
  885                 return 0;
  886 
  887         if (rtinitflags(target))
  888                 prefix = target->ia_dstaddr.sin_addr;
  889         else {
  890                 prefix = target->ia_addr.sin_addr;
  891                 mask = target->ia_sockmask.sin_addr;
  892                 prefix.s_addr &= mask.s_addr;
  893         }
  894 
  895         TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
  896                 if (rtinitflags(ia))
  897                         p = ia->ia_dstaddr.sin_addr;
  898                 else {
  899                         p = ia->ia_addr.sin_addr;
  900                         p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
  901                 }
  902 
  903                 if (prefix.s_addr != p.s_addr)
  904                         continue;
  905 
  906                 /*
  907                  * If we got a matching prefix address, move IFA_ROUTE and
  908                  * the route itself to it.  Make sure that routing daemons
  909                  * get a heads-up.
  910                  *
  911                  * XXX: a special case for carp(4) interface
  912                  */
  913                 if ((ia->ia_flags & IFA_ROUTE) == 0
  914 #ifdef DEV_CARP
  915                     && (ia->ia_ifp->if_type != IFT_CARP)
  916 #endif
  917                                                         ) {
  918                         rtinit(&(target->ia_ifa), (int)RTM_DELETE,
  919                             rtinitflags(target));
  920                         target->ia_flags &= ~IFA_ROUTE;
  921 
  922                         error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
  923                             rtinitflags(ia) | RTF_UP);
  924                         if (error == 0)
  925                                 ia->ia_flags |= IFA_ROUTE;
  926                         return error;
  927                 }
  928         }
  929 
  930         /*
  931          * As no-one seem to have this prefix, we can remove the route.
  932          */
  933         rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
  934         target->ia_flags &= ~IFA_ROUTE;
  935         return 0;
  936 }
  937 
  938 #undef rtinitflags
  939 
  940 /*
  941  * Return 1 if the address might be a local broadcast address.
  942  */
  943 int
  944 in_broadcast(struct in_addr in, struct ifnet *ifp)
  945 {
  946         register struct ifaddr *ifa;
  947         u_long t;
  948 
  949         if (in.s_addr == INADDR_BROADCAST ||
  950             in.s_addr == INADDR_ANY)
  951                 return 1;
  952         if ((ifp->if_flags & IFF_BROADCAST) == 0)
  953                 return 0;
  954         t = ntohl(in.s_addr);
  955         /*
  956          * Look through the list of addresses for a match
  957          * with a broadcast address.
  958          */
  959 #define ia ((struct in_ifaddr *)ifa)
  960         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
  961                 if (ifa->ifa_addr->sa_family == AF_INET &&
  962                     (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
  963                      in.s_addr == ia->ia_netbroadcast.s_addr ||
  964                      /*
  965                       * Check for old-style (host 0) broadcast.
  966                       */
  967                      t == ia->ia_subnet || t == ia->ia_net) &&
  968                      /*
  969                       * Check for an all one subnetmask. These
  970                       * only exist when an interface gets a secondary
  971                       * address.
  972                       */
  973                      ia->ia_subnetmask != (u_long)0xffffffff)
  974                             return 1;
  975         return (0);
  976 #undef ia
  977 }
  978 
  979 /*
  980  * Delete all IPv4 multicast address records, and associated link-layer
  981  * multicast address records, associated with ifp.
  982  */
  983 static void
  984 in_purgemaddrs(struct ifnet *ifp)
  985 {
  986         struct in_multi *inm;
  987         struct in_multi *oinm;
  988 
  989 #ifdef DIAGNOSTIC
  990         printf("%s: purging ifp %p\n", __func__, ifp);
  991 #endif
  992         IFF_LOCKGIANT(ifp);
  993         IN_MULTI_LOCK();
  994         LIST_FOREACH_SAFE(inm, &in_multihead, inm_link, oinm) {
  995                 if (inm->inm_ifp == ifp)
  996                         in_delmulti_locked(inm);
  997         }
  998         IN_MULTI_UNLOCK();
  999         IFF_UNLOCKGIANT(ifp);
 1000 }
 1001 
 1002 /*
 1003  * On interface removal, clean up IPv4 data structures hung off of the ifnet.
 1004  */
 1005 void
 1006 in_ifdetach(struct ifnet *ifp)
 1007 {
 1008 
 1009         in_pcbpurgeif0(&ripcbinfo, ifp);
 1010         in_pcbpurgeif0(&udbinfo, ifp);
 1011         in_purgemaddrs(ifp);
 1012 }

Cache object: 796fd4ea6c8618b0717fd3d3249b6443


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