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: releng/5.1/sys/netinet6/in6_src.c 97658 2002-05-31 11:52:35Z tanimura $       */
    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 
   81 #include <net/if.h>
   82 #include <net/route.h>
   83 
   84 #include <netinet/in.h>
   85 #include <netinet/in_var.h>
   86 #include <netinet/in_systm.h>
   87 #include <netinet/ip.h>
   88 #include <netinet/in_pcb.h>
   89 #include <netinet6/in6_var.h>
   90 #include <netinet/ip6.h>
   91 #include <netinet6/in6_pcb.h>
   92 #include <netinet6/ip6_var.h>
   93 #include <netinet6/nd6.h>
   94 #ifdef ENABLE_DEFAULT_SCOPE
   95 #include <netinet6/scope6_var.h> 
   96 #endif
   97 
   98 #include <net/net_osdep.h>
   99 
  100 /*
  101  * Return an IPv6 address, which is the most appropriate for a given
  102  * destination and user specified options.
  103  * If necessary, this function lookups the routing table and returns
  104  * an entry to the caller for later use.
  105  */
  106 struct in6_addr *
  107 in6_selectsrc(dstsock, opts, mopts, ro, laddr, errorp)
  108         struct sockaddr_in6 *dstsock;
  109         struct ip6_pktopts *opts;
  110         struct ip6_moptions *mopts;
  111         struct route_in6 *ro;
  112         struct in6_addr *laddr;
  113         int *errorp;
  114 {
  115         struct in6_addr *dst;
  116         struct in6_ifaddr *ia6 = 0;
  117         struct in6_pktinfo *pi = NULL;
  118 
  119         dst = &dstsock->sin6_addr;
  120         *errorp = 0;
  121 
  122         /*
  123          * If the source address is explicitly specified by the caller,
  124          * use it.
  125          */
  126         if (opts && (pi = opts->ip6po_pktinfo) &&
  127             !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr))
  128                 return(&pi->ipi6_addr);
  129 
  130         /*
  131          * If the source address is not specified but the socket(if any)
  132          * is already bound, use the bound address.
  133          */
  134         if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr))
  135                 return(laddr);
  136 
  137         /*
  138          * If the caller doesn't specify the source address but
  139          * the outgoing interface, use an address associated with
  140          * the interface.
  141          */
  142         if (pi && pi->ipi6_ifindex) {
  143                 /* XXX boundary check is assumed to be already done. */
  144                 ia6 = in6_ifawithscope(ifnet_byindex(pi->ipi6_ifindex), dst);
  145                 if (ia6 == 0) {
  146                         *errorp = EADDRNOTAVAIL;
  147                         return(0);
  148                 }
  149                 return(&satosin6(&ia6->ia_addr)->sin6_addr);
  150         }
  151 
  152         /*
  153          * If the destination address is a link-local unicast address or
  154          * a multicast address, and if the outgoing interface is specified
  155          * by the sin6_scope_id filed, use an address associated with the
  156          * interface.
  157          * XXX: We're now trying to define more specific semantics of
  158          *      sin6_scope_id field, so this part will be rewritten in
  159          *      the near future.
  160          */
  161         if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst)) &&
  162             dstsock->sin6_scope_id) {
  163                 /*
  164                  * I'm not sure if boundary check for scope_id is done
  165                  * somewhere...
  166                  */
  167                 if (dstsock->sin6_scope_id < 0 ||
  168                     if_index < dstsock->sin6_scope_id) {
  169                         *errorp = ENXIO; /* XXX: better error? */
  170                         return(0);
  171                 }
  172                 ia6 = in6_ifawithscope(ifnet_byindex(dstsock->sin6_scope_id),
  173                                        dst);
  174                 if (ia6 == 0) {
  175                         *errorp = EADDRNOTAVAIL;
  176                         return(0);
  177                 }
  178                 return(&satosin6(&ia6->ia_addr)->sin6_addr);
  179         }
  180 
  181         /*
  182          * If the destination address is a multicast address and
  183          * the outgoing interface for the address is specified
  184          * by the caller, use an address associated with the interface.
  185          * There is a sanity check here; if the destination has node-local
  186          * scope, the outgoing interfacde should be a loopback address.
  187          * Even if the outgoing interface is not specified, we also
  188          * choose a loopback interface as the outgoing interface.
  189          */
  190         if (IN6_IS_ADDR_MULTICAST(dst)) {
  191                 struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
  192 
  193                 if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
  194                         ifp = &loif[0];
  195                 }
  196 
  197                 if (ifp) {
  198                         ia6 = in6_ifawithscope(ifp, dst);
  199                         if (ia6 == 0) {
  200                                 *errorp = EADDRNOTAVAIL;
  201                                 return(0);
  202                         }
  203                         return(&satosin6(&ia6->ia_addr)->sin6_addr);
  204                 }
  205         }
  206 
  207         /*
  208          * If the next hop address for the packet is specified
  209          * by caller, use an address associated with the route
  210          * to the next hop.
  211          */
  212         {
  213                 struct sockaddr_in6 *sin6_next;
  214                 struct rtentry *rt;
  215 
  216                 if (opts && opts->ip6po_nexthop) {
  217                         sin6_next = satosin6(opts->ip6po_nexthop);
  218                         rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL);
  219                         if (rt) {
  220                                 ia6 = in6_ifawithscope(rt->rt_ifp, dst);
  221                                 if (ia6 == 0)
  222                                         ia6 = ifatoia6(rt->rt_ifa);
  223                         }
  224                         if (ia6 == 0) {
  225                                 *errorp = EADDRNOTAVAIL;
  226                                 return(0);
  227                         }
  228                         return(&satosin6(&ia6->ia_addr)->sin6_addr);
  229                 }
  230         }
  231 
  232         /*
  233          * If route is known or can be allocated now,
  234          * our src addr is taken from the i/f, else punt.
  235          */
  236         if (ro) {
  237                 if (ro->ro_rt &&
  238                     (!(ro->ro_rt->rt_flags & RTF_UP) ||
  239                      satosin6(&ro->ro_dst)->sin6_family != AF_INET6 || 
  240                      !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr,
  241                                          dst))) {
  242                         RTFREE(ro->ro_rt);
  243                         ro->ro_rt = (struct rtentry *)0;
  244                 }
  245                 if (ro->ro_rt == (struct rtentry *)0 ||
  246                     ro->ro_rt->rt_ifp == (struct ifnet *)0) {
  247                         struct sockaddr_in6 *sa6;
  248 
  249                         /* No route yet, so try to acquire one */
  250                         bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
  251                         sa6 = (struct sockaddr_in6 *)&ro->ro_dst;
  252                         sa6->sin6_family = AF_INET6;
  253                         sa6->sin6_len = sizeof(struct sockaddr_in6);
  254                         sa6->sin6_addr = *dst;
  255                         sa6->sin6_scope_id = dstsock->sin6_scope_id;
  256                         if (IN6_IS_ADDR_MULTICAST(dst)) {
  257                                 ro->ro_rt = rtalloc1(&((struct route *)ro)
  258                                                      ->ro_dst, 0, 0UL);
  259                         } else {
  260                                 rtalloc((struct route *)ro);
  261                         }
  262                 }
  263 
  264                 /*
  265                  * in_pcbconnect() checks out IFF_LOOPBACK to skip using
  266                  * the address. But we don't know why it does so.
  267                  * It is necessary to ensure the scope even for lo0
  268                  * so doesn't check out IFF_LOOPBACK.
  269                  */
  270 
  271                 if (ro->ro_rt) {
  272                         ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst);
  273                         if (ia6 == 0) /* xxx scope error ?*/
  274                                 ia6 = ifatoia6(ro->ro_rt->rt_ifa);
  275                 }
  276 #if 0
  277                 /*
  278                  * xxx The followings are necessary? (kazu)
  279                  * I don't think so.
  280                  * It's for SO_DONTROUTE option in IPv4.(jinmei)
  281                  */
  282                 if (ia6 == 0) {
  283                         struct sockaddr_in6 sin6 = {sizeof(sin6), AF_INET6, 0};
  284 
  285                         sin6->sin6_addr = *dst;
  286 
  287                         ia6 = ifatoia6(ifa_ifwithdstaddr(sin6tosa(&sin6)));
  288                         if (ia6 == 0)
  289                                 ia6 = ifatoia6(ifa_ifwithnet(sin6tosa(&sin6)));
  290                         if (ia6 == 0)
  291                                 return(0);
  292                         return(&satosin6(&ia6->ia_addr)->sin6_addr);
  293                 }
  294 #endif /* 0 */
  295                 if (ia6 == 0) {
  296                         *errorp = EHOSTUNREACH; /* no route */
  297                         return(0);
  298                 }
  299                 return(&satosin6(&ia6->ia_addr)->sin6_addr);
  300         }
  301 
  302         *errorp = EADDRNOTAVAIL;
  303         return(0);
  304 }
  305 
  306 /*
  307  * Default hop limit selection. The precedence is as follows:
  308  * 1. Hoplimit value specified via ioctl.
  309  * 2. (If the outgoing interface is detected) the current
  310  *     hop limit of the interface specified by router advertisement.
  311  * 3. The system default hoplimit.
  312 */
  313 int
  314 in6_selecthlim(in6p, ifp)
  315         struct in6pcb *in6p;
  316         struct ifnet *ifp;
  317 {
  318         if (in6p && in6p->in6p_hops >= 0)
  319                 return(in6p->in6p_hops);
  320         else if (ifp)
  321                 return(nd_ifinfo[ifp->if_index].chlim);
  322         else
  323                 return(ip6_defhlim);
  324 }
  325 
  326 /*
  327  * XXX: this is borrowed from in6_pcbbind(). If possible, we should
  328  * share this function by all *bsd*...
  329  */
  330 int
  331 in6_pcbsetport(laddr, inp, td)
  332         struct in6_addr *laddr;
  333         struct inpcb *inp;
  334         struct thread *td;
  335 {
  336         struct socket *so = inp->inp_socket;
  337         u_int16_t lport = 0, first, last, *lastport;
  338         int count, error = 0, wild = 0;
  339         struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
  340 
  341         /* XXX: this is redundant when called from in6_pcbbind */
  342         if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
  343                 wild = INPLOOKUP_WILDCARD;
  344 
  345         inp->inp_flags |= INP_ANONPORT;
  346 
  347         if (inp->inp_flags & INP_HIGHPORT) {
  348                 first = ipport_hifirstauto;     /* sysctl */
  349                 last  = ipport_hilastauto;
  350                 lastport = &pcbinfo->lasthi;
  351         } else if (inp->inp_flags & INP_LOWPORT) {
  352                 if (td && (error = suser(td)))
  353                         return error;
  354                 first = ipport_lowfirstauto;    /* 1023 */
  355                 last  = ipport_lowlastauto;     /* 600 */
  356                 lastport = &pcbinfo->lastlow;
  357         } else {
  358                 first = ipport_firstauto;       /* sysctl */
  359                 last  = ipport_lastauto;
  360                 lastport = &pcbinfo->lastport;
  361         }
  362         /*
  363          * Simple check to ensure all ports are not used up causing
  364          * a deadlock here.
  365          *
  366          * We split the two cases (up and down) so that the direction
  367          * is not being tested on each round of the loop.
  368          */
  369         if (first > last) {
  370                 /*
  371                  * counting down
  372                  */
  373                 count = first - last;
  374 
  375                 do {
  376                         if (count-- < 0) {      /* completely used? */
  377                                 /*
  378                                  * Undo any address bind that may have
  379                                  * occurred above.
  380                                  */
  381                                 inp->in6p_laddr = in6addr_any;
  382                                 return (EAGAIN);
  383                         }
  384                         --*lastport;
  385                         if (*lastport > first || *lastport < last)
  386                                 *lastport = first;
  387                         lport = htons(*lastport);
  388                 } while (in6_pcblookup_local(pcbinfo,
  389                                              &inp->in6p_laddr, lport, wild));
  390         } else {
  391                 /*
  392                          * counting up
  393                          */
  394                 count = last - first;
  395 
  396                 do {
  397                         if (count-- < 0) {      /* completely used? */
  398                                 /*
  399                                  * Undo any address bind that may have
  400                                  * occurred above.
  401                                  */
  402                                 inp->in6p_laddr = in6addr_any;
  403                                 return (EAGAIN);
  404                         }
  405                         ++*lastport;
  406                         if (*lastport < first || *lastport > last)
  407                                 *lastport = first;
  408                         lport = htons(*lastport);
  409                 } while (in6_pcblookup_local(pcbinfo,
  410                                              &inp->in6p_laddr, lport, wild));
  411         }
  412 
  413         inp->inp_lport = lport;
  414         if (in_pcbinshash(inp) != 0) {
  415                 inp->in6p_laddr = in6addr_any;
  416                 inp->inp_lport = 0;
  417                 return (EAGAIN);
  418         }
  419 
  420         return(0);
  421 }
  422 
  423 /*
  424  * generate kernel-internal form (scopeid embedded into s6_addr16[1]).
  425  * If the address scope of is link-local, embed the interface index in the
  426  * address.  The routine determines our precedence
  427  * between advanced API scope/interface specification and basic API
  428  * specification.
  429  *
  430  * this function should be nuked in the future, when we get rid of
  431  * embedded scopeid thing.
  432  *
  433  * XXX actually, it is over-specification to return ifp against sin6_scope_id.
  434  * there can be multiple interfaces that belong to a particular scope zone
  435  * (in specification, we have 1:N mapping between a scope zone and interfaces).
  436  * we may want to change the function to return something other than ifp.
  437  */
  438 int
  439 in6_embedscope(in6, sin6, in6p, ifpp)
  440         struct in6_addr *in6;
  441         const struct sockaddr_in6 *sin6;
  442 #ifdef HAVE_NRL_INPCB
  443         struct inpcb *in6p;
  444 #define in6p_outputopts inp_outputopts6
  445 #define in6p_moptions   inp_moptions6
  446 #else
  447         struct in6pcb *in6p;
  448 #endif
  449         struct ifnet **ifpp;
  450 {
  451         struct ifnet *ifp = NULL;
  452         u_int32_t scopeid;
  453 
  454         *in6 = sin6->sin6_addr;
  455         scopeid = sin6->sin6_scope_id;
  456         if (ifpp)
  457                 *ifpp = NULL;
  458 
  459         /*
  460          * don't try to read sin6->sin6_addr beyond here, since the caller may
  461          * ask us to overwrite existing sockaddr_in6
  462          */
  463 
  464 #ifdef ENABLE_DEFAULT_SCOPE
  465         if (scopeid == 0)
  466                 scopeid = scope6_addr2default(in6);
  467 #endif
  468 
  469         if (IN6_IS_SCOPE_LINKLOCAL(in6)) {
  470                 struct in6_pktinfo *pi;
  471 
  472                 /*
  473                  * KAME assumption: link id == interface id
  474                  */
  475 
  476                 if (in6p && in6p->in6p_outputopts &&
  477                     (pi = in6p->in6p_outputopts->ip6po_pktinfo) &&
  478                     pi->ipi6_ifindex) {
  479                         ifp = ifnet_byindex(pi->ipi6_ifindex);
  480                         in6->s6_addr16[1] = htons(pi->ipi6_ifindex);
  481                 } else if (in6p && IN6_IS_ADDR_MULTICAST(in6) &&
  482                            in6p->in6p_moptions &&
  483                            in6p->in6p_moptions->im6o_multicast_ifp) {
  484                         ifp = in6p->in6p_moptions->im6o_multicast_ifp;
  485                         in6->s6_addr16[1] = htons(ifp->if_index);
  486                 } else if (scopeid) {
  487                         /* boundary check */
  488                         if (scopeid < 0 || if_index < scopeid)
  489                                 return ENXIO;  /* XXX EINVAL? */
  490                         ifp = ifnet_byindex(scopeid);
  491                         /*XXX assignment to 16bit from 32bit variable */
  492                         in6->s6_addr16[1] = htons(scopeid & 0xffff);
  493                 }
  494 
  495                 if (ifpp)
  496                         *ifpp = ifp;
  497         }
  498 
  499         return 0;
  500 }
  501 #ifdef HAVE_NRL_INPCB
  502 #undef in6p_outputopts
  503 #undef in6p_moptions
  504 #endif
  505 
  506 /*
  507  * generate standard sockaddr_in6 from embedded form.
  508  * touches sin6_addr and sin6_scope_id only.
  509  *
  510  * this function should be nuked in the future, when we get rid of
  511  * embedded scopeid thing.
  512  */
  513 int
  514 in6_recoverscope(sin6, in6, ifp)
  515         struct sockaddr_in6 *sin6;
  516         const struct in6_addr *in6;
  517         struct ifnet *ifp;
  518 {
  519         u_int32_t scopeid;
  520 
  521         sin6->sin6_addr = *in6;
  522 
  523         /*
  524          * don't try to read *in6 beyond here, since the caller may
  525          * ask us to overwrite existing sockaddr_in6
  526          */
  527 
  528         sin6->sin6_scope_id = 0;
  529         if (IN6_IS_SCOPE_LINKLOCAL(in6)) {
  530                 /*
  531                  * KAME assumption: link id == interface id
  532                  */
  533                 scopeid = ntohs(sin6->sin6_addr.s6_addr16[1]);
  534                 if (scopeid) {
  535                         /* sanity check */
  536                         if (scopeid < 0 || if_index < scopeid)
  537                                 return ENXIO;
  538                         if (ifp && ifp->if_index != scopeid)
  539                                 return ENXIO;
  540                         sin6->sin6_addr.s6_addr16[1] = 0;
  541                         sin6->sin6_scope_id = scopeid;
  542                 }
  543         }
  544 
  545         return 0;
  546 }
  547 
  548 /*
  549  * just clear the embedded scope identifer.
  550  * XXX: currently used for bsdi4 only as a supplement function.
  551  */
  552 void
  553 in6_clearscope(addr)
  554         struct in6_addr *addr;
  555 {
  556         if (IN6_IS_SCOPE_LINKLOCAL(addr))
  557                 addr->s6_addr16[1] = 0;
  558 }

Cache object: 3a8f70537dc8712beaed9bc23ba17aea


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