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

Cache object: eb5dc31eb6be39a9dc89adbd67f6ea63


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