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


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