root/netinet/in.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. in_localaddr
  2. in_canforward
  3. in_socktrim
  4. in_mask2len
  5. in_len2mask
  6. in_control
  7. in_lifaddr_ioctl
  8. in_ifscrub
  9. in_ifinit
  10. in_addprefix
  11. in_scrubprefix
  12. in_broadcast
  13. in_addmulti
  14. in_delmulti

    1 /*      $OpenBSD: in.c,v 1.49 2007/07/20 19:00:35 claudio Exp $ */
    2 /*      $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
    3 
    4 /*
    5  * Copyright (C) 2001 WIDE Project.  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) 1982, 1986, 1991, 1993
   34  *      The Regents of the University of California.  All rights reserved.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. Neither the name of the University nor the names of its contributors
   45  *    may be used to endorse or promote products derived from this software
   46  *    without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)in.c        8.2 (Berkeley) 11/15/93
   61  */
   62 
   63 #include <sys/param.h>
   64 #include <sys/systm.h>
   65 #include <sys/ioctl.h>
   66 #include <sys/malloc.h>
   67 #include <sys/socket.h>
   68 #include <sys/socketvar.h>
   69 
   70 #include <net/if.h>
   71 #include <net/route.h>
   72 
   73 #include "carp.h"
   74 #if NCARP > 0
   75 #include <net/if_types.h>
   76 #endif
   77 
   78 #include <netinet/in.h>
   79 #include <netinet/in_var.h>
   80 #include <netinet/igmp_var.h>
   81 
   82 #ifdef MROUTING
   83 #include <netinet/ip_mroute.h>
   84 #endif
   85 
   86 #include "ether.h"
   87 
   88 #ifdef INET
   89 
   90 int in_mask2len(struct in_addr *);
   91 void in_len2mask(struct in_addr *, int);
   92 int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
   93         struct ifnet *);
   94 
   95 int in_addprefix(struct in_ifaddr *, int);
   96 int in_scrubprefix(struct in_ifaddr *);
   97 
   98 #ifndef SUBNETSARELOCAL
   99 #define SUBNETSARELOCAL 0
  100 #endif
  101 
  102 #ifndef HOSTZEROBROADCAST
  103 #define HOSTZEROBROADCAST 1
  104 #endif
  105 
  106 int subnetsarelocal = SUBNETSARELOCAL;
  107 int hostzeroisbroadcast = HOSTZEROBROADCAST;
  108 
  109 /*
  110  * Return 1 if an internet address is for a ``local'' host
  111  * (one to which we have a connection).  If subnetsarelocal
  112  * is true, this includes other subnets of the local net.
  113  * Otherwise, it includes only the directly-connected (sub)nets.
  114  */
  115 int
  116 in_localaddr(in)
  117         struct in_addr in;
  118 {
  119         struct in_ifaddr *ia;
  120 
  121         if (subnetsarelocal) {
  122                 TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
  123                         if ((in.s_addr & ia->ia_netmask) == ia->ia_net)
  124                                 return (1);
  125         } else {
  126                 TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
  127                         if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet)
  128                                 return (1);
  129         }
  130         return (0);
  131 }
  132 
  133 /*
  134  * Determine whether an IP address is in a reserved set of addresses
  135  * that may not be forwarded, or whether datagrams to that destination
  136  * may be forwarded.
  137  */
  138 int
  139 in_canforward(in)
  140         struct in_addr in;
  141 {
  142         u_int32_t net;
  143 
  144         if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr))
  145                 return (0);
  146         if (IN_CLASSA(in.s_addr)) {
  147                 net = in.s_addr & IN_CLASSA_NET;
  148                 if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
  149                         return (0);
  150         }
  151         return (1);
  152 }
  153 
  154 /*
  155  * Trim a mask in a sockaddr
  156  */
  157 void
  158 in_socktrim(ap)
  159         struct sockaddr_in *ap;
  160 {
  161         char *cplim = (char *) &ap->sin_addr;
  162         char *cp = (char *) (&ap->sin_addr + 1);
  163 
  164         ap->sin_len = 0;
  165         while (--cp >= cplim)
  166                 if (*cp) {
  167                         (ap)->sin_len = cp - (char *) (ap) + 1;
  168                         break;
  169                 }
  170 }
  171 
  172 int
  173 in_mask2len(mask)
  174         struct in_addr *mask;
  175 {
  176         int x, y;
  177         u_char *p;
  178 
  179         p = (u_char *)mask;
  180         for (x = 0; x < sizeof(*mask); x++) {
  181                 if (p[x] != 0xff)
  182                         break;
  183         }
  184         y = 0;
  185         if (x < sizeof(*mask)) {
  186                 for (y = 0; y < 8; y++) {
  187                         if ((p[x] & (0x80 >> y)) == 0)
  188                                 break;
  189                 }
  190         }
  191         return x * 8 + y;
  192 }
  193 
  194 void
  195 in_len2mask(mask, len)
  196         struct in_addr *mask;
  197         int len;
  198 {
  199         int i;
  200         u_char *p;
  201 
  202         p = (u_char *)mask;
  203         bzero(mask, sizeof(*mask));
  204         for (i = 0; i < len / 8; i++)
  205                 p[i] = 0xff;
  206         if (len % 8)
  207                 p[i] = (0xff00 >> (len % 8)) & 0xff;
  208 }
  209 
  210 int     in_interfaces;          /* number of external internet interfaces */
  211 
  212 /*
  213  * Generic internet control operations (ioctl's).
  214  * Ifp is 0 if not an interface-specific ioctl.
  215  */
  216 /* ARGSUSED */
  217 int
  218 in_control(so, cmd, data, ifp)
  219         struct socket *so;
  220         u_long cmd;
  221         caddr_t data;
  222         struct ifnet *ifp;
  223 {
  224         struct ifreq *ifr = (struct ifreq *)data;
  225         struct in_ifaddr *ia = 0;
  226         struct in_aliasreq *ifra = (struct in_aliasreq *)data;
  227         struct sockaddr_in oldaddr;
  228         int error, hostIsNew, maskIsNew;
  229         int newifaddr;
  230         int s;
  231 
  232         switch (cmd) {
  233         case SIOCALIFADDR:
  234         case SIOCDLIFADDR:
  235                 if ((so->so_state & SS_PRIV) == 0)
  236                         return (EPERM);
  237                 /* FALLTHROUGH */
  238         case SIOCGLIFADDR:
  239                 if (!ifp)
  240                         return EINVAL;
  241                 return in_lifaddr_ioctl(so, cmd, data, ifp);
  242         }
  243 
  244         /*
  245          * Find address for this interface, if it exists.
  246          */
  247         if (ifp)
  248                 TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
  249                         if (ia->ia_ifp == ifp)
  250                                 break;
  251 
  252         switch (cmd) {
  253 
  254         case SIOCAIFADDR:
  255         case SIOCDIFADDR:
  256                 if (ifra->ifra_addr.sin_family == AF_INET)
  257                         for (; ia != TAILQ_END(&in_ifaddr);
  258                             ia = TAILQ_NEXT(ia, ia_list)) {
  259                                 if (ia->ia_ifp == ifp &&
  260                                     ia->ia_addr.sin_addr.s_addr ==
  261                                         ifra->ifra_addr.sin_addr.s_addr)
  262                                     break;
  263                         }
  264                 if (cmd == SIOCDIFADDR && ia == 0)
  265                         return (EADDRNOTAVAIL);
  266                 /* FALLTHROUGH */
  267         case SIOCSIFADDR:
  268         case SIOCSIFNETMASK:
  269         case SIOCSIFDSTADDR:
  270                 if ((so->so_state & SS_PRIV) == 0)
  271                         return (EPERM);
  272 
  273                 if (ifp == 0)
  274                         panic("in_control");
  275                 if (ia == (struct in_ifaddr *)0) {
  276                         ia = (struct in_ifaddr *)
  277                                 malloc(sizeof *ia, M_IFADDR, M_WAITOK);
  278                         bzero((caddr_t)ia, sizeof *ia);
  279                         s = splsoftnet();
  280                         TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list);
  281                         TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
  282                             ifa_list);
  283                         ia->ia_addr.sin_family = AF_INET;
  284                         ia->ia_addr.sin_len = sizeof(ia->ia_addr);
  285                         ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
  286                         ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
  287                         ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
  288                         ia->ia_sockmask.sin_len = 8;
  289                         if (ifp->if_flags & IFF_BROADCAST) {
  290                                 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
  291                                 ia->ia_broadaddr.sin_family = AF_INET;
  292                         }
  293                         ia->ia_ifp = ifp;
  294                         LIST_INIT(&ia->ia_multiaddrs);
  295                         if ((ifp->if_flags & IFF_LOOPBACK) == 0)
  296                                 in_interfaces++;
  297                         splx(s);
  298 
  299                         newifaddr = 1;
  300                 } else
  301                         newifaddr = 0;
  302                 break;
  303 
  304         case SIOCSIFBRDADDR:
  305                 if ((so->so_state & SS_PRIV) == 0)
  306                         return (EPERM);
  307                 /* FALLTHROUGH */
  308 
  309         case SIOCGIFADDR:
  310         case SIOCGIFNETMASK:
  311         case SIOCGIFDSTADDR:
  312         case SIOCGIFBRDADDR:
  313                 if (ia && satosin(&ifr->ifr_addr)->sin_addr.s_addr) {
  314                         struct in_ifaddr *ia2;
  315 
  316                         for (ia2 = ia; ia2 != TAILQ_END(&in_ifaddr);
  317                             ia2 = TAILQ_NEXT(ia2, ia_list)) {
  318                                 if (ia2->ia_ifp == ifp &&
  319                                     ia2->ia_addr.sin_addr.s_addr ==
  320                                     satosin(&ifr->ifr_addr)->sin_addr.s_addr)
  321                                         break;
  322                         }
  323                         if (ia2 && ia2->ia_ifp == ifp)
  324                                 ia = ia2;
  325                 }
  326                 if (ia == (struct in_ifaddr *)0)
  327                         return (EADDRNOTAVAIL);
  328                 break;
  329         }
  330         switch (cmd) {
  331 
  332         case SIOCGIFADDR:
  333                 *satosin(&ifr->ifr_addr) = ia->ia_addr;
  334                 break;
  335 
  336         case SIOCGIFBRDADDR:
  337                 if ((ifp->if_flags & IFF_BROADCAST) == 0)
  338                         return (EINVAL);
  339                 *satosin(&ifr->ifr_dstaddr) = ia->ia_broadaddr;
  340                 break;
  341 
  342         case SIOCGIFDSTADDR:
  343                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  344                         return (EINVAL);
  345                 *satosin(&ifr->ifr_dstaddr) = ia->ia_dstaddr;
  346                 break;
  347 
  348         case SIOCGIFNETMASK:
  349                 *satosin(&ifr->ifr_addr) = ia->ia_sockmask;
  350                 break;
  351 
  352         case SIOCSIFDSTADDR:
  353                 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
  354                         return (EINVAL);
  355                 s = splsoftnet();
  356                 oldaddr = ia->ia_dstaddr;
  357                 ia->ia_dstaddr = *satosin(&ifr->ifr_dstaddr);
  358                 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
  359                                         (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
  360                         ia->ia_dstaddr = oldaddr;
  361                         splx(s);
  362                         return (error);
  363                 }
  364                 if (ia->ia_flags & IFA_ROUTE) {
  365                         ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
  366                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
  367                         ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
  368                         rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
  369                 }
  370                 splx(s);
  371                 break;
  372 
  373         case SIOCSIFBRDADDR:
  374                 if ((ifp->if_flags & IFF_BROADCAST) == 0)
  375                         return (EINVAL);
  376                 ia->ia_broadaddr = *satosin(&ifr->ifr_broadaddr);
  377                 break;
  378 
  379         case SIOCSIFADDR:
  380                 s = splsoftnet();
  381                 error = in_ifinit(ifp, ia, satosin(&ifr->ifr_addr), 1);
  382                 if (!error)
  383                         dohooks(ifp->if_addrhooks, 0);
  384                 else if (newifaddr) {
  385                         splx(s);
  386                         goto cleanup;
  387                 }
  388                 splx(s);
  389                 return error;
  390 
  391         case SIOCSIFNETMASK:
  392                 ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr =
  393                     ifra->ifra_addr.sin_addr.s_addr;
  394                 break;
  395 
  396         case SIOCAIFADDR:
  397                 maskIsNew = 0;
  398                 hostIsNew = 1;
  399                 error = 0;
  400                 s = splsoftnet();
  401                 if (ia->ia_addr.sin_family == AF_INET) {
  402                         if (ifra->ifra_addr.sin_len == 0) {
  403                                 ifra->ifra_addr = ia->ia_addr;
  404                                 hostIsNew = 0;
  405                         } else if (ifra->ifra_addr.sin_addr.s_addr ==
  406                                                ia->ia_addr.sin_addr.s_addr)
  407                                 hostIsNew = 0;
  408                 }
  409                 if (ifra->ifra_mask.sin_len) {
  410                         in_ifscrub(ifp, ia);
  411                         ia->ia_sockmask = ifra->ifra_mask;
  412                         ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
  413                         maskIsNew = 1;
  414                 }
  415                 if ((ifp->if_flags & IFF_POINTOPOINT) &&
  416                     (ifra->ifra_dstaddr.sin_family == AF_INET)) {
  417                         in_ifscrub(ifp, ia);
  418                         ia->ia_dstaddr = ifra->ifra_dstaddr;
  419                         maskIsNew  = 1; /* We lie; but the effect's the same */
  420                 }
  421                 if (ifra->ifra_addr.sin_family == AF_INET &&
  422                     (hostIsNew || maskIsNew)) {
  423                         error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
  424                 }
  425                 if ((ifp->if_flags & IFF_BROADCAST) &&
  426                     (ifra->ifra_broadaddr.sin_family == AF_INET))
  427                         ia->ia_broadaddr = ifra->ifra_broadaddr;
  428                 if (!error)
  429                         dohooks(ifp->if_addrhooks, 0);
  430                 else if (newifaddr) {
  431                         splx(s);
  432                         goto cleanup;
  433                 }
  434                 splx(s);
  435                 return (error);
  436 
  437         case SIOCDIFADDR: {
  438 
  439                 error = 0;
  440 cleanup:
  441                 /*
  442                  * Even if the individual steps were safe, shouldn't
  443                  * these kinds of changes happen atomically?  What 
  444                  * should happen to a packet that was routed after
  445                  * the scrub but before the other steps? 
  446                  */
  447                 s = splsoftnet();
  448                 in_ifscrub(ifp, ia);
  449                 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
  450                 TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
  451                 if (ia->ia_allhosts != NULL) {
  452                         in_delmulti(ia->ia_allhosts);
  453                         ia->ia_allhosts = NULL;
  454                 }
  455                 IFAFREE((&ia->ia_ifa));
  456                 dohooks(ifp->if_addrhooks, 0);
  457                 splx(s);
  458                 return (error);
  459                 }
  460 
  461 #ifdef MROUTING
  462         case SIOCGETVIFCNT:
  463         case SIOCGETSGCNT:
  464                 return (mrt_ioctl(so, cmd, data));
  465 #endif /* MROUTING */
  466 
  467         default:
  468                 if (ifp == 0 || ifp->if_ioctl == 0)
  469                         return (EOPNOTSUPP);
  470                 return ((*ifp->if_ioctl)(ifp, cmd, data));
  471         }
  472         return (0);
  473 }
  474 
  475 /*
  476  * SIOC[GAD]LIFADDR.
  477  *      SIOCGLIFADDR: get first address. (???)
  478  *      SIOCGLIFADDR with IFLR_PREFIX:
  479  *              get first address that matches the specified prefix.
  480  *      SIOCALIFADDR: add the specified address.
  481  *      SIOCALIFADDR with IFLR_PREFIX:
  482  *              EINVAL since we can't deduce hostid part of the address.
  483  *      SIOCDLIFADDR: delete the specified address.
  484  *      SIOCDLIFADDR with IFLR_PREFIX:
  485  *              delete the first address that matches the specified prefix.
  486  * return values:
  487  *      EINVAL on invalid parameters
  488  *      EADDRNOTAVAIL on prefix match failed/specified address not found
  489  *      other values may be returned from in_ioctl()
  490  */
  491 int
  492 in_lifaddr_ioctl(so, cmd, data, ifp)
  493         struct socket *so;
  494         u_long cmd;
  495         caddr_t data;
  496         struct ifnet *ifp;
  497 {
  498         struct if_laddrreq *iflr = (struct if_laddrreq *)data;
  499         struct ifaddr *ifa;
  500         struct sockaddr *sa;
  501 
  502         /* sanity checks */
  503         if (!data || !ifp) {
  504                 panic("invalid argument to in_lifaddr_ioctl");
  505                 /*NOTRECHED*/
  506         }
  507 
  508         switch (cmd) {
  509         case SIOCGLIFADDR:
  510                 /* address must be specified on GET with IFLR_PREFIX */
  511                 if ((iflr->flags & IFLR_PREFIX) == 0)
  512                         break;
  513                 /*FALLTHROUGH*/
  514         case SIOCALIFADDR:
  515         case SIOCDLIFADDR:
  516                 /* address must be specified on ADD and DELETE */
  517                 sa = (struct sockaddr *)&iflr->addr;
  518                 if (sa->sa_family != AF_INET)
  519                         return EINVAL;
  520                 if (sa->sa_len != sizeof(struct sockaddr_in))
  521                         return EINVAL;
  522                 /* XXX need improvement */
  523                 sa = (struct sockaddr *)&iflr->dstaddr;
  524                 if (sa->sa_family
  525                  && sa->sa_family != AF_INET)
  526                         return EINVAL;
  527                 if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in))
  528                         return EINVAL;
  529                 break;
  530         default: /*shouldn't happen*/
  531 #if 0
  532                 panic("invalid cmd to in_lifaddr_ioctl");
  533                 /*NOTREACHED*/
  534 #else
  535                 return EOPNOTSUPP;
  536 #endif
  537         }
  538         if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
  539                 return EINVAL;
  540 
  541         switch (cmd) {
  542         case SIOCALIFADDR:
  543             {
  544                 struct in_aliasreq ifra;
  545 
  546                 if (iflr->flags & IFLR_PREFIX)
  547                         return EINVAL;
  548 
  549                 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR). */
  550                 bzero(&ifra, sizeof(ifra));
  551                 bcopy(iflr->iflr_name, ifra.ifra_name,
  552                         sizeof(ifra.ifra_name));
  553 
  554                 bcopy(&iflr->addr, &ifra.ifra_addr,
  555                         ((struct sockaddr *)&iflr->addr)->sa_len);
  556 
  557                 if (((struct sockaddr *)&iflr->dstaddr)->sa_family) {   /*XXX*/
  558                         bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
  559                                 ((struct sockaddr *)&iflr->dstaddr)->sa_len);
  560                 }
  561 
  562                 ifra.ifra_mask.sin_family = AF_INET;
  563                 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
  564                 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
  565 
  566                 return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp);
  567             }
  568         case SIOCGLIFADDR:
  569         case SIOCDLIFADDR:
  570             {
  571                 struct in_ifaddr *ia;
  572                 struct in_addr mask, candidate, match;
  573                 struct sockaddr_in *sin;
  574                 int cmp;
  575 
  576                 bzero(&mask, sizeof(mask));
  577                 if (iflr->flags & IFLR_PREFIX) {
  578                         /* lookup a prefix rather than address. */
  579                         in_len2mask(&mask, iflr->prefixlen);
  580 
  581                         sin = (struct sockaddr_in *)&iflr->addr;
  582                         match.s_addr = sin->sin_addr.s_addr;
  583                         match.s_addr &= mask.s_addr;
  584 
  585                         /* if you set extra bits, that's wrong */
  586                         if (match.s_addr != sin->sin_addr.s_addr)
  587                                 return EINVAL;
  588 
  589                         cmp = 1;
  590                 } else {
  591                         if (cmd == SIOCGLIFADDR) {
  592                                 /* on getting an address, take the 1st match */
  593                                 cmp = 0;        /*XXX*/
  594                         } else {
  595                                 /* on deleting an address, do exact match */
  596                                 in_len2mask(&mask, 32);
  597                                 sin = (struct sockaddr_in *)&iflr->addr;
  598                                 match.s_addr = sin->sin_addr.s_addr;
  599 
  600                                 cmp = 1;
  601                         }
  602                 }
  603 
  604                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  605                         if (ifa->ifa_addr->sa_family != AF_INET)
  606                                 continue;
  607                         if (!cmp)
  608                                 break;
  609                         candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
  610                         candidate.s_addr &= mask.s_addr;
  611                         if (candidate.s_addr == match.s_addr)
  612                                 break;
  613                 }
  614                 if (!ifa)
  615                         return EADDRNOTAVAIL;
  616                 ia = (struct in_ifaddr *)ifa;
  617 
  618                 if (cmd == SIOCGLIFADDR) {
  619                         /* fill in the if_laddrreq structure */
  620                         bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
  621 
  622                         if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
  623                                 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
  624                                         ia->ia_dstaddr.sin_len);
  625                         } else
  626                                 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
  627 
  628                         iflr->prefixlen =
  629                                 in_mask2len(&ia->ia_sockmask.sin_addr);
  630 
  631                         iflr->flags = 0;        /*XXX*/
  632 
  633                         return 0;
  634                 } else {
  635                         struct in_aliasreq ifra;
  636 
  637                         /* fill in_aliasreq and do ioctl(SIOCDIFADDR) */
  638                         bzero(&ifra, sizeof(ifra));
  639                         bcopy(iflr->iflr_name, ifra.ifra_name,
  640                                 sizeof(ifra.ifra_name));
  641 
  642                         bcopy(&ia->ia_addr, &ifra.ifra_addr,
  643                                 ia->ia_addr.sin_len);
  644                         if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
  645                                 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
  646                                         ia->ia_dstaddr.sin_len);
  647                         }
  648                         bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
  649                                 ia->ia_sockmask.sin_len);
  650 
  651                         return in_control(so, SIOCDIFADDR, (caddr_t)&ifra, ifp);
  652                 }
  653             }
  654         }
  655 
  656         return EOPNOTSUPP;      /*just for safety*/
  657 }
  658 
  659 /*
  660  * Delete any existing route for an interface.
  661  */
  662 void
  663 in_ifscrub(ifp, ia)
  664         struct ifnet *ifp;
  665         struct in_ifaddr *ia;
  666 {
  667         in_scrubprefix(ia);
  668 }
  669 
  670 /*
  671  * Initialize an interface's internet address
  672  * and routing table entry.
  673  */
  674 int
  675 in_ifinit(ifp, ia, sin, scrub)
  676         struct ifnet *ifp;
  677         struct in_ifaddr *ia;
  678         struct sockaddr_in *sin;
  679         int scrub;
  680 {
  681         u_int32_t i = sin->sin_addr.s_addr;
  682         struct sockaddr_in oldaddr;
  683         int s = splnet(), flags = RTF_UP, error;
  684 
  685         oldaddr = ia->ia_addr;
  686         ia->ia_addr = *sin;
  687         /*
  688          * Give the interface a chance to initialize
  689          * if this is its first address,
  690          * and to validate the address if necessary.
  691          */
  692         if (ifp->if_ioctl &&
  693             (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
  694                 ia->ia_addr = oldaddr;
  695                 splx(s);
  696                 return (error);
  697         }
  698         splx(s);
  699 
  700         /*
  701          * How should a packet be routed during
  702          * an address change--and is it safe?
  703          * Is the "ifp" even in a consistent state?
  704          * Be safe for now.
  705          */
  706         splassert(IPL_SOFTNET);
  707 
  708         if (scrub) {
  709                 ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
  710                 in_ifscrub(ifp, ia);
  711                 ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
  712         }
  713         if (IN_CLASSA(i))
  714                 ia->ia_netmask = IN_CLASSA_NET;
  715         else if (IN_CLASSB(i))
  716                 ia->ia_netmask = IN_CLASSB_NET;
  717         else
  718                 ia->ia_netmask = IN_CLASSC_NET;
  719         /*
  720          * The subnet mask usually includes at least the standard network part,
  721          * but may may be smaller in the case of supernetting.
  722          * If it is set, we believe it.
  723          */
  724         if (ia->ia_subnetmask == 0) {
  725                 ia->ia_subnetmask = ia->ia_netmask;
  726                 ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask;
  727         } else
  728                 ia->ia_netmask &= ia->ia_subnetmask;
  729         ia->ia_net = i & ia->ia_netmask;
  730         ia->ia_subnet = i & ia->ia_subnetmask;
  731         in_socktrim(&ia->ia_sockmask);
  732         /*
  733          * Add route for the network.
  734          */
  735         ia->ia_ifa.ifa_metric = ifp->if_metric;
  736         if (ifp->if_flags & IFF_BROADCAST) {
  737                 ia->ia_broadaddr.sin_addr.s_addr =
  738                         ia->ia_subnet | ~ia->ia_subnetmask;
  739                 ia->ia_netbroadcast.s_addr =
  740                         ia->ia_net | ~ia->ia_netmask;
  741         } else if (ifp->if_flags & IFF_LOOPBACK) {
  742                 ia->ia_dstaddr = ia->ia_addr;
  743                 flags |= RTF_HOST;
  744         } else if (ifp->if_flags & IFF_POINTOPOINT) {
  745                 if (ia->ia_dstaddr.sin_family != AF_INET)
  746                         return (0);
  747                 flags |= RTF_HOST;
  748         }
  749         error = in_addprefix(ia, flags);
  750         /*
  751          * If the interface supports multicast, join the "all hosts"
  752          * multicast group on that interface.
  753          */
  754         if ((ifp->if_flags & IFF_MULTICAST) && ia->ia_allhosts == NULL) {
  755                 struct in_addr addr;
  756 
  757                 addr.s_addr = INADDR_ALLHOSTS_GROUP;
  758                 ia->ia_allhosts = in_addmulti(&addr, ifp);
  759         }
  760         return (error);
  761 }
  762 
  763 #define rtinitflags(x) \
  764         ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
  765             ? RTF_HOST : 0)
  766 
  767 /*
  768  * add a route to prefix ("connected route" in cisco terminology).
  769  * does nothing if there's some interface address with the same prefix already.
  770  */
  771 int
  772 in_addprefix(target, flags)
  773         struct in_ifaddr *target;
  774         int flags;
  775 {
  776         struct in_ifaddr *ia;
  777         struct in_addr prefix, mask, p;
  778         int error;
  779 
  780         if ((flags & RTF_HOST) != 0)
  781                 prefix = target->ia_dstaddr.sin_addr;
  782         else {
  783                 prefix = target->ia_addr.sin_addr;
  784                 mask = target->ia_sockmask.sin_addr;
  785                 prefix.s_addr &= mask.s_addr;
  786         }
  787 
  788         TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
  789                 if (rtinitflags(ia)) {
  790                         p = ia->ia_dstaddr.sin_addr;
  791                         if (prefix.s_addr != p.s_addr)
  792                                 continue;
  793                 } else {
  794                         p = ia->ia_addr.sin_addr;
  795                         p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
  796                         if (prefix.s_addr != p.s_addr ||
  797                             mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
  798                                 continue;
  799                 }
  800                 if ((ia->ia_flags & IFA_ROUTE) == 0)
  801                         continue;
  802 #if NCARP > 0
  803                 /* move to a real interface instead of carp interface */
  804                 if (ia->ia_ifp->if_type == IFT_CARP &&
  805                     target->ia_ifp->if_type != IFT_CARP) {
  806                         rtinit(&(ia->ia_ifa), (int)RTM_DELETE,
  807                             rtinitflags(ia));
  808                         ia->ia_flags &= ~IFA_ROUTE;
  809                         break;
  810                 }
  811 #endif
  812                 /*
  813                  * if we got a matching prefix route inserted by other
  814                  * interface adderss, we don't need to bother
  815                  */
  816                 return 0;
  817         }
  818 
  819         /*
  820          * noone seem to have prefix route.  insert it.
  821          */
  822         error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
  823         if (!error)
  824                 target->ia_flags |= IFA_ROUTE;
  825         return error;
  826 }
  827 
  828 /*
  829  * remove a route to prefix ("connected route" in cisco terminology).
  830  * re-installs the route by using another interface address, if there's one
  831  * with the same prefix (otherwise we lose the route mistakenly).
  832  */
  833 int
  834 in_scrubprefix(target)
  835         struct in_ifaddr *target;
  836 {
  837         struct in_ifaddr *ia;
  838         struct in_addr prefix, mask, p;
  839         int error;
  840 
  841         if ((target->ia_flags & IFA_ROUTE) == 0)
  842                 return 0;
  843 
  844         if (rtinitflags(target))
  845                 prefix = target->ia_dstaddr.sin_addr;
  846         else {
  847                 prefix = target->ia_addr.sin_addr;
  848                 mask = target->ia_sockmask.sin_addr;
  849                 prefix.s_addr &= mask.s_addr;
  850         }
  851 
  852         TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
  853                 if (rtinitflags(ia))
  854                         p = ia->ia_dstaddr.sin_addr;
  855                 else {
  856                         p = ia->ia_addr.sin_addr;
  857                         p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
  858                 }
  859 
  860                 if (prefix.s_addr != p.s_addr)
  861                         continue;
  862 
  863                 /*
  864                  * if we got a matching prefix route, move IFA_ROUTE to him
  865                  */
  866                 if ((ia->ia_flags & IFA_ROUTE) == 0) {
  867                         rtinit(&(target->ia_ifa), (int)RTM_DELETE,
  868                             rtinitflags(target));
  869                         target->ia_flags &= ~IFA_ROUTE;
  870 
  871                         error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
  872                             rtinitflags(ia) | RTF_UP);
  873                         if (error == 0)
  874                                 ia->ia_flags |= IFA_ROUTE;
  875                         return error;
  876                 }
  877         }
  878 
  879         /*
  880          * noone seem to have prefix route.  remove it.
  881          */
  882         rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
  883         target->ia_flags &= ~IFA_ROUTE;
  884         return 0;
  885 }
  886 
  887 #undef rtinitflags
  888 
  889 /*
  890  * Return 1 if the address might be a local broadcast address.
  891  */
  892 int
  893 in_broadcast(in, ifp)
  894         struct in_addr in;
  895         struct ifnet *ifp;
  896 {
  897         struct ifnet *ifn, *if_first, *if_target;
  898         struct ifaddr *ifa;
  899 
  900         if (in.s_addr == INADDR_BROADCAST ||
  901             in.s_addr == INADDR_ANY)
  902                 return 1;
  903 
  904         if (ifp == NULL) {
  905                 if_first = TAILQ_FIRST(&ifnet);
  906                 if_target = 0;
  907         } else {
  908                 if_first = ifp;
  909                 if_target = TAILQ_NEXT(ifp, if_list);
  910         }
  911 
  912 #define ia (ifatoia(ifa))
  913         /*
  914          * Look through the list of addresses for a match
  915          * with a broadcast address.
  916          * If ifp is NULL, check against all the interfaces.
  917          */
  918         for (ifn = if_first; ifn != if_target; ifn = TAILQ_NEXT(ifn, if_list)) {
  919                 if ((ifn->if_flags & IFF_BROADCAST) == 0)
  920                         continue;
  921                 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list)
  922                         if (ifa->ifa_addr->sa_family == AF_INET &&
  923                             in.s_addr != ia->ia_addr.sin_addr.s_addr &&
  924                             (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
  925                              in.s_addr == ia->ia_netbroadcast.s_addr ||
  926                              (hostzeroisbroadcast &&
  927                               /*
  928                                * Check for old-style (host 0) broadcast.
  929                                */
  930                               (in.s_addr == ia->ia_subnet ||
  931                                in.s_addr == ia->ia_net))))
  932                                 return 1;
  933         }
  934         return (0);
  935 #undef ia
  936 }
  937 
  938 /*
  939  * Add an address to the list of IP multicast addresses for a given interface.
  940  */
  941 struct in_multi *
  942 in_addmulti(ap, ifp)
  943         struct in_addr *ap;
  944         struct ifnet *ifp;
  945 {
  946         struct in_multi *inm;
  947         struct ifreq ifr;
  948         struct in_ifaddr *ia;
  949         int s = splsoftnet();
  950 
  951         /*
  952          * See if address already in list.
  953          */
  954         IN_LOOKUP_MULTI(*ap, ifp, inm);
  955         if (inm != NULL) {
  956                 /*
  957                  * Found it; just increment the reference count.
  958                  */
  959                 ++inm->inm_refcount;
  960         } else {
  961                 /*
  962                  * New address; allocate a new multicast record
  963                  * and link it into the interface's multicast list.
  964                  */
  965                 inm = (struct in_multi *)malloc(sizeof(*inm),
  966                     M_IPMADDR, M_NOWAIT);
  967                 if (inm == NULL) {
  968                         splx(s);
  969                         return (NULL);
  970                 }
  971                 inm->inm_addr = *ap;
  972                 inm->inm_refcount = 1;
  973                 IFP_TO_IA(ifp, ia);
  974                 if (ia == NULL) {
  975                         free(inm, M_IPMADDR);
  976                         splx(s);
  977                         return (NULL);
  978                 }
  979                 inm->inm_ia = ia;
  980                 ia->ia_ifa.ifa_refcnt++;
  981                 LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_list);
  982                 /*
  983                  * Ask the network driver to update its multicast reception
  984                  * filter appropriately for the new address.
  985                  */
  986                 satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
  987                 satosin(&ifr.ifr_addr)->sin_family = AF_INET;
  988                 satosin(&ifr.ifr_addr)->sin_addr = *ap;
  989                 if ((ifp->if_ioctl == NULL) ||
  990                     (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
  991                         LIST_REMOVE(inm, inm_list);
  992                         IFAFREE(&inm->inm_ia->ia_ifa);
  993                         free(inm, M_IPMADDR);
  994                         splx(s);
  995                         return (NULL);
  996                 }
  997                 /*
  998                  * Let IGMP know that we have joined a new IP multicast group.
  999                  */
 1000                 igmp_joingroup(inm);
 1001         }
 1002         splx(s);
 1003         return (inm);
 1004 }
 1005 
 1006 /*
 1007  * Delete a multicast address record.
 1008  */
 1009 void
 1010 in_delmulti(inm)
 1011         struct in_multi *inm;
 1012 {
 1013         struct ifreq ifr;
 1014         struct ifnet *ifp;
 1015         int s = splsoftnet();
 1016 
 1017         if (--inm->inm_refcount == 0) {
 1018                 /*
 1019                  * No remaining claims to this record; let IGMP know that
 1020                  * we are leaving the multicast group.
 1021                  */
 1022                 igmp_leavegroup(inm);
 1023                 /*
 1024                  * Unlink from list.
 1025                  */
 1026                 LIST_REMOVE(inm, inm_list);
 1027                 ifp = inm->inm_ia->ia_ifp;
 1028                 IFAFREE(&inm->inm_ia->ia_ifa);
 1029 
 1030                 if (ifp) {
 1031                         /*
 1032                          * Notify the network driver to update its multicast
 1033                          * reception filter.
 1034                          */
 1035                         satosin(&ifr.ifr_addr)->sin_family = AF_INET;
 1036                         satosin(&ifr.ifr_addr)->sin_addr = inm->inm_addr;
 1037                         (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
 1038                 }
 1039                 free(inm, M_IPMADDR);
 1040         }
 1041         splx(s);
 1042 }
 1043 
 1044 #endif

/* [<][>][^][v][top][bottom][index][help] */