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

Cache object: 97cf673e3b9b2ea8cd921e3446a2bb4c


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