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/in6_src.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 /*      $KAME: in6_src.c,v 1.159 2005/10/19 01:40:32 t-momose 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) 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. All advertising materials mentioning features or use of this software
   45  *    must display the following acknowledgement:
   46  *      This product includes software developed by the University of
   47  *      California, Berkeley and its contributors.
   48  * 4. Neither the name of the University nor the names of its contributors
   49  *    may be used to endorse or promote products derived from this software
   50  *    without specific prior written permission.
   51  *
   52  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   62  * SUCH DAMAGE.
   63  *
   64  *      @(#)in_pcb.c    8.2 (Berkeley) 1/4/94
   65  */
   66 
   67 #include <sys/cdefs.h>
   68 __KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.43 2008/04/15 03:57:04 thorpej Exp $");
   69 
   70 #include "opt_inet.h"
   71 
   72 #include <sys/param.h>
   73 #include <sys/systm.h>
   74 #include <sys/malloc.h>
   75 #include <sys/mbuf.h>
   76 #include <sys/protosw.h>
   77 #include <sys/socket.h>
   78 #include <sys/socketvar.h>
   79 #ifndef __FreeBSD__
   80 #include <sys/ioctl.h>
   81 #else
   82 #include <sys/sockio.h>
   83 #endif
   84 #ifdef __FreeBSD__
   85 #include <sys/sysctl.h>
   86 #endif
   87 #include <sys/errno.h>
   88 #include <sys/time.h>
   89 #include <sys/kernel.h>
   90 #include <sys/proc.h>
   91 #include <sys/kauth.h>
   92 
   93 #include <net/if.h>
   94 #include <net/if_types.h>
   95 #include <net/route.h>
   96 
   97 #include <netinet/in.h>
   98 #include <netinet/in_var.h>
   99 #include <netinet/in_systm.h>
  100 #include <netinet/ip.h>
  101 #include <netinet/in_pcb.h>
  102 #include <netinet6/in6_var.h>
  103 #include <netinet/ip6.h>
  104 #ifndef __OpenBSD__
  105 #include <netinet6/in6_pcb.h>
  106 #endif
  107 #include <netinet6/ip6_var.h>
  108 #include <netinet6/ip6_private.h>
  109 #include <netinet6/nd6.h>
  110 #include <netinet6/scope6_var.h>
  111 
  112 #include <net/net_osdep.h>
  113 
  114 #ifdef MIP6
  115 #include <netinet6/mip6.h>
  116 #include <netinet6/mip6_var.h>
  117 #include "mip.h"
  118 #if NMIP > 0
  119 #include <net/if_mip.h>
  120 #endif /* NMIP > 0 */
  121 #endif /* MIP6 */
  122 
  123 #ifndef __OpenBSD__
  124 #include "loop.h"
  125 #endif
  126 #ifdef __NetBSD__
  127 extern struct ifnet loif[NLOOP];
  128 #endif
  129 
  130 #define ADDR_LABEL_NOTAPP (-1)
  131 struct in6_addrpolicy defaultaddrpolicy;
  132 
  133 #ifdef notyet /* until introducing ND extensions and address selection */
  134 int ip6_prefer_tempaddr = 0;
  135 #endif
  136 
  137 static int selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
  138         struct ip6_moptions *, struct route *, struct ifnet **,
  139         struct rtentry **, int, int);
  140 static int in6_selectif(struct sockaddr_in6 *, struct ip6_pktopts *,
  141         struct ip6_moptions *, struct route *, struct ifnet **);
  142 
  143 static struct in6_addrpolicy *lookup_addrsel_policy(struct sockaddr_in6 *);
  144 
  145 static void init_policy_queue(void);
  146 static int add_addrsel_policyent(struct in6_addrpolicy *);
  147 static int delete_addrsel_policyent(struct in6_addrpolicy *);
  148 static int walk_addrsel_policy(int (*)(struct in6_addrpolicy *, void *),
  149                                     void *);
  150 static int dump_addrsel_policyent(struct in6_addrpolicy *, void *);
  151 static struct in6_addrpolicy *match_addrsel_policy(struct sockaddr_in6 *);
  152 
  153 /*
  154  * Return an IPv6 address, which is the most appropriate for a given
  155  * destination and user specified options.
  156  * If necessary, this function lookups the routing table and returns
  157  * an entry to the caller for later use.
  158  */
  159 #if 0                           /* diabled ad-hoc */
  160 #define REPLACE(r) do {\
  161         if ((r) < sizeof(ip6stat.ip6s_sources_rule) / \
  162                 sizeof(ip6stat.ip6s_sources_rule[0])) /* check for safety */ \
  163                 ip6stat.ip6s_sources_rule[(r)]++; \
  164         /* printf("in6_selectsrc: replace %s with %s by %d\n", ia_best ? ip6_sprintf(&ia_best->ia_addr.sin6_addr) : "none", ip6_sprintf(&ia->ia_addr.sin6_addr), (r)); */ \
  165         goto replace; \
  166 } while(0)
  167 #define NEXT(r) do {\
  168         if ((r) < sizeof(ip6stat.ip6s_sources_rule) / \
  169                 sizeof(ip6stat.ip6s_sources_rule[0])) /* check for safety */ \
  170                 ip6stat.ip6s_sources_rule[(r)]++; \
  171         /* printf("in6_selectsrc: keep %s against %s by %d\n", ia_best ? ip6_sprintf(&ia_best->ia_addr.sin6_addr) : "none", ip6_sprintf(&ia->ia_addr.sin6_addr), (r)); */ \
  172         goto next;              /* XXX: we can't use 'continue' here */ \
  173 } while(0)
  174 #define BREAK(r) do { \
  175         if ((r) < sizeof(ip6stat.ip6s_sources_rule) / \
  176                 sizeof(ip6stat.ip6s_sources_rule[0])) /* check for safety */ \
  177                 ip6stat.ip6s_sources_rule[(r)]++; \
  178         goto out;               /* XXX: we can't use 'break' here */ \
  179 } while(0)
  180 #else
  181 #define REPLACE(r) goto replace
  182 #define NEXT(r) goto next
  183 #define BREAK(r) goto out
  184 #endif
  185 
  186 struct in6_addr *
  187 in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 
  188         struct ip6_moptions *mopts, struct route *ro, struct in6_addr *laddr, 
  189         struct ifnet **ifpp, int *errorp)
  190 {
  191         struct in6_addr dst;
  192         struct ifnet *ifp = NULL;
  193         struct in6_ifaddr *ia = NULL, *ia_best = NULL;
  194         struct in6_pktinfo *pi = NULL;
  195         int dst_scope = -1, best_scope = -1, best_matchlen = -1;
  196         struct in6_addrpolicy *dst_policy = NULL, *best_policy = NULL;
  197         u_int32_t odstzone;
  198         int error;
  199 #ifdef notyet /* until introducing ND extensions and address selection */
  200         int prefer_tempaddr;
  201 #endif
  202 #if defined(MIP6) && NMIP > 0
  203         u_int8_t ip6po_usecoa = 0;
  204 #endif /* MIP6 && NMIP > 0 */
  205 
  206         dst = dstsock->sin6_addr; /* make a copy for local operation */
  207         *errorp = 0;
  208         if (ifpp)
  209                 *ifpp = NULL;
  210 
  211         /*
  212          * Try to determine the outgoing interface for the given destination.
  213          * We do this regardless of whether the socket is bound, since the
  214          * caller may need this information as a side effect of the call
  215          * to this function (e.g., for identifying the appropriate scope zone
  216          * ID).
  217          */
  218         error = in6_selectif(dstsock, opts, mopts, ro, &ifp);
  219         if (ifpp)
  220                 *ifpp = ifp;
  221 
  222         /*
  223          * If the source address is explicitly specified by the caller,
  224          * check if the requested source address is indeed a unicast address
  225          * assigned to the node, and can be used as the packet's source
  226          * address.  If everything is okay, use the address as source.
  227          */
  228         if (opts && (pi = opts->ip6po_pktinfo) &&
  229             !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) {
  230                 struct sockaddr_in6 srcsock;
  231                 struct in6_ifaddr *ia6;
  232 
  233                 /*
  234                  * Determine the appropriate zone id of the source based on
  235                  * the zone of the destination and the outgoing interface.
  236                  * If the specified address is ambiguous wrt the scope zone,
  237                  * the interface must be specified; otherwise, ifa_ifwithaddr()
  238                  * will fail matching the address.
  239                  */
  240                 bzero(&srcsock, sizeof(srcsock));
  241                 srcsock.sin6_family = AF_INET6;
  242                 srcsock.sin6_len = sizeof(srcsock);
  243                 srcsock.sin6_addr = pi->ipi6_addr;
  244                 if (ifp) {
  245                         *errorp = in6_setscope(&srcsock.sin6_addr, ifp, NULL);
  246                         if (*errorp != 0)
  247                                 return (NULL);
  248                 }
  249 
  250                 ia6 = (struct in6_ifaddr *)ifa_ifwithaddr((struct sockaddr *)(&srcsock));
  251                 if (ia6 == NULL ||
  252                     (ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) {
  253                         *errorp = EADDRNOTAVAIL;
  254                         return (NULL);
  255                 }
  256                 pi->ipi6_addr = srcsock.sin6_addr; /* XXX: this overrides pi */
  257                 if (ifpp)
  258                         *ifpp = ifp;
  259                 return (&ia6->ia_addr.sin6_addr);
  260         }
  261 
  262         /*
  263          * If the socket has already bound the source, just use it.  We don't
  264          * care at the moment whether in6_selectif() succeeded above, even
  265          * though it would eventually cause an error.
  266          */
  267         if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr))
  268                 return (laddr);
  269 
  270         /*
  271          * The outgoing interface is crucial in the general selection procedure
  272          * below.  If it is not known at this point, we fail.
  273          */
  274         if (ifp == NULL) {
  275                 *errorp = error;
  276                 return (NULL);
  277         }
  278 
  279         /*
  280          * If the address is not yet determined, choose the best one based on
  281          * the outgoing interface and the destination address.
  282          */
  283 
  284 #if defined(MIP6) && NMIP > 0
  285         /*
  286          * a caller can specify IP6PO_USECOA to not to use a home
  287          * address.  for example, the case that the neighbour
  288          * unreachability detection to the global address.
  289          */
  290         if (opts != NULL &&
  291             (opts->ip6po_flags & IP6PO_USECOA) != 0) {
  292                 ip6po_usecoa = 1;
  293         }
  294 #endif /* MIP6 && NMIP > 0 */
  295 
  296 #ifdef DIAGNOSTIC
  297         if (ifp == NULL)        /* this should not happen */
  298                 panic("in6_selectsrc: NULL ifp");
  299 #endif
  300         *errorp = in6_setscope(&dst, ifp, &odstzone);
  301         if (*errorp != 0)
  302                 return (NULL);
  303 
  304         for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
  305                 int new_scope = -1, new_matchlen = -1;
  306                 struct in6_addrpolicy *new_policy = NULL;
  307                 u_int32_t srczone, osrczone, dstzone;
  308                 struct in6_addr src;
  309                 struct ifnet *ifp1 = ia->ia_ifp;
  310 
  311                 /*
  312                  * We'll never take an address that breaks the scope zone
  313                  * of the destination.  We also skip an address if its zone
  314                  * does not contain the outgoing interface.
  315                  * XXX: we should probably use sin6_scope_id here.
  316                  */
  317                 if (in6_setscope(&dst, ifp1, &dstzone) ||
  318                     odstzone != dstzone) {
  319                         continue;
  320                 }
  321                 src = ia->ia_addr.sin6_addr;
  322                 if (in6_setscope(&src, ifp, &osrczone) ||
  323                     in6_setscope(&src, ifp1, &srczone) ||
  324                     osrczone != srczone) {
  325                         continue;
  326                 }
  327 
  328                 /* avoid unusable addresses */
  329                 if ((ia->ia6_flags &
  330                      (IN6_IFF_NOTREADY | IN6_IFF_ANYCAST | IN6_IFF_DETACHED))) {
  331                                 continue;
  332                 }
  333                 if (!ip6_use_deprecated && IFA6_IS_DEPRECATED(ia))
  334                         continue;
  335 
  336 #if defined(MIP6) && NMIP > 0
  337                 /* avoid unusable home addresses. */
  338                 if ((ia->ia6_flags & IN6_IFF_HOME) &&
  339                     !mip6_ifa6_is_addr_valid_hoa(ia))
  340                         continue;
  341 #endif /* MIP6 && NMIP > 0 */
  342 
  343                 /* Rule 1: Prefer same address */
  344                 if (IN6_ARE_ADDR_EQUAL(&dst, &ia->ia_addr.sin6_addr)) {
  345                         ia_best = ia;
  346                         BREAK(1); /* there should be no better candidate */
  347                 }
  348 
  349                 if (ia_best == NULL)
  350                         REPLACE(0);
  351 
  352                 /* Rule 2: Prefer appropriate scope */
  353                 if (dst_scope < 0)
  354                         dst_scope = in6_addrscope(&dst);
  355                 new_scope = in6_addrscope(&ia->ia_addr.sin6_addr);
  356                 if (IN6_ARE_SCOPE_CMP(best_scope, new_scope) < 0) {
  357                         if (IN6_ARE_SCOPE_CMP(best_scope, dst_scope) < 0)
  358                                 REPLACE(2);
  359                         NEXT(2);
  360                 } else if (IN6_ARE_SCOPE_CMP(new_scope, best_scope) < 0) {
  361                         if (IN6_ARE_SCOPE_CMP(new_scope, dst_scope) < 0)
  362                                 NEXT(2);
  363                         REPLACE(2);
  364                 }
  365 
  366                 /*
  367                  * Rule 3: Avoid deprecated addresses.  Note that the case of
  368                  * !ip6_use_deprecated is already rejected above.
  369                  */
  370                 if (!IFA6_IS_DEPRECATED(ia_best) && IFA6_IS_DEPRECATED(ia))
  371                         NEXT(3);
  372                 if (IFA6_IS_DEPRECATED(ia_best) && !IFA6_IS_DEPRECATED(ia))
  373                         REPLACE(3);
  374 
  375                 /* Rule 4: Prefer home addresses */
  376 #if defined(MIP6) && NMIP > 0
  377                 if (!MIP6_IS_MN)
  378                         goto skip_rule4;
  379 
  380                 if ((ia_best->ia6_flags & IN6_IFF_HOME) == 0 &&
  381                     (ia->ia6_flags & IN6_IFF_HOME) == 0) {
  382                         /* both address are not home addresses. */
  383                         goto skip_rule4;
  384                 }
  385 
  386                 /*
  387                  * If SA is simultaneously a home address and care-of
  388                  * address and SB is not, then prefer SA. Similarly,
  389                  * if SB is simultaneously a home address and care-of
  390                  * address and SA is not, then prefer SB.
  391                  */
  392                 if (((ia_best->ia6_flags & IN6_IFF_HOME) != 0 &&
  393                         ia_best->ia_ifp->if_type != IFT_MIP)
  394                     &&
  395                     ((ia->ia6_flags & IN6_IFF_HOME) != 0 &&
  396                         ia->ia_ifp->if_type == IFT_MIP))
  397                         NEXT(4);
  398                 if (((ia_best->ia6_flags & IN6_IFF_HOME) != 0 &&
  399                         ia_best->ia_ifp->if_type == IFT_MIP)
  400                     &&
  401                     ((ia->ia6_flags & IN6_IFF_HOME) != 0 &&
  402                         ia->ia_ifp->if_type != IFT_MIP))
  403                         REPLACE(4);
  404                 if (ip6po_usecoa == 0) {
  405                         /*
  406                          * If SA is just a home address and SB is just
  407                          * a care-of address, then prefer
  408                          * SA. Similarly, if SB is just a home address
  409                          * and SA is just a care-of address, then
  410                          * prefer SB.
  411                          */
  412                         if ((ia_best->ia6_flags & IN6_IFF_HOME) != 0 &&
  413                             (ia->ia6_flags & IN6_IFF_HOME) == 0) {
  414                                 NEXT(4);
  415                         }
  416                         if ((ia_best->ia6_flags & IN6_IFF_HOME) == 0 &&
  417                             (ia->ia6_flags & IN6_IFF_HOME) != 0) {
  418                                 REPLACE(4);
  419                         }
  420                 } else {
  421                         /*
  422                          * a sender don't want to use a home address
  423                          * because:
  424                          *
  425                          * 1) we cannot use.  (ex. NS or NA to global
  426                          * addresses.)
  427                          *
  428                          * 2) a user specified not to use.
  429                          * (ex. mip6control -u)
  430                          */
  431                         if ((ia_best->ia6_flags & IN6_IFF_HOME) == 0 &&
  432                             (ia->ia6_flags & IN6_IFF_HOME) != 0) {
  433                                 /* XXX breaks stat */
  434                                 NEXT(0);
  435                         }
  436                         if ((ia_best->ia6_flags & IN6_IFF_HOME) != 0 &&
  437                             (ia->ia6_flags & IN6_IFF_HOME) == 0) {
  438                                 /* XXX breaks stat */
  439                                 REPLACE(0);
  440                         }
  441                 }                       
  442         skip_rule4:
  443 #endif /* MIP6 && NMIP > 0 */
  444 
  445                 /* Rule 5: Prefer outgoing interface */
  446                 if (ia_best->ia_ifp == ifp && ia->ia_ifp != ifp)
  447                         NEXT(5);
  448                 if (ia_best->ia_ifp != ifp && ia->ia_ifp == ifp)
  449                         REPLACE(5);
  450 
  451                 /*
  452                  * Rule 6: Prefer matching label
  453                  * Note that best_policy should be non-NULL here.
  454                  */
  455                 if (dst_policy == NULL)
  456                         dst_policy = lookup_addrsel_policy(dstsock);
  457                 if (dst_policy->label != ADDR_LABEL_NOTAPP) {
  458                         new_policy = lookup_addrsel_policy(&ia->ia_addr);
  459                         if (dst_policy->label == best_policy->label &&
  460                             dst_policy->label != new_policy->label)
  461                                 NEXT(6);
  462                         if (dst_policy->label != best_policy->label &&
  463                             dst_policy->label == new_policy->label)
  464                                 REPLACE(6);
  465                 }
  466 
  467                 /*
  468                  * Rule 7: Prefer public addresses.
  469                  * We allow users to reverse the logic by configuring
  470                  * a sysctl variable, so that privacy conscious users can
  471                  * always prefer temporary addresses.
  472                  */
  473 #ifdef notyet /* until introducing ND extensions and address selection */
  474                 if (opts == NULL ||
  475                     opts->ip6po_prefer_tempaddr == IP6PO_TEMPADDR_SYSTEM) {
  476                         prefer_tempaddr = ip6_prefer_tempaddr;
  477                 } else if (opts->ip6po_prefer_tempaddr ==
  478                     IP6PO_TEMPADDR_NOTPREFER) {
  479                         prefer_tempaddr = 0;
  480                 } else
  481                         prefer_tempaddr = 1;
  482                 if (!(ia_best->ia6_flags & IN6_IFF_TEMPORARY) &&
  483                     (ia->ia6_flags & IN6_IFF_TEMPORARY)) {
  484                         if (prefer_tempaddr)
  485                                 REPLACE(7);
  486                         else
  487                                 NEXT(7);
  488                 }
  489                 if ((ia_best->ia6_flags & IN6_IFF_TEMPORARY) &&
  490                     !(ia->ia6_flags & IN6_IFF_TEMPORARY)) {
  491                         if (prefer_tempaddr)
  492                                 NEXT(7);
  493                         else
  494                                 REPLACE(7);
  495                 }
  496 #endif
  497 
  498                 /*
  499                  * Rule 8: prefer addresses on alive interfaces.
  500                  * This is a KAME specific rule.
  501                  */
  502                 if ((ia_best->ia_ifp->if_flags & IFF_UP) &&
  503                     !(ia->ia_ifp->if_flags & IFF_UP))
  504                         NEXT(8);
  505                 if (!(ia_best->ia_ifp->if_flags & IFF_UP) &&
  506                     (ia->ia_ifp->if_flags & IFF_UP))
  507                         REPLACE(8);
  508 
  509                 /*
  510                  * Rule 9: prefer addresses on "preferred" interfaces.
  511                  * This is a KAME specific rule.
  512                  */
  513 #ifdef notyet                   /* until introducing address selection */
  514 #define NDI_BEST ND_IFINFO(ia_best->ia_ifp)
  515 #define NDI_NEW  ND_IFINFO(ia->ia_ifp)
  516                 if ((NDI_BEST->flags & ND6_IFF_PREFER_SOURCE) &&
  517                     !(NDI_NEW->flags & ND6_IFF_PREFER_SOURCE))
  518                         NEXT(9);
  519                 if (!(NDI_BEST->flags & ND6_IFF_PREFER_SOURCE) &&
  520                     (NDI_NEW->flags & ND6_IFF_PREFER_SOURCE))
  521                         REPLACE(9);
  522 #undef NDI_BEST
  523 #undef NDI_NEW
  524 #endif
  525 
  526                 /*
  527                  * Rule 14: Use longest matching prefix.
  528                  * Note: in the address selection draft, this rule is
  529                  * documented as "Rule 8".  However, since it is also
  530                  * documented that this rule can be overridden, we assign
  531                  * a large number so that it is easy to assign smaller numbers
  532                  * to more preferred rules.
  533                  */
  534                 new_matchlen = in6_matchlen(&ia->ia_addr.sin6_addr, &dst);
  535                 if (best_matchlen < new_matchlen)
  536                         REPLACE(14);
  537                 if (new_matchlen < best_matchlen)
  538                         NEXT(14);
  539 
  540                 /* Rule 15 is reserved. */
  541 
  542                 /*
  543                  * Last resort: just keep the current candidate.
  544                  * Or, do we need more rules?
  545                  */
  546                 continue;
  547 
  548           replace:
  549                 ia_best = ia;
  550                 best_scope = (new_scope >= 0 ? new_scope :
  551                               in6_addrscope(&ia_best->ia_addr.sin6_addr));
  552                 best_policy = (new_policy ? new_policy :
  553                                lookup_addrsel_policy(&ia_best->ia_addr));
  554                 best_matchlen = (new_matchlen >= 0 ? new_matchlen :
  555                                  in6_matchlen(&ia_best->ia_addr.sin6_addr,
  556                                               &dst));
  557 
  558           next:
  559                 continue;
  560 
  561           out:
  562                 break;
  563         }
  564 
  565         if ((ia = ia_best) == NULL) {
  566                 *errorp = EADDRNOTAVAIL;
  567                 return (NULL);
  568         }
  569 
  570         return (&ia->ia_addr.sin6_addr);
  571 }
  572 #undef REPLACE
  573 #undef BREAK
  574 #undef NEXT
  575 
  576 static int
  577 selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 
  578         struct ip6_moptions *mopts, struct route *ro, struct ifnet **retifp, 
  579         struct rtentry **retrt, int clone, int norouteok)
  580 {
  581         int error = 0;
  582         struct ifnet *ifp = NULL;
  583         struct rtentry *rt = NULL;
  584         struct sockaddr_in6 *sin6_next;
  585         struct in6_pktinfo *pi = NULL;
  586         struct in6_addr *dst;
  587 
  588         dst = &dstsock->sin6_addr;
  589 
  590 #if 0
  591         if (dstsock->sin6_addr.s6_addr32[0] == 0 &&
  592             dstsock->sin6_addr.s6_addr32[1] == 0 &&
  593             !IN6_IS_ADDR_LOOPBACK(&dstsock->sin6_addr)) {
  594                 printf("in6_selectroute: strange destination %s\n",
  595                        ip6_sprintf(&dstsock->sin6_addr));
  596         } else {
  597                 printf("in6_selectroute: destination = %s%%%d\n",
  598                        ip6_sprintf(&dstsock->sin6_addr),
  599                        dstsock->sin6_scope_id); /* for debug */
  600         }
  601 #endif
  602 
  603         /* If the caller specify the outgoing interface explicitly, use it. */
  604         if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) {
  605                 /* XXX boundary check is assumed to be already done. */
  606 #ifdef __FreeBSD__
  607                 ifp = ifnet_byindex(pi->ipi6_ifindex);
  608 #else
  609                 ifp = ifindex2ifnet[pi->ipi6_ifindex];
  610 #endif
  611                 if (ifp != NULL &&
  612                     (norouteok || retrt == NULL ||
  613                     IN6_IS_ADDR_MULTICAST(dst))) {
  614                         /*
  615                          * we do not have to check or get the route for
  616                          * multicast.
  617                          */
  618                         goto done;
  619                 } else
  620                         goto getroute;
  621         }
  622 
  623         /*
  624          * If the destination address is a multicast address and the outgoing
  625          * interface for the address is specified by the caller, use it.
  626          */
  627         if (IN6_IS_ADDR_MULTICAST(dst) &&
  628             mopts != NULL && (ifp = mopts->im6o_multicast_ifp) != NULL) {
  629                 goto done; /* we do not need a route for multicast. */
  630         }
  631 
  632   getroute:
  633         /*
  634          * If the next hop address for the packet is specified by the caller,
  635          * use it as the gateway.
  636          */
  637         if (opts && opts->ip6po_nexthop) {
  638                 struct route *ron;
  639 
  640                 sin6_next = satosin6(opts->ip6po_nexthop);
  641 
  642                 /* at this moment, we only support AF_INET6 next hops */
  643                 if (sin6_next->sin6_family != AF_INET6) {
  644                         error = EAFNOSUPPORT; /* or should we proceed? */
  645                         goto done;
  646                 }
  647 
  648                 /*
  649                  * If the next hop is an IPv6 address, then the node identified
  650                  * by that address must be a neighbor of the sending host.
  651                  */
  652                 ron = &opts->ip6po_nextroute;
  653                 if ((rt = rtcache_lookup(ron, sin6tosa(sin6_next))) == NULL ||
  654                     (rt->rt_flags & RTF_GATEWAY) != 0 ||
  655                     !nd6_is_addr_neighbor(sin6_next, rt->rt_ifp)) {
  656                         rtcache_free(ron);
  657                         error = EHOSTUNREACH;
  658                         goto done;
  659                 }
  660                 ifp = rt->rt_ifp;
  661 
  662                 /*
  663                  * When cloning is required, try to allocate a route to the
  664                  * destination so that the caller can store path MTU
  665                  * information.
  666                  */
  667                 if (!clone)
  668                         goto done;
  669         }
  670 
  671         /*
  672          * Use a cached route if it exists and is valid, else try to allocate
  673          * a new one.  Note that we should check the address family of the
  674          * cached destination, in case of sharing the cache with IPv4.
  675          */
  676         if (ro != NULL) {
  677                 union {
  678                         struct sockaddr         dst;
  679                         struct sockaddr_in6     dst6;
  680                 } u;
  681 
  682                 /* No route yet, so try to acquire one */
  683                 u.dst6 = *dstsock;
  684                 u.dst6.sin6_scope_id = 0;
  685                 rt = rtcache_lookup1(ro, &u.dst, clone);
  686 
  687                 /*
  688                  * do not care about the result if we have the nexthop
  689                  * explicitly specified.
  690                  */
  691                 if (opts && opts->ip6po_nexthop)
  692                         goto done;
  693 
  694                 if (rt == NULL)
  695                         error = EHOSTUNREACH;
  696                 else
  697                         ifp = rt->rt_ifp;
  698 
  699                 /*
  700                  * Check if the outgoing interface conflicts with
  701                  * the interface specified by ipi6_ifindex (if specified).
  702                  * Note that loopback interface is always okay.
  703                  * (this may happen when we are sending a packet to one of
  704                  *  our own addresses.)
  705                  */
  706                 if (opts && opts->ip6po_pktinfo &&
  707                     opts->ip6po_pktinfo->ipi6_ifindex) {
  708                         if (!(ifp->if_flags & IFF_LOOPBACK) &&
  709                             ifp->if_index !=
  710                             opts->ip6po_pktinfo->ipi6_ifindex) {
  711                                 error = EHOSTUNREACH;
  712                                 goto done;
  713                         }
  714                 }
  715         }
  716 
  717   done:
  718         if (ifp == NULL && rt == NULL) {
  719                 /*
  720                  * This can happen if the caller did not pass a cached route
  721                  * nor any other hints.  We treat this case an error.
  722                  */
  723                 error = EHOSTUNREACH;
  724         }
  725         if (error == EHOSTUNREACH)
  726                 IP6_STATINC(IP6_STAT_NOROUTE);
  727 
  728         if (retifp != NULL)
  729                 *retifp = ifp;
  730         if (retrt != NULL)
  731                 *retrt = rt;    /* rt may be NULL */
  732 
  733         return (error);
  734 }
  735 
  736 static int
  737 in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 
  738         struct ip6_moptions *mopts, struct route *ro, struct ifnet **retifp)
  739 {
  740         int error, clone;
  741         struct rtentry *rt = NULL;
  742 
  743         clone = IN6_IS_ADDR_MULTICAST(&dstsock->sin6_addr) ? 0 : 1;
  744         if ((error = selectroute(dstsock, opts, mopts, ro, retifp,
  745             &rt, clone, 1)) != 0) {
  746                 return (error);
  747         }
  748 
  749         /*
  750          * do not use a rejected or black hole route.
  751          * XXX: this check should be done in the L2 output routine.
  752          * However, if we skipped this check here, we'd see the following
  753          * scenario:
  754          * - install a rejected route for a scoped address prefix
  755          *   (like fe80::/10)
  756          * - send a packet to a destination that matches the scoped prefix,
  757          *   with ambiguity about the scope zone.
  758          * - pick the outgoing interface from the route, and disambiguate the
  759          *   scope zone with the interface.
  760          * - ip6_output() would try to get another route with the "new"
  761          *   destination, which may be valid.
  762          * - we'd see no error on output.
  763          * Although this may not be very harmful, it should still be confusing.
  764          * We thus reject the case here.
  765          */
  766         if (rt && (rt->rt_flags & (RTF_REJECT | RTF_BLACKHOLE)))
  767                 return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
  768 
  769         /*
  770          * Adjust the "outgoing" interface.  If we're going to loop the packet
  771          * back to ourselves, the ifp would be the loopback interface.
  772          * However, we'd rather know the interface associated to the
  773          * destination address (which should probably be one of our own
  774          * addresses.)
  775          */
  776         if (rt && rt->rt_ifa && rt->rt_ifa->ifa_ifp)
  777                 *retifp = rt->rt_ifa->ifa_ifp;
  778 
  779         return (0);
  780 }
  781 
  782 /*
  783  * close - meaningful only for bsdi and freebsd.
  784  */
  785 
  786 int
  787 in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 
  788         struct ip6_moptions *mopts, struct route *ro, struct ifnet **retifp, 
  789         struct rtentry **retrt, int clone)
  790 {
  791         return selectroute(dstsock, opts, mopts, ro, retifp,
  792             retrt, clone, 0);
  793 }
  794 
  795 /*
  796  * Default hop limit selection. The precedence is as follows:
  797  * 1. Hoplimit value specified via ioctl.
  798  * 2. (If the outgoing interface is detected) the current
  799  *     hop limit of the interface specified by router advertisement.
  800  * 3. The system default hoplimit.
  801 */
  802 int
  803 in6_selecthlim(struct in6pcb *in6p, struct ifnet *ifp)
  804 {
  805         if (in6p && in6p->in6p_hops >= 0)
  806                 return (in6p->in6p_hops);
  807         else if (ifp)
  808                 return (ND_IFINFO(ifp)->chlim);
  809         else
  810                 return (ip6_defhlim);
  811 }
  812 
  813 /*
  814  * Find an empty port and set it to the specified PCB.
  815  */
  816 int
  817 in6_pcbsetport(struct in6_addr *laddr, struct in6pcb *in6p, struct lwp *l)
  818 {
  819         struct socket *so = in6p->in6p_socket;
  820         struct inpcbtable *table = in6p->in6p_table;
  821         int cnt;
  822         u_int16_t minport, maxport;
  823         u_int16_t lport, *lastport;
  824         int wild = 0;
  825         void *t;
  826 
  827         /* XXX: this is redundant when called from in6_pcbbind */
  828         if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
  829            ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
  830             (so->so_options & SO_ACCEPTCONN) == 0))
  831                 wild = 1;
  832 
  833         if (in6p->in6p_flags & IN6P_LOWPORT) {
  834 #ifndef IPNOPRIVPORTS
  835                 if (l == 0 || (kauth_authorize_generic(l->l_cred,
  836                     KAUTH_GENERIC_ISSUSER, NULL) != 0))
  837                         return (EACCES);
  838 #endif
  839                 minport = ip6_lowportmin;
  840                 maxport = ip6_lowportmax;
  841                 lastport = &table->inpt_lastlow;
  842         } else {
  843                 minport = ip6_anonportmin;
  844                 maxport = ip6_anonportmax;
  845                 lastport = &table->inpt_lastport;
  846         }
  847 
  848         if (minport > maxport) {        /* sanity check */
  849                 u_int16_t swp;
  850                 
  851                 swp = minport;
  852                 minport = maxport;
  853                 maxport = swp;
  854         }
  855 
  856         lport = *lastport - 1;
  857         for (cnt = maxport - minport + 1; cnt; cnt--, lport--) {
  858                 if (lport < minport || lport > maxport)
  859                         lport = maxport;
  860 #ifdef INET
  861                 if (IN6_IS_ADDR_V4MAPPED(laddr)) {
  862                         t = in_pcblookup_port(table,
  863                             *(struct in_addr *)&laddr->s6_addr32[3],
  864                             htons(lport), wild);
  865                 } else
  866 #endif
  867                 {
  868                         t = in6_pcblookup_port(table, laddr, htons(lport),
  869                             wild);
  870                 }
  871                 if (t == 0)
  872                         goto found;
  873         }
  874 
  875         return (EAGAIN);
  876 
  877 found:
  878         in6p->in6p_flags |= IN6P_ANONPORT;
  879         *lastport = lport;
  880         in6p->in6p_lport = htons(lport);
  881         in6_pcbstate(in6p, IN6P_BOUND);
  882         return (0);             /* success */
  883 }
  884 
  885 void
  886 addrsel_policy_init(void)
  887 {
  888         init_policy_queue();
  889 
  890         /* initialize the "last resort" policy */
  891         bzero(&defaultaddrpolicy, sizeof(defaultaddrpolicy));
  892         defaultaddrpolicy.label = ADDR_LABEL_NOTAPP;
  893 }
  894 
  895 static struct in6_addrpolicy *
  896 lookup_addrsel_policy(struct sockaddr_in6 *key)
  897 {
  898         struct in6_addrpolicy *match = NULL;
  899 
  900         match = match_addrsel_policy(key);
  901 
  902         if (match == NULL)
  903                 match = &defaultaddrpolicy;
  904         else
  905                 match->use++;
  906 
  907         return (match);
  908 }
  909 
  910 /*
  911  * Subroutines to manage the address selection policy table via sysctl.
  912  */
  913 struct walkarg {
  914         size_t  w_total;
  915         size_t  w_given;
  916         void *  w_where;
  917         void *w_limit;
  918 };
  919 
  920 int
  921 in6_src_sysctl(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
  922 {
  923         int error = 0;
  924         int s;
  925 
  926         s = splsoftnet();
  927 
  928         if (newp) {
  929                 error = EPERM;
  930                 goto end;
  931         }
  932         if (oldp && oldlenp == NULL) {
  933                 error = EINVAL;
  934                 goto end;
  935         }
  936         if (oldp || oldlenp) {
  937                 struct walkarg w;
  938                 size_t oldlen = *oldlenp;
  939 
  940                 memset(&w, 0, sizeof(w));
  941                 w.w_given = oldlen;
  942                 w.w_where = oldp;
  943                 if (oldp)
  944                         w.w_limit = (char *)oldp + oldlen;
  945 
  946                 error = walk_addrsel_policy(dump_addrsel_policyent, &w);
  947 
  948                 *oldlenp = w.w_total;
  949                 if (oldp && w.w_total > oldlen && error == 0)
  950                         error = ENOMEM;
  951         }
  952 
  953   end:
  954         splx(s);
  955 
  956         return (error);
  957 }
  958 
  959 int
  960 in6_src_ioctl(u_long cmd, void *data)
  961 {
  962         int i;
  963         struct in6_addrpolicy ent0;
  964 
  965         if (cmd != SIOCAADDRCTL_POLICY && cmd != SIOCDADDRCTL_POLICY)
  966                 return (EOPNOTSUPP); /* check for safety */
  967 
  968         ent0 = *(struct in6_addrpolicy *)data;
  969 
  970         if (ent0.label == ADDR_LABEL_NOTAPP)
  971                 return (EINVAL);
  972         /* check if the prefix mask is consecutive. */
  973         if (in6_mask2len(&ent0.addrmask.sin6_addr, NULL) < 0)
  974                 return (EINVAL);
  975         /* clear trailing garbages (if any) of the prefix address. */
  976         for (i = 0; i < 4; i++) {
  977                 ent0.addr.sin6_addr.s6_addr32[i] &=
  978                         ent0.addrmask.sin6_addr.s6_addr32[i];
  979         }
  980         ent0.use = 0;
  981 
  982         switch (cmd) {
  983         case SIOCAADDRCTL_POLICY:
  984                 return (add_addrsel_policyent(&ent0));
  985         case SIOCDADDRCTL_POLICY:
  986                 return (delete_addrsel_policyent(&ent0));
  987         }
  988 
  989         return (0);             /* XXX: compromise compilers */
  990 }
  991 
  992 /*
  993  * The followings are implementation of the policy table using a
  994  * simple tail queue.
  995  * XXX such details should be hidden.
  996  * XXX implementation using binary tree should be more efficient.
  997  */
  998 struct addrsel_policyent {
  999         TAILQ_ENTRY(addrsel_policyent) ape_entry;
 1000         struct in6_addrpolicy ape_policy;
 1001 };
 1002 
 1003 TAILQ_HEAD(addrsel_policyhead, addrsel_policyent);
 1004 
 1005 struct addrsel_policyhead addrsel_policytab;
 1006 
 1007 static void
 1008 init_policy_queue(void)
 1009 {
 1010         TAILQ_INIT(&addrsel_policytab);
 1011 }
 1012 
 1013 static int
 1014 add_addrsel_policyent(struct in6_addrpolicy *newpolicy)
 1015 {
 1016         struct addrsel_policyent *new, *pol;
 1017 
 1018         /* duplication check */
 1019         for (pol = TAILQ_FIRST(&addrsel_policytab); pol;
 1020              pol = TAILQ_NEXT(pol, ape_entry)) {
 1021                 if (IN6_ARE_ADDR_EQUAL(&newpolicy->addr.sin6_addr,
 1022                     &pol->ape_policy.addr.sin6_addr) &&
 1023                     IN6_ARE_ADDR_EQUAL(&newpolicy->addrmask.sin6_addr,
 1024                     &pol->ape_policy.addrmask.sin6_addr)) {
 1025                         return (EEXIST);        /* or override it? */
 1026                 }
 1027         }
 1028 
 1029         MALLOC(new, struct addrsel_policyent *, sizeof(*new), M_IFADDR,
 1030                M_WAITOK);
 1031         bzero(new, sizeof(*new));
 1032 
 1033         /* XXX: should validate entry */
 1034         new->ape_policy = *newpolicy;
 1035 
 1036         TAILQ_INSERT_TAIL(&addrsel_policytab, new, ape_entry);
 1037 
 1038         return (0);
 1039 }
 1040 
 1041 static int
 1042 delete_addrsel_policyent(struct in6_addrpolicy *key)
 1043 {
 1044         struct addrsel_policyent *pol;
 1045 
 1046         /* search for the entry in the table */
 1047         for (pol = TAILQ_FIRST(&addrsel_policytab); pol;
 1048              pol = TAILQ_NEXT(pol, ape_entry)) {
 1049                 if (IN6_ARE_ADDR_EQUAL(&key->addr.sin6_addr,
 1050                     &pol->ape_policy.addr.sin6_addr) &&
 1051                     IN6_ARE_ADDR_EQUAL(&key->addrmask.sin6_addr,
 1052                     &pol->ape_policy.addrmask.sin6_addr)) {
 1053                         break;
 1054                 }
 1055         }
 1056         if (pol == NULL) {
 1057                 return (ESRCH);
 1058         }
 1059 
 1060         TAILQ_REMOVE(&addrsel_policytab, pol, ape_entry);
 1061 
 1062         return (0);
 1063 }
 1064 
 1065 static int
 1066 walk_addrsel_policy(int (*callback)(struct in6_addrpolicy *, void *), void *w)
 1067 {
 1068         struct addrsel_policyent *pol;
 1069         int error = 0;
 1070 
 1071         TAILQ_FOREACH(pol, &addrsel_policytab, ape_entry) {
 1072                 if ((error = (*callback)(&pol->ape_policy, w)) != 0)
 1073                         return error;
 1074         }
 1075 
 1076         return error;
 1077 }
 1078 
 1079 static int
 1080 dump_addrsel_policyent(struct in6_addrpolicy *pol, void *arg)
 1081 {
 1082         int error = 0;
 1083         struct walkarg *w = arg;
 1084 
 1085         if (w->w_where && (char *)w->w_where + sizeof(*pol) <= (char *)w->w_limit) {
 1086                 if ((error = copyout(pol, w->w_where, sizeof(*pol))) != 0)
 1087                         return error;
 1088                 w->w_where = (char *)w->w_where + sizeof(*pol);
 1089         }
 1090         w->w_total += sizeof(*pol);
 1091 
 1092         return error;
 1093 }
 1094 
 1095 static struct in6_addrpolicy *
 1096 match_addrsel_policy(struct sockaddr_in6 *key)
 1097 {
 1098         struct addrsel_policyent *pent;
 1099         struct in6_addrpolicy *bestpol = NULL, *pol;
 1100         int matchlen, bestmatchlen = -1;
 1101         u_char *mp, *ep, *k, *p, m;
 1102 
 1103         for (pent = TAILQ_FIRST(&addrsel_policytab); pent;
 1104              pent = TAILQ_NEXT(pent, ape_entry)) {
 1105                 matchlen = 0;
 1106 
 1107                 pol = &pent->ape_policy;
 1108                 mp = (u_char *)&pol->addrmask.sin6_addr;
 1109                 ep = mp + 16;   /* XXX: scope field? */
 1110                 k = (u_char *)&key->sin6_addr;
 1111                 p = (u_char *)&pol->addr.sin6_addr;
 1112                 for (; mp < ep && *mp; mp++, k++, p++) {
 1113                         m = *mp;
 1114                         if ((*k & m) != *p)
 1115                                 goto next; /* not match */
 1116                         if (m == 0xff) /* short cut for a typical case */
 1117                                 matchlen += 8;
 1118                         else {
 1119                                 while (m >= 0x80) {
 1120                                         matchlen++;
 1121                                         m <<= 1;
 1122                                 }
 1123                         }
 1124                 }
 1125 
 1126                 /* matched.  check if this is better than the current best. */
 1127                 if (bestpol == NULL ||
 1128                     matchlen > bestmatchlen) {
 1129                         bestpol = pol;
 1130                         bestmatchlen = matchlen;
 1131                 }
 1132 
 1133           next:
 1134                 continue;
 1135         }
 1136 
 1137         return (bestpol);
 1138 }

Cache object: 3fc2d57bc037b48f11e50e8fedd769e0


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