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

Cache object: 4bd53549639e3a694249fe98c9991401


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