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/netinet6/scope6.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 /*      $FreeBSD: releng/5.0/sys/netinet6/scope6.c 93128 2002-03-25 10:12:51Z ume $     */
    2 /*      $KAME: scope6.c,v 1.10 2000/07/24 13:29:31 itojun Exp $ */
    3 
    4 /*
    5  * Copyright (C) 2000 WIDE Project.
    6  * All rights reserved.
    7  * 
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the project nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  * 
   20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/malloc.h>
   35 #include <sys/mbuf.h>
   36 #include <sys/socket.h>
   37 #include <sys/systm.h>
   38 #include <sys/queue.h>
   39 
   40 #include <net/route.h>
   41 #include <net/if.h>
   42 
   43 #include <netinet/in.h>
   44 
   45 #include <netinet6/in6_var.h>
   46 #include <netinet6/scope6_var.h>
   47 
   48 struct scope6_id {
   49         /*
   50          * 16 is correspondent to 4bit multicast scope field.
   51          * i.e. from node-local to global with some reserved/unassigned types.
   52          */
   53         u_int32_t s6id_list[16];
   54 };
   55 static size_t if_indexlim = 8;
   56 struct scope6_id *scope6_ids = NULL;
   57 
   58 void
   59 scope6_ifattach(ifp)
   60         struct ifnet *ifp;
   61 {
   62         int s = splnet();
   63 
   64         /*
   65          * We have some arrays that should be indexed by if_index.
   66          * since if_index will grow dynamically, they should grow too.
   67          */
   68         if (scope6_ids == NULL || if_index >= if_indexlim) {
   69                 size_t n;
   70                 caddr_t q;
   71 
   72                 while (if_index >= if_indexlim)
   73                         if_indexlim <<= 1;
   74 
   75                 /* grow scope index array */
   76                 n = if_indexlim * sizeof(struct scope6_id);
   77                 /* XXX: need new malloc type? */
   78                 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
   79                 bzero(q, n);
   80                 if (scope6_ids) {
   81                         bcopy((caddr_t)scope6_ids, q, n/2);
   82                         free((caddr_t)scope6_ids, M_IFADDR);
   83                 }
   84                 scope6_ids = (struct scope6_id *)q;
   85         }
   86 
   87 #define SID scope6_ids[ifp->if_index]
   88 
   89         /* don't initialize if called twice */
   90         if (SID.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL]) {
   91                 splx(s);
   92                 return;
   93         }
   94 
   95         /*
   96          * XXX: IPV6_ADDR_SCOPE_xxx macros are not standard.
   97          * Should we rather hardcode here?
   98          */
   99         SID.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = ifp->if_index;
  100 #ifdef MULTI_SCOPE
  101         /* by default, we don't care about scope boundary for these scopes. */
  102         SID.s6id_list[IPV6_ADDR_SCOPE_SITELOCAL] = 1;
  103         SID.s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL] = 1;
  104 #endif
  105 #undef SID
  106 
  107         splx(s);
  108 }
  109 
  110 int
  111 scope6_set(ifp, idlist)
  112         struct ifnet *ifp;
  113         u_int32_t *idlist;
  114 {
  115         int i, s;
  116         int error = 0;
  117 
  118         if (scope6_ids == NULL) /* paranoid? */
  119                 return(EINVAL);
  120 
  121         /*
  122          * XXX: We need more consistency checks of the relationship among
  123          * scopes (e.g. an organization should be larger than a site).
  124          */
  125 
  126         /*
  127          * TODO(XXX): after setting, we should reflect the changes to
  128          * interface addresses, routing table entries, PCB entries... 
  129          */
  130 
  131         s = splnet();
  132 
  133         for (i = 0; i < 16; i++) {
  134                 if (idlist[i] &&
  135                     idlist[i] != scope6_ids[ifp->if_index].s6id_list[i]) {
  136                         if (i == IPV6_ADDR_SCOPE_LINKLOCAL &&
  137                             idlist[i] > if_index) {
  138                                 /*
  139                                  * XXX: theoretically, there should be no
  140                                  * relationship between link IDs and interface
  141                                  * IDs, but we check the consistency for
  142                                  * safety in later use.
  143                                  */
  144                                 splx(s);
  145                                 return(EINVAL);
  146                         }
  147 
  148                         /*
  149                          * XXX: we must need lots of work in this case,
  150                          * but we simply set the new value in this initial
  151                          * implementation.
  152                          */
  153                         scope6_ids[ifp->if_index].s6id_list[i] = idlist[i];
  154                 }
  155         }
  156         splx(s);
  157 
  158         return(error);
  159 }
  160 
  161 int
  162 scope6_get(ifp, idlist)
  163         struct ifnet *ifp;
  164         u_int32_t *idlist;
  165 {
  166         if (scope6_ids == NULL) /* paranoid? */
  167                 return(EINVAL);
  168 
  169         bcopy(scope6_ids[ifp->if_index].s6id_list, idlist,
  170               sizeof(scope6_ids[ifp->if_index].s6id_list));
  171 
  172         return(0);
  173 }
  174 
  175 
  176 /*
  177  * Get a scope of the address. Node-local, link-local, site-local or global.
  178  */
  179 int
  180 in6_addrscope(addr)
  181 struct in6_addr *addr;
  182 {
  183         int scope;
  184 
  185         if (addr->s6_addr8[0] == 0xfe) {
  186                 scope = addr->s6_addr8[1] & 0xc0;
  187 
  188                 switch (scope) {
  189                 case 0x80:
  190                         return IPV6_ADDR_SCOPE_LINKLOCAL;
  191                         break;
  192                 case 0xc0:
  193                         return IPV6_ADDR_SCOPE_SITELOCAL;
  194                         break;
  195                 default:
  196                         return IPV6_ADDR_SCOPE_GLOBAL; /* just in case */
  197                         break;
  198                 }
  199         }
  200 
  201 
  202         if (addr->s6_addr8[0] == 0xff) {
  203                 scope = addr->s6_addr8[1] & 0x0f;
  204 
  205                 /*
  206                  * due to other scope such as reserved,
  207                  * return scope doesn't work.
  208                  */
  209                 switch (scope) {
  210                 case IPV6_ADDR_SCOPE_NODELOCAL:
  211                         return IPV6_ADDR_SCOPE_NODELOCAL;
  212                         break;
  213                 case IPV6_ADDR_SCOPE_LINKLOCAL:
  214                         return IPV6_ADDR_SCOPE_LINKLOCAL;
  215                         break;
  216                 case IPV6_ADDR_SCOPE_SITELOCAL:
  217                         return IPV6_ADDR_SCOPE_SITELOCAL;
  218                         break;
  219                 default:
  220                         return IPV6_ADDR_SCOPE_GLOBAL;
  221                         break;
  222                 }
  223         }
  224 
  225         if (bcmp(&in6addr_loopback, addr, sizeof(*addr) - 1) == 0) {
  226                 if (addr->s6_addr8[15] == 1) /* loopback */
  227                         return IPV6_ADDR_SCOPE_NODELOCAL;
  228                 if (addr->s6_addr8[15] == 0) /* unspecified */
  229                         return IPV6_ADDR_SCOPE_LINKLOCAL;
  230         }
  231 
  232         return IPV6_ADDR_SCOPE_GLOBAL;
  233 }
  234 
  235 int
  236 in6_addr2scopeid(ifp, addr)
  237         struct ifnet *ifp;      /* must not be NULL */
  238         struct in6_addr *addr;  /* must not be NULL */
  239 {
  240         int scope = in6_addrscope(addr);
  241 
  242         if (scope6_ids == NULL) /* paranoid? */
  243                 return(0);      /* XXX */
  244         if (ifp->if_index >= if_indexlim)
  245                 return(0);      /* XXX */
  246 
  247 #define SID scope6_ids[ifp->if_index]
  248         switch(scope) {
  249         case IPV6_ADDR_SCOPE_NODELOCAL:
  250                 return(-1);     /* XXX: is this an appropriate value? */
  251 
  252         case IPV6_ADDR_SCOPE_LINKLOCAL:
  253                 return(SID.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL]);
  254 
  255         case IPV6_ADDR_SCOPE_SITELOCAL:
  256                 return(SID.s6id_list[IPV6_ADDR_SCOPE_SITELOCAL]);
  257 
  258         case IPV6_ADDR_SCOPE_ORGLOCAL:
  259                 return(SID.s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL]);
  260 
  261         default:
  262                 return(0);      /* XXX: treat as global. */
  263         }
  264 #undef SID
  265 }
  266 
  267 void
  268 scope6_setdefault(ifp)
  269         struct ifnet *ifp;      /* note that this might be NULL */
  270 {
  271         /*
  272          * Currently, this function just set the default "link" according to
  273          * the given interface.
  274          * We might eventually have to separate the notion of "link" from
  275          * "interface" and provide a user interface to set the default.
  276          */
  277         if (ifp) {
  278                 scope6_ids[0].s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] =
  279                         ifp->if_index;
  280         }
  281         else
  282                 scope6_ids[0].s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 0;
  283 }
  284 
  285 int
  286 scope6_get_default(idlist)
  287         u_int32_t *idlist;
  288 {
  289         if (scope6_ids == NULL) /* paranoid? */
  290                 return(EINVAL);
  291 
  292         bcopy(scope6_ids[0].s6id_list, idlist,
  293               sizeof(scope6_ids[0].s6id_list));
  294 
  295         return(0);
  296 }
  297 
  298 u_int32_t
  299 scope6_addr2default(addr)
  300         struct in6_addr *addr;
  301 {
  302         return(scope6_ids[0].s6id_list[in6_addrscope(addr)]);
  303 }

Cache object: e339702559293618277955f71f6976e1


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