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

Cache object: 615ac11a10b70a794564c0b5247c3bfb


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