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 /*      $FreeBSD$       */
    2 /*      $KAME: in6_src.c,v 1.37 2001/03/29 05:34:31 itojun Exp $        */
    3 
    4 /*
    5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the project nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 /*
   34  * Copyright (c) 1982, 1986, 1991, 1993
   35  *      The Regents of the University of California.  All rights reserved.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions and the following disclaimer.
   42  * 2. Redistributions in binary form must reproduce the above copyright
   43  *    notice, this list of conditions and the following disclaimer in the
   44  *    documentation and/or other materials provided with the distribution.
   45  * 3. All advertising materials mentioning features or use of this software
   46  *    must display the following acknowledgement:
   47  *      This product includes software developed by the University of
   48  *      California, Berkeley and its contributors.
   49  * 4. Neither the name of the University nor the names of its contributors
   50  *    may be used to endorse or promote products derived from this software
   51  *    without specific prior written permission.
   52  *
   53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   63  * SUCH DAMAGE.
   64  *
   65  *      @(#)in_pcb.c    8.2 (Berkeley) 1/4/94
   66  */
   67 
   68 #include "opt_inet.h"
   69 #include "opt_inet6.h"
   70 
   71 #include <sys/param.h>
   72 #include <sys/systm.h>
   73 #include <sys/malloc.h>
   74 #include <sys/mbuf.h>
   75 #include <sys/protosw.h>
   76 #include <sys/socket.h>
   77 #include <sys/socketvar.h>
   78 #include <sys/errno.h>
   79 #include <sys/time.h>
   80 #include <sys/proc.h>
   81 
   82 #include <net/if.h>
   83 #include <net/route.h>
   84 
   85 #include <netinet/in.h>
   86 #include <netinet/in_var.h>
   87 #include <netinet/in_systm.h>
   88 #include <netinet/ip.h>
   89 #include <netinet/in_pcb.h>
   90 #include <netinet6/in6_var.h>
   91 #include <netinet/ip6.h>
   92 #include <netinet6/in6_pcb.h>
   93 #include <netinet6/ip6_var.h>
   94 #include <netinet6/nd6.h>
   95 #ifdef ENABLE_DEFAULT_SCOPE
   96 #include <netinet6/scope6_var.h> 
   97 #endif
   98 
   99 #include <net/net_osdep.h>
  100 
  101 #include "loop.h"
  102 
  103 /*
  104  * Return an IPv6 address, which is the most appropriate for a given
  105  * destination and user specified options.
  106  * If necessary, this function lookups the routing table and returns
  107  * an entry to the caller for later use.
  108  */
  109 struct in6_addr *
  110 in6_selectsrc(dstsock, opts, mopts, ro, laddr, errorp)
  111         struct sockaddr_in6 *dstsock;
  112         struct ip6_pktopts *opts;
  113         struct ip6_moptions *mopts;
  114         struct route_in6 *ro;
  115         struct in6_addr *laddr;
  116         int *errorp;
  117 {
  118         struct in6_addr *dst;
  119         struct in6_ifaddr *ia6 = 0;
  120         struct in6_pktinfo *pi = NULL;
  121 
  122         dst = &dstsock->sin6_addr;
  123         *errorp = 0;
  124 
  125         /*
  126          * If the source address is explicitly specified by the caller,
  127          * use it.
  128          */
  129         if (opts && (pi = opts->ip6po_pktinfo) &&
  130             !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr))
  131                 return(&pi->ipi6_addr);
  132 
  133         /*
  134          * If the source address is not specified but the socket(if any)
  135          * is already bound, use the bound address.
  136          */
  137         if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr))
  138                 return(laddr);
  139 
  140         /*
  141          * If the caller doesn't specify the source address but
  142          * the outgoing interface, use an address associated with
  143          * the interface.
  144          */
  145         if (pi && pi->ipi6_ifindex) {
  146                 /* XXX boundary check is assumed to be already done. */
  147                 ia6 = in6_ifawithscope(ifindex2ifnet[pi->ipi6_ifindex],
  148                                        dst);
  149                 if (ia6 == 0) {
  150                         *errorp = EADDRNOTAVAIL;
  151                         return(0);
  152                 }
  153                 return(&satosin6(&ia6->ia_addr)->sin6_addr);
  154         }
  155 
  156         /*
  157          * If the destination address is a link-local unicast address or
  158          * a multicast address, and if the outgoing interface is specified
  159          * by the sin6_scope_id filed, use an address associated with the
  160          * interface.
  161          * XXX: We're now trying to define more specific semantics of
  162          *      sin6_scope_id field, so this part will be rewritten in
  163          *      the near future.
  164          */
  165         if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst)) &&
  166             dstsock->sin6_scope_id) {
  167                 /*
  168                  * I'm not sure if boundary check for scope_id is done
  169                  * somewhere...
  170                  */
  171                 if (dstsock->sin6_scope_id < 0 ||
  172                     if_index < dstsock->sin6_scope_id) {
  173                         *errorp = ENXIO; /* XXX: better error? */
  174                         return(0);
  175                 }
  176                 ia6 = in6_ifawithscope(ifindex2ifnet[dstsock->sin6_scope_id],
  177                                        dst);
  178                 if (ia6 == 0) {
  179                         *errorp = EADDRNOTAVAIL;
  180                         return(0);
  181                 }
  182                 return(&satosin6(&ia6->ia_addr)->sin6_addr);
  183         }
  184 
  185         /*
  186          * If the destination address is a multicast address and
  187          * the outgoing interface for the address is specified
  188          * by the caller, use an address associated with the interface.
  189          * There is a sanity check here; if the destination has node-local
  190          * scope, the outgoing interfacde should be a loopback address.
  191          * Even if the outgoing interface is not specified, we also
  192          * choose a loopback interface as the outgoing interface.
  193          */
  194         if (IN6_IS_ADDR_MULTICAST(dst)) {
  195                 struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
  196 
  197                 if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
  198                         ifp = &loif[0];
  199                 }
  200 
  201                 if (ifp) {
  202                         ia6 = in6_ifawithscope(ifp, dst);
  203                         if (ia6 == 0) {
  204                                 *errorp = EADDRNOTAVAIL;
  205                                 return(0);
  206                         }
  207                         return(&satosin6(&ia6->ia_addr)->sin6_addr);
  208                 }
  209         }
  210 
  211         /*
  212          * If the next hop address for the packet is specified
  213          * by caller, use an address associated with the route
  214          * to the next hop.
  215          */
  216         {
  217                 struct sockaddr_in6 *sin6_next;
  218                 struct rtentry *rt;
  219 
  220                 if (opts && opts->ip6po_nexthop) {
  221                         sin6_next = satosin6(opts->ip6po_nexthop);
  222                         rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL);
  223                         if (rt) {
  224                                 ia6 = in6_ifawithscope(rt->rt_ifp, dst);
  225                                 if (ia6 == 0)
  226                                         ia6 = ifatoia6(rt->rt_ifa);
  227                         }
  228                         if (ia6 == 0) {
  229                                 *errorp = EADDRNOTAVAIL;
  230                                 return(0);
  231                         }
  232                         return(&satosin6(&ia6->ia_addr)->sin6_addr);
  233                 }
  234         }
  235 
  236         /*
  237          * If route is known or can be allocated now,
  238          * our src addr is taken from the i/f, else punt.
  239          */
  240         if (ro) {
  241                 if (ro->ro_rt &&
  242                     (!(ro->ro_rt->rt_flags & RTF_UP) ||
  243                      satosin6(&ro->ro_dst)->sin6_family != AF_INET6 || 
  244                      !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr,
  245                                          dst))) {
  246                         RTFREE(ro->ro_rt);
  247                         ro->ro_rt = (struct rtentry *)0;
  248                 }
  249                 if (ro->ro_rt == (struct rtentry *)0 ||
  250                     ro->ro_rt->rt_ifp == (struct ifnet *)0) {
  251                         struct sockaddr_in6 *sa6;
  252 
  253                         /* No route yet, so try to acquire one */
  254                         bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
  255                         sa6 = (struct sockaddr_in6 *)&ro->ro_dst;
  256                         sa6->sin6_family = AF_INET6;
  257                         sa6->sin6_len = sizeof(struct sockaddr_in6);
  258                         sa6->sin6_addr = *dst;
  259                         sa6->sin6_scope_id = dstsock->sin6_scope_id;
  260                         if (IN6_IS_ADDR_MULTICAST(dst)) {
  261                                 ro->ro_rt = rtalloc1(&((struct route *)ro)
  262                                                      ->ro_dst, 0, 0UL);
  263                         } else {
  264                                 rtalloc((struct route *)ro);
  265                         }
  266                 }
  267 
  268                 /*
  269                  * in_pcbconnect() checks out IFF_LOOPBACK to skip using
  270                  * the address. But we don't know why it does so.
  271                  * It is necessary to ensure the scope even for lo0
  272                  * so doesn't check out IFF_LOOPBACK.
  273                  */
  274 
  275                 if (ro->ro_rt) {
  276                         ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst);
  277                         if (ia6 == 0) /* xxx scope error ?*/
  278                                 ia6 = ifatoia6(ro->ro_rt->rt_ifa);
  279                 }
  280 #if 0
  281                 /*
  282                  * xxx The followings are necessary? (kazu)
  283                  * I don't think so.
  284                  * It's for SO_DONTROUTE option in IPv4.(jinmei)
  285                  */
  286                 if (ia6 == 0) {
  287                         struct sockaddr_in6 sin6 = {sizeof(sin6), AF_INET6, 0};
  288 
  289                         sin6->sin6_addr = *dst;
  290 
  291                         ia6 = ifatoia6(ifa_ifwithdstaddr(sin6tosa(&sin6)));
  292                         if (ia6 == 0)
  293                                 ia6 = ifatoia6(ifa_ifwithnet(sin6tosa(&sin6)));
  294                         if (ia6 == 0)
  295                                 return(0);
  296                         return(&satosin6(&ia6->ia_addr)->sin6_addr);
  297                 }
  298 #endif /* 0 */
  299                 if (ia6 == 0) {
  300                         *errorp = EHOSTUNREACH; /* no route */
  301                         return(0);
  302                 }
  303                 return(&satosin6(&ia6->ia_addr)->sin6_addr);
  304         }
  305 
  306         *errorp = EADDRNOTAVAIL;
  307         return(0);
  308 }
  309 
  310 /*
  311  * Default hop limit selection. The precedence is as follows:
  312  * 1. Hoplimit value specified via ioctl.
  313  * 2. (If the outgoing interface is detected) the current
  314  *     hop limit of the interface specified by router advertisement.
  315  * 3. The system default hoplimit.
  316 */
  317 int
  318 in6_selecthlim(in6p, ifp)
  319         struct in6pcb *in6p;
  320         struct ifnet *ifp;
  321 {
  322         if (in6p && in6p->in6p_hops >= 0)
  323                 return(in6p->in6p_hops);
  324         else if (ifp)
  325                 return(nd_ifinfo[ifp->if_index].chlim);
  326         else
  327                 return(ip6_defhlim);
  328 }
  329 
  330 /*
  331  * XXX: this is borrowed from in6_pcbbind(). If possible, we should
  332  * share this function by all *bsd*...
  333  */
  334 int
  335 in6_pcbsetport(laddr, inp, p)
  336         struct in6_addr *laddr;
  337         struct inpcb *inp;
  338         struct proc *p;
  339 {
  340         struct socket *so = inp->inp_socket;
  341         u_int16_t lport = 0, first, last, *lastport;
  342         int count, error = 0, wild = 0;
  343         struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
  344 
  345         /* XXX: this is redundant when called from in6_pcbbind */
  346         if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
  347                 wild = INPLOOKUP_WILDCARD;
  348 
  349         inp->inp_flags |= INP_ANONPORT;
  350 
  351         if (inp->inp_flags & INP_HIGHPORT) {
  352                 first = ipport_hifirstauto;     /* sysctl */
  353                 last  = ipport_hilastauto;
  354                 lastport = &pcbinfo->lasthi;
  355         } else if (inp->inp_flags & INP_LOWPORT) {
  356                 if (p && (error = suser(p)))
  357                         return error;
  358                 first = ipport_lowfirstauto;    /* 1023 */
  359                 last  = ipport_lowlastauto;     /* 600 */
  360                 lastport = &pcbinfo->lastlow;
  361         } else {
  362                 first = ipport_firstauto;       /* sysctl */
  363                 last  = ipport_lastauto;
  364                 lastport = &pcbinfo->lastport;
  365         }
  366         /*
  367          * Simple check to ensure all ports are not used up causing
  368          * a deadlock here.
  369          *
  370          * We split the two cases (up and down) so that the direction
  371          * is not being tested on each round of the loop.
  372          */
  373         if (first > last) {
  374                 /*
  375                  * counting down
  376                  */
  377                 count = first - last;
  378 
  379                 do {
  380                         if (count-- < 0) {      /* completely used? */
  381                                 /*
  382                                  * Undo any address bind that may have
  383                                  * occurred above.
  384                                  */
  385                                 inp->in6p_laddr = in6addr_any;
  386                                 return (EAGAIN);
  387                         }
  388                         --*lastport;
  389                         if (*lastport > first || *lastport < last)
  390                                 *lastport = first;
  391                         lport = htons(*lastport);
  392                 } while (in6_pcblookup_local(pcbinfo,
  393                                              &inp->in6p_laddr, lport, wild));
  394         } else {
  395                 /*
  396                          * counting up
  397                          */
  398                 count = last - first;
  399 
  400                 do {
  401                         if (count-- < 0) {      /* completely used? */
  402                                 /*
  403                                  * Undo any address bind that may have
  404                                  * occurred above.
  405                                  */
  406                                 inp->in6p_laddr = in6addr_any;
  407                                 return (EAGAIN);
  408                         }
  409                         ++*lastport;
  410                         if (*lastport < first || *lastport > last)
  411                                 *lastport = first;
  412                         lport = htons(*lastport);
  413                 } while (in6_pcblookup_local(pcbinfo,
  414                                              &inp->in6p_laddr, lport, wild));
  415         }
  416 
  417         inp->inp_lport = lport;
  418         if (in_pcbinshash(inp) != 0) {
  419                 inp->in6p_laddr = in6addr_any;
  420                 inp->inp_lport = 0;
  421                 return (EAGAIN);
  422         }
  423 
  424         return(0);
  425 }
  426 
  427 /*
  428  * generate kernel-internal form (scopeid embedded into s6_addr16[1]).
  429  * If the address scope of is link-local, embed the interface index in the
  430  * address.  The routine determines our precedence
  431  * between advanced API scope/interface specification and basic API
  432  * specification.
  433  *
  434  * this function should be nuked in the future, when we get rid of
  435  * embedded scopeid thing.
  436  *
  437  * XXX actually, it is over-specification to return ifp against sin6_scope_id.
  438  * there can be multiple interfaces that belong to a particular scope zone
  439  * (in specification, we have 1:N mapping between a scope zone and interfaces).
  440  * we may want to change the function to return something other than ifp.
  441  */
  442 int
  443 in6_embedscope(in6, sin6, in6p, ifpp)
  444         struct in6_addr *in6;
  445         const struct sockaddr_in6 *sin6;
  446 #ifdef HAVE_NRL_INPCB
  447         struct inpcb *in6p;
  448 #define in6p_outputopts inp_outputopts6
  449 #define in6p_moptions   inp_moptions6
  450 #else
  451         struct in6pcb *in6p;
  452 #endif
  453         struct ifnet **ifpp;
  454 {
  455         struct ifnet *ifp = NULL;
  456         u_int32_t scopeid;
  457 
  458         *in6 = sin6->sin6_addr;
  459         scopeid = sin6->sin6_scope_id;
  460         if (ifpp)
  461                 *ifpp = NULL;
  462 
  463         /*
  464          * don't try to read sin6->sin6_addr beyond here, since the caller may
  465          * ask us to overwrite existing sockaddr_in6
  466          */
  467 
  468 #ifdef ENABLE_DEFAULT_SCOPE
  469         if (scopeid == 0)
  470                 scopeid = scope6_addr2default(in6);
  471 #endif
  472 
  473         if (IN6_IS_SCOPE_LINKLOCAL(in6)) {
  474                 struct in6_pktinfo *pi;
  475 
  476                 /*
  477                  * KAME assumption: link id == interface id
  478                  */
  479 
  480                 if (in6p && in6p->in6p_outputopts &&
  481                     (pi = in6p->in6p_outputopts->ip6po_pktinfo) &&
  482                     pi->ipi6_ifindex) {
  483                         ifp = ifindex2ifnet[pi->ipi6_ifindex];
  484                         in6->s6_addr16[1] = htons(pi->ipi6_ifindex);
  485                 } else if (in6p && IN6_IS_ADDR_MULTICAST(in6) &&
  486                            in6p->in6p_moptions &&
  487                            in6p->in6p_moptions->im6o_multicast_ifp) {
  488                         ifp = in6p->in6p_moptions->im6o_multicast_ifp;
  489                         in6->s6_addr16[1] = htons(ifp->if_index);
  490                 } else if (scopeid) {
  491                         /* boundary check */
  492                         if (scopeid < 0 || if_index < scopeid)
  493                                 return ENXIO;  /* XXX EINVAL? */
  494                         ifp = ifindex2ifnet[scopeid];
  495                         /*XXX assignment to 16bit from 32bit variable */
  496                         in6->s6_addr16[1] = htons(scopeid & 0xffff);
  497                 }
  498 
  499                 if (ifpp)
  500                         *ifpp = ifp;
  501         }
  502 
  503         return 0;
  504 }
  505 #ifdef HAVE_NRL_INPCB
  506 #undef in6p_outputopts
  507 #undef in6p_moptions
  508 #endif
  509 
  510 /*
  511  * generate standard sockaddr_in6 from embedded form.
  512  * touches sin6_addr and sin6_scope_id only.
  513  *
  514  * this function should be nuked in the future, when we get rid of
  515  * embedded scopeid thing.
  516  */
  517 int
  518 in6_recoverscope(sin6, in6, ifp)
  519         struct sockaddr_in6 *sin6;
  520         const struct in6_addr *in6;
  521         struct ifnet *ifp;
  522 {
  523         u_int32_t scopeid;
  524 
  525         sin6->sin6_addr = *in6;
  526 
  527         /*
  528          * don't try to read *in6 beyond here, since the caller may
  529          * ask us to overwrite existing sockaddr_in6
  530          */
  531 
  532         sin6->sin6_scope_id = 0;
  533         if (IN6_IS_SCOPE_LINKLOCAL(in6)) {
  534                 /*
  535                  * KAME assumption: link id == interface id
  536                  */
  537                 scopeid = ntohs(sin6->sin6_addr.s6_addr16[1]);
  538                 if (scopeid) {
  539                         /* sanity check */
  540                         if (scopeid < 0 || if_index < scopeid)
  541                                 return ENXIO;
  542                         if (ifp && ifp->if_index != scopeid)
  543                                 return ENXIO;
  544                         sin6->sin6_addr.s6_addr16[1] = 0;
  545                         sin6->sin6_scope_id = scopeid;
  546                 }
  547         }
  548 
  549         return 0;
  550 }
  551 
  552 /*
  553  * just clear the embedded scope identifer.
  554  * XXX: currently used for bsdi4 only as a supplement function.
  555  */
  556 void
  557 in6_clearscope(addr)
  558         struct in6_addr *addr;
  559 {
  560         if (IN6_IS_SCOPE_LINKLOCAL(addr))
  561                 addr->s6_addr16[1] = 0;
  562 }

Cache object: fe67118db38ee719141384a4a11a567e


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