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/ip6_forward.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: ip6_forward.c,v 1.69 2001/05/17 03:48:30 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 #include "opt_ip6fw.h"
   34 #include "opt_inet.h"
   35 #include "opt_inet6.h"
   36 #include "opt_ipsec.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/domain.h>
   43 #include <sys/protosw.h>
   44 #include <sys/socket.h>
   45 #include <sys/errno.h>
   46 #include <sys/time.h>
   47 #include <sys/kernel.h>
   48 #include <sys/syslog.h>
   49 
   50 #include <net/if.h>
   51 #include <net/route.h>
   52 
   53 #include <netinet/in.h>
   54 #include <netinet/in_var.h>
   55 #include <netinet/in_systm.h>
   56 #include <netinet/ip.h>
   57 #include <netinet/ip_var.h>
   58 #include <netinet6/in6_var.h>
   59 #include <netinet/ip6.h>
   60 #include <netinet6/ip6_var.h>
   61 #include <netinet/icmp6.h>
   62 #include <netinet6/nd6.h>
   63 
   64 #include <netinet/in_pcb.h>
   65 
   66 #ifdef IPSEC
   67 #include <netinet6/ipsec.h>
   68 #ifdef INET6
   69 #include <netinet6/ipsec6.h>
   70 #endif
   71 #include <netkey/key.h>
   72 #endif /* IPSEC */
   73 
   74 #ifdef FAST_IPSEC
   75 #include <netipsec/ipsec.h>
   76 #include <netipsec/ipsec6.h>
   77 #include <netipsec/key.h>
   78 #define IPSEC
   79 #endif /* FAST_IPSEC */
   80 
   81 #include <netinet6/ip6_fw.h>
   82 
   83 #include <net/net_osdep.h>
   84 
   85 extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **));
   86 
   87 struct  route_in6 ip6_forward_rt;
   88 
   89 /*
   90  * Forward a packet.  If some error occurs return the sender
   91  * an icmp packet.  Note we can't always generate a meaningful
   92  * icmp message because icmp doesn't have a large enough repertoire
   93  * of codes and types.
   94  *
   95  * If not forwarding, just drop the packet.  This could be confusing
   96  * if ipforwarding was zero but some routing protocol was advancing
   97  * us as a gateway to somewhere.  However, we must let the routing
   98  * protocol deal with that.
   99  *
  100  */
  101 
  102 void
  103 ip6_forward(m, srcrt)
  104         struct mbuf *m;
  105         int srcrt;
  106 {
  107         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
  108         struct sockaddr_in6 *dst;
  109         struct rtentry *rt;
  110         int error, type = 0, code = 0;
  111         struct mbuf *mcopy = NULL;
  112         struct ifnet *origifp;  /* maybe unnecessary */
  113 #ifdef IPSEC
  114         struct secpolicy *sp = NULL;
  115 #endif
  116 
  117 #ifdef IPSEC
  118         /*
  119          * Check AH/ESP integrity.
  120          */
  121         /*
  122          * Don't increment ip6s_cantforward because this is the check
  123          * before forwarding packet actually.
  124          */
  125         if (ipsec6_in_reject(m, NULL)) {
  126 #if !defined(FAST_IPSEC)
  127                 ipsec6stat.in_polvio++;
  128 #endif
  129                 m_freem(m);
  130                 return;
  131         }
  132 #endif /* IPSEC */
  133 
  134         /*
  135          * Do not forward packets to multicast destination (should be handled
  136          * by ip6_mforward().
  137          * Do not forward packets with unspecified source.  It was discussed
  138          * in July 2000, on ipngwg mailing list.
  139          */
  140         if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
  141             IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
  142             IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
  143                 ip6stat.ip6s_cantforward++;
  144                 /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
  145                 if (ip6_log_time + ip6_log_interval < time_second) {
  146                         ip6_log_time = time_second;
  147                         log(LOG_DEBUG,
  148                             "cannot forward "
  149                             "from %s to %s nxt %d received on %s\n",
  150                             ip6_sprintf(&ip6->ip6_src),
  151                             ip6_sprintf(&ip6->ip6_dst),
  152                             ip6->ip6_nxt,
  153                             if_name(m->m_pkthdr.rcvif));
  154                 }
  155                 m_freem(m);
  156                 return;
  157         }
  158 
  159         if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
  160                 /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
  161                 icmp6_error(m, ICMP6_TIME_EXCEEDED,
  162                                 ICMP6_TIME_EXCEED_TRANSIT, 0);
  163                 return;
  164         }
  165         ip6->ip6_hlim -= IPV6_HLIMDEC;
  166 
  167         /*
  168          * Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU -
  169          * size of IPv6 + ICMPv6 headers) bytes of the packet in case
  170          * we need to generate an ICMP6 message to the src.
  171          * Thanks to M_EXT, in most cases copy will not occur.
  172          *
  173          * It is important to save it before IPsec processing as IPsec
  174          * processing may modify the mbuf.
  175          */
  176         mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));
  177 
  178 #ifdef IPSEC
  179         /* get a security policy for this packet */
  180         sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING,
  181             &error);
  182         if (sp == NULL) {
  183                 ipsec6stat.out_inval++;
  184                 ip6stat.ip6s_cantforward++;
  185                 if (mcopy) {
  186 #if 0
  187                         /* XXX: what icmp ? */
  188 #else
  189                         m_freem(mcopy);
  190 #endif
  191                 }
  192                 m_freem(m);
  193                 return;
  194         }
  195 
  196         error = 0;
  197 
  198         /* check policy */
  199         switch (sp->policy) {
  200         case IPSEC_POLICY_DISCARD:
  201                 /*
  202                  * This packet is just discarded.
  203                  */
  204                 ipsec6stat.out_polvio++;
  205                 ip6stat.ip6s_cantforward++;
  206                 key_freesp(sp);
  207                 if (mcopy) {
  208 #if 0
  209                         /* XXX: what icmp ? */
  210 #else
  211                         m_freem(mcopy);
  212 #endif
  213                 }
  214                 m_freem(m);
  215                 return;
  216 
  217         case IPSEC_POLICY_BYPASS:
  218         case IPSEC_POLICY_NONE:
  219                 /* no need to do IPsec. */
  220                 key_freesp(sp);
  221                 goto skip_ipsec;
  222 
  223         case IPSEC_POLICY_IPSEC:
  224                 if (sp->req == NULL) {
  225                         /* XXX should be panic ? */
  226                         printf("ip6_forward: No IPsec request specified.\n");
  227                         ip6stat.ip6s_cantforward++;
  228                         key_freesp(sp);
  229                         if (mcopy) {
  230 #if 0
  231                                 /* XXX: what icmp ? */
  232 #else
  233                                 m_freem(mcopy);
  234 #endif
  235                         }
  236                         m_freem(m);
  237                         return;
  238                 }
  239                 /* do IPsec */
  240                 break;
  241 
  242         case IPSEC_POLICY_ENTRUST:
  243         default:
  244                 /* should be panic ?? */
  245                 printf("ip6_forward: Invalid policy found. %d\n", sp->policy);
  246                 key_freesp(sp);
  247                 goto skip_ipsec;
  248         }
  249 
  250     {
  251         struct ipsec_output_state state;
  252 
  253         /*
  254          * All the extension headers will become inaccessible
  255          * (since they can be encrypted).
  256          * Don't panic, we need no more updates to extension headers
  257          * on inner IPv6 packet (since they are now encapsulated).
  258          *
  259          * IPv6 [ESP|AH] IPv6 [extension headers] payload
  260          */
  261         bzero(&state, sizeof(state));
  262         state.m = m;
  263         state.ro = NULL;        /* update at ipsec6_output_tunnel() */
  264         state.dst = NULL;       /* update at ipsec6_output_tunnel() */
  265 
  266         error = ipsec6_output_tunnel(&state, sp, 0);
  267 
  268         m = state.m;
  269         key_freesp(sp);
  270 
  271         if (error) {
  272                 /* mbuf is already reclaimed in ipsec6_output_tunnel. */
  273                 switch (error) {
  274                 case EHOSTUNREACH:
  275                 case ENETUNREACH:
  276                 case EMSGSIZE:
  277                 case ENOBUFS:
  278                 case ENOMEM:
  279                         break;
  280                 default:
  281                         printf("ip6_output (ipsec): error code %d\n", error);
  282                         /* fall through */
  283                 case ENOENT:
  284                         /* don't show these error codes to the user */
  285                         break;
  286                 }
  287                 ip6stat.ip6s_cantforward++;
  288                 if (mcopy) {
  289 #if 0
  290                         /* XXX: what icmp ? */
  291 #else
  292                         m_freem(mcopy);
  293 #endif
  294                 }
  295                 m_freem(m);
  296                 return;
  297         }
  298     }
  299     skip_ipsec:
  300 #endif /* IPSEC */
  301 
  302         dst = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst;
  303         if (!srcrt) {
  304                 /*
  305                  * ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst
  306                  */
  307                 if (ip6_forward_rt.ro_rt == 0 ||
  308                     (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) == 0) {
  309                         if (ip6_forward_rt.ro_rt) {
  310                                 RTFREE(ip6_forward_rt.ro_rt);
  311                                 ip6_forward_rt.ro_rt = 0;
  312                         }
  313                         /* this probably fails but give it a try again */
  314                         rtalloc_ign((struct route *)&ip6_forward_rt,
  315                                     RTF_PRCLONING);
  316                 }
  317 
  318                 if (ip6_forward_rt.ro_rt == 0) {
  319                         ip6stat.ip6s_noroute++;
  320                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute);
  321                         if (mcopy) {
  322                                 icmp6_error(mcopy, ICMP6_DST_UNREACH,
  323                                             ICMP6_DST_UNREACH_NOROUTE, 0);
  324                         }
  325                         m_freem(m);
  326                         return;
  327                 }
  328         } else if ((rt = ip6_forward_rt.ro_rt) == 0 ||
  329                  !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst->sin6_addr)) {
  330                 if (ip6_forward_rt.ro_rt) {
  331                         RTFREE(ip6_forward_rt.ro_rt);
  332                         ip6_forward_rt.ro_rt = 0;
  333                 }
  334                 bzero(dst, sizeof(*dst));
  335                 dst->sin6_len = sizeof(struct sockaddr_in6);
  336                 dst->sin6_family = AF_INET6;
  337                 dst->sin6_addr = ip6->ip6_dst;
  338 
  339                 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
  340                 if (ip6_forward_rt.ro_rt == 0) {
  341                         ip6stat.ip6s_noroute++;
  342                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute);
  343                         if (mcopy) {
  344                                 icmp6_error(mcopy, ICMP6_DST_UNREACH,
  345                                             ICMP6_DST_UNREACH_NOROUTE, 0);
  346                         }
  347                         m_freem(m);
  348                         return;
  349                 }
  350         }
  351         rt = ip6_forward_rt.ro_rt;
  352 
  353         /*
  354          * Scope check: if a packet can't be delivered to its destination
  355          * for the reason that the destination is beyond the scope of the
  356          * source address, discard the packet and return an icmp6 destination
  357          * unreachable error with Code 2 (beyond scope of source address).
  358          * [draft-ietf-ipngwg-icmp-v3-02.txt, Section 3.1]
  359          */
  360         if (in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_src) !=
  361             in6_addr2scopeid(rt->rt_ifp, &ip6->ip6_src)) {
  362                 ip6stat.ip6s_cantforward++;
  363                 ip6stat.ip6s_badscope++;
  364                 in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);
  365 
  366                 if (ip6_log_time + ip6_log_interval < time_second) {
  367                         ip6_log_time = time_second;
  368                         log(LOG_DEBUG,
  369                             "cannot forward "
  370                             "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
  371                             ip6_sprintf(&ip6->ip6_src),
  372                             ip6_sprintf(&ip6->ip6_dst),
  373                             ip6->ip6_nxt,
  374                             if_name(m->m_pkthdr.rcvif), if_name(rt->rt_ifp));
  375                 }
  376                 if (mcopy)
  377                         icmp6_error(mcopy, ICMP6_DST_UNREACH,
  378                                     ICMP6_DST_UNREACH_BEYONDSCOPE, 0);
  379                 m_freem(m);
  380                 return;
  381         }
  382 
  383         if (m->m_pkthdr.len > rt->rt_ifp->if_mtu) {
  384                 in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
  385                 if (mcopy) {
  386                         u_long mtu;
  387 #ifdef IPSEC
  388                         struct secpolicy *sp;
  389                         int ipsecerror;
  390                         size_t ipsechdrsiz;
  391 #endif
  392 
  393                         mtu = rt->rt_ifp->if_mtu;
  394 #ifdef IPSEC
  395                         /*
  396                          * When we do IPsec tunnel ingress, we need to play
  397                          * with if_mtu value (decrement IPsec header size
  398                          * from mtu value).  The code is much simpler than v4
  399                          * case, as we have the outgoing interface for
  400                          * encapsulated packet as "rt->rt_ifp".
  401                          */
  402                         sp = ipsec6_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND,
  403                                 IP_FORWARDING, &ipsecerror);
  404                         if (sp) {
  405                                 ipsechdrsiz = ipsec6_hdrsiz(mcopy,
  406                                         IPSEC_DIR_OUTBOUND, NULL);
  407                                 if (ipsechdrsiz < mtu)
  408                                         mtu -= ipsechdrsiz;
  409                         }
  410 
  411                         /*
  412                          * if mtu becomes less than minimum MTU,
  413                          * tell minimum MTU (and I'll need to fragment it).
  414                          */
  415                         if (mtu < IPV6_MMTU)
  416                                 mtu = IPV6_MMTU;
  417 #endif
  418                         icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu);
  419                 }
  420                 m_freem(m);
  421                 return;
  422         }
  423 
  424         if (rt->rt_flags & RTF_GATEWAY)
  425                 dst = (struct sockaddr_in6 *)rt->rt_gateway;
  426 
  427         /*
  428          * If we are to forward the packet using the same interface
  429          * as one we got the packet from, perhaps we should send a redirect
  430          * to sender to shortcut a hop.
  431          * Only send redirect if source is sending directly to us,
  432          * and if packet was not source routed (or has any options).
  433          * Also, don't send redirect if forwarding using a route
  434          * modified by a redirect.
  435          */
  436         if (rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt &&
  437             (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {
  438                 if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) != 0) {
  439                         /*
  440                          * If the incoming interface is equal to the outgoing
  441                          * one, and the link attached to the interface is
  442                          * point-to-point, then it will be highly probable
  443                          * that a routing loop occurs. Thus, we immediately
  444                          * drop the packet and send an ICMPv6 error message.
  445                          *
  446                          * type/code is based on suggestion by Rich Draves.
  447                          * not sure if it is the best pick.
  448                          */
  449                         icmp6_error(mcopy, ICMP6_DST_UNREACH,
  450                                     ICMP6_DST_UNREACH_ADDR, 0);
  451                         m_freem(m);
  452                         return;
  453                 }
  454                 type = ND_REDIRECT;
  455         }
  456 
  457         /*
  458          * Check with the firewall...
  459          */
  460         if (ip6_fw_enable && ip6_fw_chk_ptr) {
  461                 u_short port = 0;
  462                 /* If ipfw says divert, we have to just drop packet */
  463                 if ((*ip6_fw_chk_ptr)(&ip6, rt->rt_ifp, &port, &m)) {
  464                         m_freem(m);
  465                         goto freecopy;
  466                 }
  467                 if (!m)
  468                         goto freecopy;
  469         }
  470 
  471         /*
  472          * Fake scoped addresses. Note that even link-local source or
  473          * destinaion can appear, if the originating node just sends the
  474          * packet to us (without address resolution for the destination).
  475          * Since both icmp6_error and icmp6_redirect_output fill the embedded
  476          * link identifiers, we can do this stuff after making a copy for
  477          * returning an error.
  478          */
  479         if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
  480                 /*
  481                  * See corresponding comments in ip6_output.
  482                  * XXX: but is it possible that ip6_forward() sends a packet
  483                  *      to a loopback interface? I don't think so, and thus
  484                  *      I bark here. (jinmei@kame.net)
  485                  * XXX: it is common to route invalid packets to loopback.
  486                  *      also, the codepath will be visited on use of ::1 in
  487                  *      rthdr. (itojun)
  488                  */
  489 #if 1
  490                 if (0)
  491 #else
  492                 if ((rt->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) == 0)
  493 #endif
  494                 {
  495                         printf("ip6_forward: outgoing interface is loopback. "
  496                                 "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
  497                                 ip6_sprintf(&ip6->ip6_src),
  498                                 ip6_sprintf(&ip6->ip6_dst),
  499                                 ip6->ip6_nxt, if_name(m->m_pkthdr.rcvif),
  500                                 if_name(rt->rt_ifp));
  501                 }
  502 
  503                 /* we can just use rcvif in forwarding. */
  504                 origifp = m->m_pkthdr.rcvif;
  505         }
  506         else
  507                 origifp = rt->rt_ifp;
  508 #ifndef SCOPEDROUTING
  509         /*
  510          * clear embedded scope identifiers if necessary.
  511          * in6_clearscope will touch the addresses only when necessary.
  512          */
  513         in6_clearscope(&ip6->ip6_src);
  514         in6_clearscope(&ip6->ip6_dst);
  515 #endif
  516 
  517         /*
  518          * Check if we want to allow this packet to be processed.
  519          * Consider it to be bad if not.
  520          */
  521         if (fr_checkp) {
  522                 struct  mbuf    *m1 = m;
  523 
  524                 if ((*fr_checkp)((struct ip *)ip6, sizeof(*ip6),
  525                                  rt->rt_ifp, 1, &m1) != 0)
  526                         goto freecopy;
  527                 m = m1;
  528                 if (m == NULL)
  529                         goto freecopy;
  530                 ip6 = mtod(m, struct ip6_hdr *);
  531         }
  532 
  533         error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
  534         if (error) {
  535                 in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
  536                 ip6stat.ip6s_cantforward++;
  537         } else {
  538                 ip6stat.ip6s_forward++;
  539                 in6_ifstat_inc(rt->rt_ifp, ifs6_out_forward);
  540                 if (type)
  541                         ip6stat.ip6s_redirectsent++;
  542                 else {
  543                         if (mcopy)
  544                                 goto freecopy;
  545                 }
  546         }
  547         if (mcopy == NULL)
  548                 return;
  549         switch (error) {
  550         case 0:
  551 #if 1
  552                 if (type == ND_REDIRECT) {
  553                         icmp6_redirect_output(mcopy, rt);
  554                         return;
  555                 }
  556 #endif
  557                 goto freecopy;
  558 
  559         case EMSGSIZE:
  560                 /* xxx MTU is constant in PPP? */
  561                 goto freecopy;
  562 
  563         case ENOBUFS:
  564                 /* Tell source to slow down like source quench in IP? */
  565                 goto freecopy;
  566 
  567         case ENETUNREACH:       /* shouldn't happen, checked above */
  568         case EHOSTUNREACH:
  569         case ENETDOWN:
  570         case EHOSTDOWN:
  571         default:
  572                 type = ICMP6_DST_UNREACH;
  573                 code = ICMP6_DST_UNREACH_ADDR;
  574                 break;
  575         }
  576         icmp6_error(mcopy, type, code, 0);
  577         return;
  578 
  579  freecopy:
  580         m_freem(mcopy);
  581         return;
  582 }

Cache object: 0b169af0bd05b383916966d7451c2a7b


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