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 /*      $NetBSD: in.c,v 1.127.4.3 2010/05/20 05:05:58 snj Exp $ */
    2 
    3 /*
    4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    5  * 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 project 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 PROJECT 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 PROJECT 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 
   32 /*-
   33  * Copyright (c) 1998 The NetBSD Foundation, Inc.
   34  * All rights reserved.
   35  *
   36  * This code is derived from software contributed to The NetBSD Foundation
   37  * by Public Access Networks Corporation ("Panix").  It was developed under
   38  * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
   39  *
   40  * Redistribution and use in source and binary forms, with or without
   41  * modification, are permitted provided that the following conditions
   42  * are met:
   43  * 1. Redistributions of source code must retain the above copyright
   44  *    notice, this list of conditions and the following disclaimer.
   45  * 2. Redistributions in binary form must reproduce the above copyright
   46  *    notice, this list of conditions and the following disclaimer in the
   47  *    documentation and/or other materials provided with the distribution.
   48  *
   49  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   50  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   51  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   52  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   53  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   54  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   55  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   56  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   57  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   58  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   59  * POSSIBILITY OF SUCH DAMAGE.
   60  */
   61 
   62 /*
   63  * Copyright (c) 1982, 1986, 1991, 1993
   64  *      The Regents of the University of California.  All rights reserved.
   65  *
   66  * Redistribution and use in source and binary forms, with or without
   67  * modification, are permitted provided that the following conditions
   68  * are met:
   69  * 1. Redistributions of source code must retain the above copyright
   70  *    notice, this list of conditions and the following disclaimer.
   71  * 2. Redistributions in binary form must reproduce the above copyright
   72  *    notice, this list of conditions and the following disclaimer in the
   73  *    documentation and/or other materials provided with the distribution.
   74  * 3. Neither the name of the University nor the names of its contributors
   75  *    may be used to endorse or promote products derived from this software
   76  *    without specific prior written permission.
   77  *
   78  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   79  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   80  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   81  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   82  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   83  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   84  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   85  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   86  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   87  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   88  * SUCH DAMAGE.
   89  *
   90  *      @(#)in.c        8.4 (Berkeley) 1/9/95
   91  */
   92 
   93 #include <sys/cdefs.h>
   94 __KERNEL_RCSID(0, "$NetBSD: in.c,v 1.127.4.3 2010/05/20 05:05:58 snj Exp $");
   95 
   96 #include "opt_inet.h"
   97 #include "opt_inet_conf.h"
   98 #include "opt_mrouting.h"
   99 #include "opt_pfil_hooks.h"
  100 
  101 #include <sys/param.h>
  102 #include <sys/ioctl.h>
  103 #include <sys/errno.h>
  104 #include <sys/malloc.h>
  105 #include <sys/socket.h>
  106 #include <sys/socketvar.h>
  107 #include <sys/sysctl.h>
  108 #include <sys/systm.h>
  109 #include <sys/proc.h>
  110 #include <sys/syslog.h>
  111 #include <sys/kauth.h>
  112 
  113 #include <net/if.h>
  114 #include <net/route.h>
  115 
  116 #include <net/if_ether.h>
  117 
  118 #include <netinet/in_systm.h>
  119 #include <netinet/in.h>
  120 #include <netinet/in_var.h>
  121 #include <netinet/ip.h>
  122 #include <netinet/ip_var.h>
  123 #include <netinet/in_ifattach.h>
  124 #include <netinet/in_pcb.h>
  125 #include <netinet/if_inarp.h>
  126 #include <netinet/ip_mroute.h>
  127 #include <netinet/igmp_var.h>
  128 
  129 #ifdef IPSELSRC
  130 #include <netinet/in_selsrc.h>
  131 #endif
  132 
  133 #ifdef PFIL_HOOKS
  134 #include <net/pfil.h>
  135 #endif
  136 
  137 static u_int in_mask2len(struct in_addr *);
  138 static void in_len2mask(struct in_addr *, u_int);
  139 static int in_lifaddr_ioctl(struct socket *, u_long, void *,
  140         struct ifnet *, struct lwp *);
  141 
  142 static int in_ifaddrpref_ioctl(struct socket *, u_long, void *,
  143         struct ifnet *);
  144 static int in_addprefix(struct in_ifaddr *, int);
  145 static int in_scrubprefix(struct in_ifaddr *);
  146 
  147 #ifndef SUBNETSARELOCAL
  148 #define SUBNETSARELOCAL 1
  149 #endif
  150 
  151 #ifndef HOSTZEROBROADCAST
  152 #define HOSTZEROBROADCAST 1
  153 #endif
  154 
  155 int subnetsarelocal = SUBNETSARELOCAL;
  156 int hostzeroisbroadcast = HOSTZEROBROADCAST;
  157 
  158 /*
  159  * This list is used to keep track of in_multi chains which belong to
  160  * deleted interface addresses.  We use in_ifaddr so that a chain head
  161  * won't be deallocated until all multicast address record are deleted.
  162  */
  163 static TAILQ_HEAD(, in_ifaddr) in_mk = TAILQ_HEAD_INITIALIZER(in_mk);
  164 
  165 /*
  166  * Return 1 if an internet address is for a ``local'' host
  167  * (one to which we have a connection).  If subnetsarelocal
  168  * is true, this includes other subnets of the local net.
  169  * Otherwise, it includes only the directly-connected (sub)nets.
  170  */
  171 int
  172 in_localaddr(struct in_addr in)
  173 {
  174         struct in_ifaddr *ia;
  175 
  176         if (subnetsarelocal) {
  177                 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list)
  178                         if ((in.s_addr & ia->ia_netmask) == ia->ia_net)
  179                                 return (1);
  180         } else {
  181                 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list)
  182                         if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet)
  183                                 return (1);
  184         }
  185         return (0);
  186 }
  187 
  188 /*
  189  * Determine whether an IP address is in a reserved set of addresses
  190  * that may not be forwarded, or whether datagrams to that destination
  191  * may be forwarded.
  192  */
  193 int
  194 in_canforward(struct in_addr in)
  195 {
  196         u_int32_t net;
  197 
  198         if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr))
  199                 return (0);
  200         if (IN_CLASSA(in.s_addr)) {
  201                 net = in.s_addr & IN_CLASSA_NET;
  202                 if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
  203                         return (0);
  204         }
  205         return (1);
  206 }
  207 
  208 /*
  209  * Trim a mask in a sockaddr
  210  */
  211 void
  212 in_socktrim(struct sockaddr_in *ap)
  213 {
  214         char *cplim = (char *) &ap->sin_addr;
  215         char *cp = (char *) (&ap->sin_addr + 1);
  216 
  217         ap->sin_len = 0;
  218         while (--cp >= cplim)
  219                 if (*cp) {
  220                         (ap)->sin_len = cp - (char *) (ap) + 1;
  221                         break;
  222                 }
  223 }
  224 
  225 /*
  226  *  Routine to take an Internet address and convert into a
  227  *  "dotted quad" representation for printing.
  228  */
  229 const char *
  230 in_fmtaddr(struct in_addr addr)
  231 {
  232         static char buf[sizeof("123.456.789.123")];
  233 
  234         addr.s_addr = ntohl(addr.s_addr);
  235 
  236         snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
  237                 (addr.s_addr >> 24) & 0xFF,
  238                 (addr.s_addr >> 16) & 0xFF,
  239                 (addr.s_addr >>  8) & 0xFF,
  240                 (addr.s_addr >>  0) & 0xFF);
  241         return buf;
  242 }
  243 
  244 /*
  245  * Maintain the "in_maxmtu" variable, which is the largest
  246  * mtu for non-local interfaces with AF_INET addresses assigned
  247  * to them that are up.
  248  */
  249 unsigned long in_maxmtu;
  250 
  251 void
  252 in_setmaxmtu(void)
  253 {
  254         struct in_ifaddr *ia;
  255         struct ifnet *ifp;
  256         unsigned long maxmtu = 0;
  257 
  258         TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list) {
  259                 if ((ifp = ia->ia_ifp) == 0)
  260                         continue;
  261                 if ((ifp->if_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP)
  262                         continue;
  263                 if (ifp->if_mtu > maxmtu)
  264                         maxmtu = ifp->if_mtu;
  265         }
  266         if (maxmtu)
  267                 in_maxmtu = maxmtu;
  268 }
  269 
  270 static u_int
  271 in_mask2len(struct in_addr *mask)
  272 {
  273         u_int x, y;
  274         u_char *p;
  275 
  276         p = (u_char *)mask;
  277         for (x = 0; x < sizeof(*mask); x++) {
  278                 if (p[x] != 0xff)
  279                         break;
  280         }
  281         y = 0;
  282         if (x < sizeof(*mask)) {
  283                 for (y = 0; y < NBBY; y++) {
  284                         if ((p[x] & (0x80 >> y)) == 0)
  285                                 break;
  286                 }
  287         }
  288         return x * NBBY + y;
  289 }
  290 
  291 static void
  292 in_len2mask(struct in_addr *mask, u_int len)
  293 {
  294         u_int i;
  295         u_char *p;
  296 
  297         p = (u_char *)mask;
  298         bzero(mask, sizeof(*mask));
  299         for (i = 0; i < len / NBBY; i++)
  300                 p[i] = 0xff;
  301         if (len % NBBY)
  302                 p[i] = (0xff00 >> (len % NBBY)) & 0xff;
  303 }
  304 
  305 /*
  306  * Generic internet control operations (ioctl's).
  307  * Ifp is 0 if not an interface-specific ioctl.
  308  */
  309 /* ARGSUSED */
  310 int
  311 in_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
  312     struct lwp *l)
  313 {
  314         struct ifreq *ifr = (struct ifreq *)data;
  315         struct in_ifaddr *ia = 0;
  316         struct in_aliasreq *ifra = (struct in_aliasreq *)data;
  317         struct sockaddr_in oldaddr;
  318         int error, hostIsNew, maskIsNew;
  319         int newifaddr = 0;
  320 
  321         switch (cmd) {
  322         case SIOCALIFADDR:
  323         case SIOCDLIFADDR:
  324         case SIOCSIFADDRPREF:
  325                 if (l == NULL)
  326                         return (EPERM);
  327                 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
  328                     KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
  329                     NULL) != 0)
  330                         return (EPERM);
  331                 /*FALLTHROUGH*/
  332         case SIOCGIFADDRPREF:
  333         case SIOCGLIFADDR:
  334                 if (ifp == NULL)
  335                         return EINVAL;
  336                 if (cmd == SIOCGIFADDRPREF || cmd == SIOCSIFADDRPREF)
  337                         return in_ifaddrpref_ioctl(so, cmd, data, ifp);
  338                 else
  339                         return in_lifaddr_ioctl(so, cmd, data, ifp, l);
  340         }
  341 
  342         /*
  343          * Find address for this interface, if it exists.
  344          */
  345         if (ifp != NULL)
  346                 IFP_TO_IA(ifp, ia);
  347 
  348         switch (cmd) {
  349 
  350         case SIOCAIFADDR:
  351         case SIOCDIFADDR:
  352         case SIOCGIFALIAS:
  353                 if (ifra->ifra_addr.sin_family == AF_INET)
  354                         LIST_FOREACH(ia,
  355                             &IN_IFADDR_HASH(ifra->ifra_addr.sin_addr.s_addr),
  356                             ia_hash) {
  357                                 if (ia->ia_ifp == ifp &&
  358                                     in_hosteq(ia->ia_addr.sin_addr,
  359                                     ifra->ifra_addr.sin_addr))
  360                                         break;
  361                         }
  362                 if ((cmd == SIOCDIFADDR || cmd == SIOCGIFALIAS) && ia == NULL)
  363                         return (EADDRNOTAVAIL);
  364 
  365 #if 1 /*def COMPAT_43*/
  366                 if (cmd == SIOCDIFADDR &&
  367                     ifra->ifra_addr.sin_family == AF_UNSPEC) {
  368                         ifra->ifra_addr.sin_family = AF_INET;
  369                 }
  370 #endif
  371                 /* FALLTHROUGH */
  372         case SIOCSIFADDR:
  373         case SIOCSIFDSTADDR:
  374                 if (ifra->ifra_addr.sin_family != AF_INET)
  375                         return (EAFNOSUPPORT);
  376                 /* FALLTHROUGH */
  377         case SIOCSIFNETMASK:
  378                 if (ifp == NULL)
  379                         panic("in_control");
  380 
  381                 if (cmd == SIOCGIFALIAS)
  382                         break;
  383 
  384                 if (ia == NULL &&
  385                     (cmd == SIOCSIFNETMASK || cmd == SIOCSIFDSTADDR))
  386                         return (EADDRNOTAVAIL);
  387 
  388                 if (l == NULL)
  389                         return (EPERM);
  390                 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
  391                     KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
  392                     NULL) != 0)
  393                         return (EPERM);
  394 
  395                 if (ia == 0) {
  396                         MALLOC(ia, struct in_ifaddr *, sizeof(*ia),
  397                                M_IFADDR, M_WAITOK);
  398                         if (ia == 0)
  399                                 return (ENOBUFS);
  400                         bzero((void *)ia, sizeof *ia);
  401                         TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_list);
  402                         IFAREF(&ia->ia_ifa);
  403                         ifa_insert(ifp, &ia->ia_ifa);
  404                         ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
  405                         ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
  406                         ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
  407 #ifdef IPSELSRC
  408                         ia->ia_ifa.ifa_getifa = in_getifa;
  409 #else /* IPSELSRC */
  410                         ia->ia_ifa.ifa_getifa = NULL;
  411 #endif /* IPSELSRC */
  412                         ia->ia_sockmask.sin_len = 8;
  413                         if (ifp->if_flags & IFF_BROADCAST) {
  414                                 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
  415                                 ia->ia_broadaddr.sin_family = AF_INET;
  416                         }
  417                         ia->ia_ifp = ifp;
  418                         ia->ia_idsalt = arc4random() % 65535;
  419                         LIST_INIT(&ia->ia_multiaddrs);
  420                         newifaddr = 1;
  421                 }
  422                 break;
  423 
  424         case SIOCSIFBRDADDR:
  425                 if (l == NULL)
  426                         return (EPERM);
  427                 if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
  428                     KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
  429                     NULL) != 0)
  430                         return (EPERM);
  431                 /* FALLTHROUGH */
  432 
  433         case SIOCGIFADDR:
  434         case SIOCGIFNETMASK:
  435         case SIOCGIFDSTADDR:
  436         case SIOCGIFBRDADDR:
  437                 if (ia == 0)
  438                         return (EADDRNOTAVAIL);
  439                 break;
  440         }
  441         error = 0;
  442         switch (cmd) {
  443 
  444         case SIOCGIFADDR:
  445                 ifreq_setaddr(cmd, ifr, sintocsa(&ia->ia_addr));
  446                 break;
  447 
  448         case SIOCGIFBRDADDR:
  449                 if ((ifp->if_flags & IFF_BROADCAST) == 0)
  450                         return (EINVAL);
  451                 ifreq_setdstaddr(cmd, ifr, sintocsa(&ia->ia_broadaddr));
  452                 break;
  453 
  454         case SIOCGIFDSTADDR:
  455                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  456                         return (EINVAL);
  457                 ifreq_setdstaddr(cmd, ifr, sintocsa(&ia->ia_dstaddr));
  458                 break;
  459 
  460         case SIOCGIFNETMASK:
  461                 ifreq_setaddr(cmd, ifr, sintocsa(&ia->ia_sockmask));
  462                 break;
  463 
  464         case SIOCSIFDSTADDR:
  465                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  466                         return (EINVAL);
  467                 oldaddr = ia->ia_dstaddr;
  468                 ia->ia_dstaddr = *satocsin(ifreq_getdstaddr(cmd, ifr));
  469                 if (ifp->if_ioctl != NULL &&
  470                     (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
  471                                               (void *)ia)) != 0) {
  472                         ia->ia_dstaddr = oldaddr;
  473                         return error;
  474                 }
  475                 if (ia->ia_flags & IFA_ROUTE) {
  476                         ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
  477                         rtinit(&ia->ia_ifa, RTM_DELETE, RTF_HOST);
  478                         ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
  479                         rtinit(&ia->ia_ifa, RTM_ADD, RTF_HOST|RTF_UP);
  480                 }
  481                 break;
  482 
  483         case SIOCSIFBRDADDR:
  484                 if ((ifp->if_flags & IFF_BROADCAST) == 0)
  485                         return EINVAL;
  486                 ia->ia_broadaddr = *satocsin(ifreq_getbroadaddr(cmd, ifr));
  487                 break;
  488 
  489         case SIOCSIFADDR:
  490                 error = in_ifinit(ifp, ia, satocsin(ifreq_getaddr(cmd, ifr)),
  491                     1);
  492 #ifdef PFIL_HOOKS
  493                 if (error == 0)
  494                         (void)pfil_run_hooks(&if_pfil,
  495                             (struct mbuf **)SIOCSIFADDR, ifp, PFIL_IFADDR);
  496 #endif
  497                 break;
  498 
  499         case SIOCSIFNETMASK:
  500                 in_ifscrub(ifp, ia);
  501                 ia->ia_sockmask = *satocsin(ifreq_getaddr(cmd, ifr));
  502                 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
  503                 error = in_ifinit(ifp, ia, NULL, 0);
  504                 break;
  505 
  506         case SIOCAIFADDR:
  507                 maskIsNew = 0;
  508                 hostIsNew = 1;
  509                 if (ia->ia_addr.sin_family != AF_INET)
  510                         ;
  511                 else if (ifra->ifra_addr.sin_len == 0) {
  512                         ifra->ifra_addr = ia->ia_addr;
  513                         hostIsNew = 0;
  514                 } else if (in_hosteq(ia->ia_addr.sin_addr,
  515                            ifra->ifra_addr.sin_addr))
  516                         hostIsNew = 0;
  517                 if (ifra->ifra_mask.sin_len) {
  518                         in_ifscrub(ifp, ia);
  519                         ia->ia_sockmask = ifra->ifra_mask;
  520                         ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
  521                         maskIsNew = 1;
  522                 }
  523                 if ((ifp->if_flags & IFF_POINTOPOINT) &&
  524                     (ifra->ifra_dstaddr.sin_family == AF_INET)) {
  525                         in_ifscrub(ifp, ia);
  526                         ia->ia_dstaddr = ifra->ifra_dstaddr;
  527                         maskIsNew  = 1; /* We lie; but the effect's the same */
  528                 }
  529                 if (ifra->ifra_addr.sin_family == AF_INET &&
  530                     (hostIsNew || maskIsNew)) {
  531                         error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  532                 }
  533                 if ((ifp->if_flags & IFF_BROADCAST) &&
  534                     (ifra->ifra_broadaddr.sin_family == AF_INET))
  535                         ia->ia_broadaddr = ifra->ifra_broadaddr;
  536 #ifdef PFIL_HOOKS
  537                 if (error == 0)
  538                         (void)pfil_run_hooks(&if_pfil,
  539                             (struct mbuf **)SIOCAIFADDR, ifp, PFIL_IFADDR);
  540 #endif
  541                 break;
  542 
  543         case SIOCGIFALIAS:
  544                 ifra->ifra_mask = ia->ia_sockmask;
  545                 if ((ifp->if_flags & IFF_POINTOPOINT) &&
  546                     (ia->ia_dstaddr.sin_family == AF_INET))
  547                         ifra->ifra_dstaddr = ia->ia_dstaddr;
  548                 else if ((ifp->if_flags & IFF_BROADCAST) &&
  549                     (ia->ia_broadaddr.sin_family == AF_INET))
  550                         ifra->ifra_broadaddr = ia->ia_broadaddr;
  551                 else
  552                         memset(&ifra->ifra_broadaddr, 0,
  553                               sizeof(ifra->ifra_broadaddr));
  554                 break;
  555 
  556         case SIOCDIFADDR:
  557                 in_purgeaddr(&ia->ia_ifa);
  558 #ifdef PFIL_HOOKS
  559                 (void)pfil_run_hooks(&if_pfil, (struct mbuf **)SIOCDIFADDR,
  560                     ifp, PFIL_IFADDR);
  561 #endif
  562                 break;
  563 
  564 #ifdef MROUTING
  565         case SIOCGETVIFCNT:
  566         case SIOCGETSGCNT:
  567                 error = mrt_ioctl(so, cmd, data);
  568                 break;
  569 #endif /* MROUTING */
  570 
  571         default:
  572                 if (ifp == NULL || ifp->if_ioctl == NULL)
  573                         return EOPNOTSUPP;
  574                 error = (*ifp->if_ioctl)(ifp, cmd, data);
  575                 in_setmaxmtu();
  576                 break;
  577         }
  578 
  579         if (error != 0 && newifaddr) {
  580                 KASSERT(ia != NULL);
  581                 in_purgeaddr(&ia->ia_ifa);
  582         }
  583 
  584         return error;
  585 }
  586 
  587 void
  588 in_purgeaddr(struct ifaddr *ifa)
  589 {
  590         struct ifnet *ifp = ifa->ifa_ifp;
  591         struct in_ifaddr *ia = (void *) ifa;
  592 
  593         in_ifscrub(ifp, ia);
  594         LIST_REMOVE(ia, ia_hash);
  595         ifa_remove(ifp, &ia->ia_ifa);
  596         TAILQ_REMOVE(&in_ifaddrhead, ia, ia_list);
  597         if (ia->ia_allhosts != NULL)
  598                 in_delmulti(ia->ia_allhosts);
  599         IFAFREE(&ia->ia_ifa);
  600         in_setmaxmtu();
  601 }
  602 
  603 void
  604 in_purgeif(struct ifnet *ifp)           /* MUST be called at splsoftnet() */
  605 {
  606         if_purgeaddrs(ifp, AF_INET, in_purgeaddr);
  607         igmp_purgeif(ifp);              /* manipulates pools */
  608 #ifdef MROUTING
  609         ip_mrouter_detach(ifp);
  610 #endif
  611 }
  612 
  613 /*
  614  * SIOC[GAD]LIFADDR.
  615  *      SIOCGLIFADDR: get first address. (???)
  616  *      SIOCGLIFADDR with IFLR_PREFIX:
  617  *              get first address that matches the specified prefix.
  618  *      SIOCALIFADDR: add the specified address.
  619  *      SIOCALIFADDR with IFLR_PREFIX:
  620  *              EINVAL since we can't deduce hostid part of the address.
  621  *      SIOCDLIFADDR: delete the specified address.
  622  *      SIOCDLIFADDR with IFLR_PREFIX:
  623  *              delete the first address that matches the specified prefix.
  624  * return values:
  625  *      EINVAL on invalid parameters
  626  *      EADDRNOTAVAIL on prefix match failed/specified address not found
  627  *      other values may be returned from in_ioctl()
  628  */
  629 static int
  630 in_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
  631     struct ifnet *ifp, struct lwp *l)
  632 {
  633         struct if_laddrreq *iflr = (struct if_laddrreq *)data;
  634         struct ifaddr *ifa;
  635         struct sockaddr *sa;
  636 
  637         /* sanity checks */
  638         if (data == NULL || ifp == NULL) {
  639                 panic("invalid argument to in_lifaddr_ioctl");
  640                 /*NOTRECHED*/
  641         }
  642 
  643         switch (cmd) {
  644         case SIOCGLIFADDR:
  645                 /* address must be specified on GET with IFLR_PREFIX */
  646                 if ((iflr->flags & IFLR_PREFIX) == 0)
  647                         break;
  648                 /*FALLTHROUGH*/
  649         case SIOCALIFADDR:
  650         case SIOCDLIFADDR:
  651                 /* address must be specified on ADD and DELETE */
  652                 sa = (struct sockaddr *)&iflr->addr;
  653                 if (sa->sa_family != AF_INET)
  654                         return EINVAL;
  655                 if (sa->sa_len != sizeof(struct sockaddr_in))
  656                         return EINVAL;
  657                 /* XXX need improvement */
  658                 sa = (struct sockaddr *)&iflr->dstaddr;
  659                 if (sa->sa_family != AF_UNSPEC && sa->sa_family != AF_INET)
  660                         return EINVAL;
  661                 if (sa->sa_len != 0 && sa->sa_len != sizeof(struct sockaddr_in))
  662                         return EINVAL;
  663                 break;
  664         default: /*shouldn't happen*/
  665 #if 0
  666                 panic("invalid cmd to in_lifaddr_ioctl");
  667                 /*NOTREACHED*/
  668 #else
  669                 return EOPNOTSUPP;
  670 #endif
  671         }
  672         if (sizeof(struct in_addr) * NBBY < iflr->prefixlen)
  673                 return EINVAL;
  674 
  675         switch (cmd) {
  676         case SIOCALIFADDR:
  677             {
  678                 struct in_aliasreq ifra;
  679 
  680                 if (iflr->flags & IFLR_PREFIX)
  681                         return EINVAL;
  682 
  683                 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR). */
  684                 bzero(&ifra, sizeof(ifra));
  685                 bcopy(iflr->iflr_name, ifra.ifra_name,
  686                         sizeof(ifra.ifra_name));
  687 
  688                 bcopy(&iflr->addr, &ifra.ifra_addr,
  689                         ((struct sockaddr *)&iflr->addr)->sa_len);
  690 
  691                 if (((struct sockaddr *)&iflr->dstaddr)->sa_family) {   /*XXX*/
  692                         bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
  693                                 ((struct sockaddr *)&iflr->dstaddr)->sa_len);
  694                 }
  695 
  696                 ifra.ifra_mask.sin_family = AF_INET;
  697                 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
  698                 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
  699 
  700                 return in_control(so, SIOCAIFADDR, (void *)&ifra, ifp, l);
  701             }
  702         case SIOCGLIFADDR:
  703         case SIOCDLIFADDR:
  704             {
  705                 struct in_ifaddr *ia;
  706                 struct in_addr mask, candidate, match;
  707                 struct sockaddr_in *sin;
  708                 int cmp;
  709 
  710                 bzero(&mask, sizeof(mask));
  711                 bzero(&match, sizeof(match));   /* XXX gcc */
  712                 if (iflr->flags & IFLR_PREFIX) {
  713                         /* lookup a prefix rather than address. */
  714                         in_len2mask(&mask, iflr->prefixlen);
  715 
  716                         sin = (struct sockaddr_in *)&iflr->addr;
  717                         match.s_addr = sin->sin_addr.s_addr;
  718                         match.s_addr &= mask.s_addr;
  719 
  720                         /* if you set extra bits, that's wrong */
  721                         if (match.s_addr != sin->sin_addr.s_addr)
  722                                 return EINVAL;
  723 
  724                         cmp = 1;
  725                 } else {
  726                         if (cmd == SIOCGLIFADDR) {
  727                                 /* on getting an address, take the 1st match */
  728                                 cmp = 0;        /*XXX*/
  729                         } else {
  730                                 /* on deleting an address, do exact match */
  731                                 in_len2mask(&mask, 32);
  732                                 sin = (struct sockaddr_in *)&iflr->addr;
  733                                 match.s_addr = sin->sin_addr.s_addr;
  734 
  735                                 cmp = 1;
  736                         }
  737                 }
  738 
  739                 IFADDR_FOREACH(ifa, ifp) {
  740                         if (ifa->ifa_addr->sa_family != AF_INET)
  741                                 continue;
  742                         if (cmp == 0)
  743                                 break;
  744                         candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
  745                         candidate.s_addr &= mask.s_addr;
  746                         if (candidate.s_addr == match.s_addr)
  747                                 break;
  748                 }
  749                 if (ifa == NULL)
  750                         return EADDRNOTAVAIL;
  751                 ia = (struct in_ifaddr *)ifa;
  752 
  753                 if (cmd == SIOCGLIFADDR) {
  754                         /* fill in the if_laddrreq structure */
  755                         bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
  756 
  757                         if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
  758                                 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
  759                                         ia->ia_dstaddr.sin_len);
  760                         } else
  761                                 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
  762 
  763                         iflr->prefixlen =
  764                                 in_mask2len(&ia->ia_sockmask.sin_addr);
  765 
  766                         iflr->flags = 0;        /*XXX*/
  767 
  768                         return 0;
  769                 } else {
  770                         struct in_aliasreq ifra;
  771 
  772                         /* fill in_aliasreq and do ioctl(SIOCDIFADDR) */
  773                         bzero(&ifra, sizeof(ifra));
  774                         bcopy(iflr->iflr_name, ifra.ifra_name,
  775                                 sizeof(ifra.ifra_name));
  776 
  777                         bcopy(&ia->ia_addr, &ifra.ifra_addr,
  778                                 ia->ia_addr.sin_len);
  779                         if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
  780                                 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
  781                                         ia->ia_dstaddr.sin_len);
  782                         }
  783                         bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
  784                                 ia->ia_sockmask.sin_len);
  785 
  786                         return in_control(so, SIOCDIFADDR, (void *)&ifra,
  787                                 ifp, l);
  788                 }
  789             }
  790         }
  791 
  792         return EOPNOTSUPP;      /*just for safety*/
  793 }
  794 
  795 static int
  796 in_ifaddrpref_ioctl(struct socket *so, u_long cmd, void *data,
  797     struct ifnet *ifp)
  798 {
  799         struct if_addrprefreq *ifap = (struct if_addrprefreq *)data;
  800         struct ifaddr *ifa;
  801         struct sockaddr *sa;
  802         struct in_ifaddr *ia = NULL; /* appease gcc -Wuninitialized */
  803         struct in_addr match;
  804         struct sockaddr_in *sin;
  805 
  806         /* sanity checks */
  807         if (data == NULL || ifp == NULL) {
  808                 panic("invalid argument to %s", __func__);
  809                 /*NOTREACHED*/
  810         }
  811 
  812         /* address must be specified on ADD and DELETE */
  813         sa = (struct sockaddr *)&ifap->ifap_addr;
  814         if (sa->sa_family != AF_INET)
  815                 return EINVAL;
  816         if (sa->sa_len != sizeof(struct sockaddr_in))
  817                 return EINVAL;
  818 
  819         switch (cmd) {
  820         case SIOCSIFADDRPREF:
  821         case SIOCGIFADDRPREF:
  822                 break;
  823         default:
  824                 return EOPNOTSUPP;
  825         }
  826 
  827         sin = (struct sockaddr_in *)&ifap->ifap_addr;
  828         match.s_addr = sin->sin_addr.s_addr;
  829 
  830         IFADDR_FOREACH(ifa, ifp) {
  831                 ia = (struct in_ifaddr *)ifa;
  832                 if (ia->ia_addr.sin_family != AF_INET)
  833                         continue;
  834                 if (ia->ia_addr.sin_addr.s_addr == match.s_addr)
  835                         break;
  836         }
  837         if (ifa == NULL)
  838                 return EADDRNOTAVAIL;
  839 
  840         switch (cmd) {
  841         case SIOCSIFADDRPREF:
  842                 ifa->ifa_preference = ifap->ifap_preference;
  843                 return 0;
  844         case SIOCGIFADDRPREF:
  845                 /* fill in the if_laddrreq structure */
  846                 (void)memcpy(&ifap->ifap_addr, &ia->ia_addr,
  847                     ia->ia_addr.sin_len);
  848                 ifap->ifap_preference = ifa->ifa_preference;
  849                 return 0;
  850         default:
  851                 return EOPNOTSUPP;
  852         }
  853 }
  854 
  855 /*
  856  * Delete any existing route for an interface.
  857  */
  858 void
  859 in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
  860 {
  861 
  862         in_scrubprefix(ia);
  863 }
  864 
  865 /*
  866  * Initialize an interface's internet address
  867  * and routing table entry.
  868  */
  869 int
  870 in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia,
  871     const struct sockaddr_in *sin, int scrub)
  872 {
  873         u_int32_t i;
  874         struct sockaddr_in oldaddr;
  875         int s = splnet(), flags = RTF_UP, error;
  876 
  877         if (sin == NULL)
  878                 sin = &ia->ia_addr;
  879 
  880         /*
  881          * Set up new addresses.
  882          */
  883         oldaddr = ia->ia_addr;
  884         if (ia->ia_addr.sin_family == AF_INET)
  885                 LIST_REMOVE(ia, ia_hash);
  886         ia->ia_addr = *sin;
  887         LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
  888 
  889         /*
  890          * Give the interface a chance to initialize
  891          * if this is its first address,
  892          * and to validate the address if necessary.
  893          */
  894         if (ifp->if_ioctl &&
  895             (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (void *)ia)))
  896                 goto bad;
  897         splx(s);
  898         if (scrub) {
  899                 ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
  900                 in_ifscrub(ifp, ia);
  901                 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
  902         }
  903 
  904         i = ia->ia_addr.sin_addr.s_addr;
  905         if (IN_CLASSA(i))
  906                 ia->ia_netmask = IN_CLASSA_NET;
  907         else if (IN_CLASSB(i))
  908                 ia->ia_netmask = IN_CLASSB_NET;
  909         else
  910                 ia->ia_netmask = IN_CLASSC_NET;
  911         /*
  912          * The subnet mask usually includes at least the standard network part,
  913          * but may may be smaller in the case of supernetting.
  914          * If it is set, we believe it.
  915          */
  916         if (ia->ia_subnetmask == 0) {
  917                 ia->ia_subnetmask = ia->ia_netmask;
  918                 ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask;
  919         } else
  920                 ia->ia_netmask &= ia->ia_subnetmask;
  921 
  922         ia->ia_net = i & ia->ia_netmask;
  923         ia->ia_subnet = i & ia->ia_subnetmask;
  924         in_socktrim(&ia->ia_sockmask);
  925         /* re-calculate the "in_maxmtu" value */
  926         in_setmaxmtu();
  927         /*
  928          * Add route for the network.
  929          */
  930         ia->ia_ifa.ifa_metric = ifp->if_metric;
  931         if (ifp->if_flags & IFF_BROADCAST) {
  932                 ia->ia_broadaddr.sin_addr.s_addr =
  933                         ia->ia_subnet | ~ia->ia_subnetmask;
  934                 ia->ia_netbroadcast.s_addr =
  935                         ia->ia_net | ~ia->ia_netmask;
  936         } else if (ifp->if_flags & IFF_LOOPBACK) {
  937                 ia->ia_dstaddr = ia->ia_addr;
  938                 flags |= RTF_HOST;
  939         } else if (ifp->if_flags & IFF_POINTOPOINT) {
  940                 if (ia->ia_dstaddr.sin_family != AF_INET)
  941                         return (0);
  942                 flags |= RTF_HOST;
  943         }
  944         error = in_addprefix(ia, flags);
  945         /*
  946          * If the interface supports multicast, join the "all hosts"
  947          * multicast group on that interface.
  948          */
  949         if ((ifp->if_flags & IFF_MULTICAST) != 0 && ia->ia_allhosts == NULL) {
  950                 struct in_addr addr;
  951 
  952                 addr.s_addr = INADDR_ALLHOSTS_GROUP;
  953                 ia->ia_allhosts = in_addmulti(&addr, ifp);
  954         }
  955         return (error);
  956 bad:
  957         splx(s);
  958         LIST_REMOVE(ia, ia_hash);
  959         ia->ia_addr = oldaddr;
  960         if (ia->ia_addr.sin_family == AF_INET)
  961                 LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
  962                     ia, ia_hash);
  963         return (error);
  964 }
  965 
  966 #define rtinitflags(x) \
  967         ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
  968             ? RTF_HOST : 0)
  969 
  970 /*
  971  * add a route to prefix ("connected route" in cisco terminology).
  972  * does nothing if there's some interface address with the same prefix already.
  973  */
  974 static int
  975 in_addprefix(struct in_ifaddr *target, int flags)
  976 {
  977         struct in_ifaddr *ia;
  978         struct in_addr prefix, mask, p;
  979         int error;
  980 
  981         if ((flags & RTF_HOST) != 0)
  982                 prefix = target->ia_dstaddr.sin_addr;
  983         else {
  984                 prefix = target->ia_addr.sin_addr;
  985                 mask = target->ia_sockmask.sin_addr;
  986                 prefix.s_addr &= mask.s_addr;
  987         }
  988 
  989         TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list) {
  990                 if (rtinitflags(ia))
  991                         p = ia->ia_dstaddr.sin_addr;
  992                 else {
  993                         p = ia->ia_addr.sin_addr;
  994                         p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
  995                 }
  996 
  997                 if (prefix.s_addr != p.s_addr)
  998                         continue;
  999 
 1000                 /*
 1001                  * if we got a matching prefix route inserted by other
 1002                  * interface address, we don't need to bother
 1003                  *
 1004                  * XXX RADIX_MPATH implications here? -dyoung
 1005                  */
 1006                 if (ia->ia_flags & IFA_ROUTE)
 1007                         return 0;
 1008         }
 1009 
 1010         /*
 1011          * noone seem to have prefix route.  insert it.
 1012          */
 1013         error = rtinit(&target->ia_ifa, RTM_ADD, flags);
 1014         if (error == 0)
 1015                 target->ia_flags |= IFA_ROUTE;
 1016         else if (error == EEXIST) {
 1017                 /* 
 1018                  * the fact the route already exists is not an error.
 1019                  */ 
 1020                 error = 0;
 1021         }
 1022         return error;
 1023 }
 1024 
 1025 /*
 1026  * remove a route to prefix ("connected route" in cisco terminology).
 1027  * re-installs the route by using another interface address, if there's one
 1028  * with the same prefix (otherwise we lose the route mistakenly).
 1029  */
 1030 static int
 1031 in_scrubprefix(struct in_ifaddr *target)
 1032 {
 1033         struct in_ifaddr *ia;
 1034         struct in_addr prefix, mask, p;
 1035         int error;
 1036 
 1037         if ((target->ia_flags & IFA_ROUTE) == 0)
 1038                 return 0;
 1039 
 1040         if (rtinitflags(target))
 1041                 prefix = target->ia_dstaddr.sin_addr;
 1042         else {
 1043                 prefix = target->ia_addr.sin_addr;
 1044                 mask = target->ia_sockmask.sin_addr;
 1045                 prefix.s_addr &= mask.s_addr;
 1046         }
 1047 
 1048         TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list) {
 1049                 if (rtinitflags(ia))
 1050                         p = ia->ia_dstaddr.sin_addr;
 1051                 else {
 1052                         p = ia->ia_addr.sin_addr;
 1053                         p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
 1054                 }
 1055 
 1056                 if (prefix.s_addr != p.s_addr)
 1057                         continue;
 1058 
 1059                 /*
 1060                  * if we got a matching prefix route, move IFA_ROUTE to him
 1061                  */
 1062                 if ((ia->ia_flags & IFA_ROUTE) == 0) {
 1063                         rtinit(&target->ia_ifa, RTM_DELETE,
 1064                             rtinitflags(target));
 1065                         target->ia_flags &= ~IFA_ROUTE;
 1066 
 1067                         error = rtinit(&ia->ia_ifa, RTM_ADD,
 1068                             rtinitflags(ia) | RTF_UP);
 1069                         if (error == 0)
 1070                                 ia->ia_flags |= IFA_ROUTE;
 1071                         return error;
 1072                 }
 1073         }
 1074 
 1075         /*
 1076          * noone seem to have prefix route.  remove it.
 1077          */
 1078         rtinit(&target->ia_ifa, RTM_DELETE, rtinitflags(target));
 1079         target->ia_flags &= ~IFA_ROUTE;
 1080         return 0;
 1081 }
 1082 
 1083 #undef rtinitflags
 1084 
 1085 /*
 1086  * Return 1 if the address might be a local broadcast address.
 1087  */
 1088 int
 1089 in_broadcast(struct in_addr in, struct ifnet *ifp)
 1090 {
 1091         struct ifaddr *ifa;
 1092 
 1093         if (in.s_addr == INADDR_BROADCAST ||
 1094             in_nullhost(in))
 1095                 return 1;
 1096         if ((ifp->if_flags & IFF_BROADCAST) == 0)
 1097                 return 0;
 1098         /*
 1099          * Look through the list of addresses for a match
 1100          * with a broadcast address.
 1101          */
 1102 #define ia (ifatoia(ifa))
 1103         IFADDR_FOREACH(ifa, ifp)
 1104                 if (ifa->ifa_addr->sa_family == AF_INET &&
 1105                     !in_hosteq(in, ia->ia_addr.sin_addr) &&
 1106                     (in_hosteq(in, ia->ia_broadaddr.sin_addr) ||
 1107                      in_hosteq(in, ia->ia_netbroadcast) ||
 1108                      (hostzeroisbroadcast &&
 1109                       /*
 1110                        * Check for old-style (host 0) broadcast.
 1111                        */
 1112                       (in.s_addr == ia->ia_subnet ||
 1113                        in.s_addr == ia->ia_net))))
 1114                         return 1;
 1115         return (0);
 1116 #undef ia
 1117 }
 1118 
 1119 /*
 1120  * Add an address to the list of IP multicast addresses for a given interface.
 1121  */
 1122 struct in_multi *
 1123 in_addmulti(struct in_addr *ap, struct ifnet *ifp)
 1124 {
 1125         struct sockaddr_in sin;
 1126         struct in_multi *inm;
 1127         struct ifreq ifr;
 1128         int s = splsoftnet();
 1129 
 1130         /*
 1131          * See if address already in list.
 1132          */
 1133         IN_LOOKUP_MULTI(*ap, ifp, inm);
 1134         if (inm != NULL) {
 1135                 /*
 1136                  * Found it; just increment the reference count.
 1137                  */
 1138                 ++inm->inm_refcount;
 1139         } else {
 1140                 /*
 1141                  * New address; allocate a new multicast record
 1142                  * and link it into the interface's multicast list.
 1143                  */
 1144                 inm = pool_get(&inmulti_pool, PR_NOWAIT);
 1145                 if (inm == NULL) {
 1146                         splx(s);
 1147                         return (NULL);
 1148                 }
 1149                 inm->inm_addr = *ap;
 1150                 inm->inm_ifp = ifp;
 1151                 inm->inm_refcount = 1;
 1152                 LIST_INSERT_HEAD(
 1153                     &IN_MULTI_HASH(inm->inm_addr.s_addr, ifp),
 1154                     inm, inm_list);
 1155                 /*
 1156                  * Ask the network driver to update its multicast reception
 1157                  * filter appropriately for the new address.
 1158                  */
 1159                 sockaddr_in_init(&sin, ap, 0);
 1160                 ifreq_setaddr(SIOCADDMULTI, &ifr, sintosa(&sin));
 1161                 if ((ifp->if_ioctl == NULL) ||
 1162                     (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(void *)&ifr) != 0) {
 1163                         LIST_REMOVE(inm, inm_list);
 1164                         pool_put(&inmulti_pool, inm);
 1165                         splx(s);
 1166                         return (NULL);
 1167                 }
 1168                 /*
 1169                  * Let IGMP know that we have joined a new IP multicast group.
 1170                  */
 1171                 if (igmp_joingroup(inm) != 0) {
 1172                         LIST_REMOVE(inm, inm_list);
 1173                         pool_put(&inmulti_pool, inm);
 1174                         splx(s);
 1175                         return (NULL);
 1176                 }
 1177                 in_multientries++;
 1178         }
 1179         splx(s);
 1180         return (inm);
 1181 }
 1182 
 1183 /*
 1184  * Delete a multicast address record.
 1185  */
 1186 void
 1187 in_delmulti(struct in_multi *inm)
 1188 {
 1189         struct sockaddr_in sin;
 1190         struct ifreq ifr;
 1191         int s = splsoftnet();
 1192 
 1193         if (--inm->inm_refcount == 0) {
 1194                 /*
 1195                  * No remaining claims to this record; let IGMP know that
 1196                  * we are leaving the multicast group.
 1197                  */
 1198                 igmp_leavegroup(inm);
 1199                 /*
 1200                  * Unlink from list.
 1201                  */
 1202                 LIST_REMOVE(inm, inm_list);
 1203                 in_multientries--;
 1204                 /*
 1205                  * Notify the network driver to update its multicast reception
 1206                  * filter.
 1207                  */
 1208                 sockaddr_in_init(&sin, &inm->inm_addr, 0);
 1209                 ifreq_setaddr(SIOCDELMULTI, &ifr, sintosa(&sin));
 1210                 (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
 1211                                                              (void *)&ifr);
 1212                 pool_put(&inmulti_pool, inm);
 1213         }
 1214         splx(s);
 1215 }

Cache object: f3478677349e27ed323d5a2ee0de0008


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