ip6_forward.c revision 88069
1294838Szbb/* $FreeBSD: head/sys/netinet6/ip6_forward.c 88069 2001-12-17 18:13:12Z sumikawa $ */ 2294838Szbb/* $KAME: ip6_forward.c,v 1.69 2001/05/17 03:48:30 itojun Exp $ */ 3294838Szbb 4294838Szbb/* 5294838Szbb * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6294838Szbb * All rights reserved. 7294838Szbb * 8294838Szbb * Redistribution and use in source and binary forms, with or without 9294838Szbb * modification, are permitted provided that the following conditions 10294838Szbb * are met: 11294838Szbb * 1. Redistributions of source code must retain the above copyright 12294838Szbb * notice, this list of conditions and the following disclaimer. 13294838Szbb * 2. Redistributions in binary form must reproduce the above copyright 14294838Szbb * notice, this list of conditions and the following disclaimer in the 15294838Szbb * documentation and/or other materials provided with the distribution. 16294838Szbb * 3. Neither the name of the project nor the names of its contributors 17294838Szbb * may be used to endorse or promote products derived from this software 18294838Szbb * without specific prior written permission. 19294838Szbb * 20294838Szbb * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21294838Szbb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22294838Szbb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23294838Szbb * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24294838Szbb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25294838Szbb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26294838Szbb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27294838Szbb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28294838Szbb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29294838Szbb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30294838Szbb * SUCH DAMAGE. 31294838Szbb */ 32294838Szbb 33294838Szbb#include "opt_ip6fw.h" 34294838Szbb#include "opt_inet.h" 35294838Szbb#include "opt_inet6.h" 36294838Szbb#include "opt_ipsec.h" 37294838Szbb 38294838Szbb#include <sys/param.h> 39294838Szbb#include <sys/systm.h> 40294838Szbb#include <sys/malloc.h> 41294838Szbb#include <sys/mbuf.h> 42294838Szbb#include <sys/domain.h> 43294838Szbb#include <sys/protosw.h> 44294838Szbb#include <sys/socket.h> 45294838Szbb#include <sys/errno.h> 46294838Szbb#include <sys/time.h> 47294838Szbb#include <sys/kernel.h> 48294838Szbb#include <sys/syslog.h> 49294838Szbb 50294838Szbb#include <net/if.h> 51294838Szbb#include <net/route.h> 52294838Szbb#ifdef PFIL_HOOKS 53294838Szbb#include <net/pfil.h> 54294838Szbb#endif 55294838Szbb 56294838Szbb#include <netinet/in.h> 57294838Szbb#include <netinet/in_var.h> 58294838Szbb#include <netinet/in_systm.h> 59294838Szbb#include <netinet/ip.h> 60294838Szbb#include <netinet/ip_var.h> 61294838Szbb#include <netinet6/in6_var.h> 62294838Szbb#include <netinet/ip6.h> 63294838Szbb#include <netinet6/ip6_var.h> 64294838Szbb#include <netinet/icmp6.h> 65294838Szbb#include <netinet6/nd6.h> 66294838Szbb 67294838Szbb#include <netinet/in_pcb.h> 68294838Szbb 69294838Szbb#ifdef IPSEC 70294838Szbb#include <netinet6/ipsec.h> 71294838Szbb#ifdef INET6 72294838Szbb#include <netinet6/ipsec6.h> 73294838Szbb#endif 74294838Szbb#include <netkey/key.h> 75294838Szbb#endif /* IPSEC */ 76294838Szbb 77294838Szbb#include <netinet6/ip6_fw.h> 78294838Szbb 79294838Szbb#include <net/net_osdep.h> 80294838Szbb 81294838Szbb#include <netinet6/ip6protosw.h> 82294838Szbb 83294838Szbbextern struct ip6protosw inet6sw[]; 84294838Szbbextern u_char ip6_protox[IPPROTO_MAX]; 85294838Szbb 86294838Szbbstruct route_in6 ip6_forward_rt; 87294838Szbb 88294838Szbb/* 89294838Szbb * Forward a packet. If some error occurs return the sender 90294838Szbb * an icmp packet. Note we can't always generate a meaningful 91294838Szbb * icmp message because icmp doesn't have a large enough repertoire 92294838Szbb * of codes and types. 93294838Szbb * 94294838Szbb * If not forwarding, just drop the packet. This could be confusing 95294838Szbb * if ipforwarding was zero but some routing protocol was advancing 96294838Szbb * us as a gateway to somewhere. However, we must let the routing 97294838Szbb * protocol deal with that. 98294838Szbb * 99294838Szbb */ 100294838Szbb 101294838Szbbvoid 102294838Szbbip6_forward(m, srcrt) 103294838Szbb struct mbuf *m; 104294838Szbb int srcrt; 105294838Szbb{ 106294838Szbb struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 107294838Szbb struct sockaddr_in6 *dst; 108294838Szbb struct rtentry *rt; 109294838Szbb int error, type = 0, code = 0; 110294838Szbb struct mbuf *mcopy = NULL; 111294838Szbb struct ifnet *origifp; /* maybe unnecessary */ 112294838Szbb#ifdef PFIL_HOOKS 113294838Szbb struct packet_filter_hook *pfh; 114294838Szbb struct mbuf *m1; 115294838Szbb int rv; 116294838Szbb#endif /* PFIL_HOOKS */ 117294838Szbb#ifdef IPSEC 118294838Szbb struct secpolicy *sp = NULL; 119294838Szbb#endif 120294838Szbb 121294838Szbb#ifdef IPSEC 122294838Szbb /* 123294838Szbb * Check AH/ESP integrity. 124294838Szbb */ 125294838Szbb /* 126294838Szbb * Don't increment ip6s_cantforward because this is the check 127294838Szbb * before forwarding packet actually. 128294838Szbb */ 129294838Szbb if (ipsec6_in_reject(m, NULL)) { 130294838Szbb ipsec6stat.in_polvio++; 131294838Szbb m_freem(m); 132294838Szbb return; 133294838Szbb } 134294838Szbb#endif /*IPSEC*/ 135294838Szbb 136294838Szbb /* 137294838Szbb * Do not forward packets to multicast destination (should be handled 138294838Szbb * by ip6_mforward(). 139294838Szbb * Do not forward packets with unspecified source. It was discussed 140294838Szbb * in July 2000, on ipngwg mailing list. 141294838Szbb */ 142294838Szbb if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 || 143294838Szbb IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || 144294838Szbb IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { 145294838Szbb ip6stat.ip6s_cantforward++; 146294838Szbb /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */ 147294838Szbb if (ip6_log_time + ip6_log_interval < time_second) { 148294838Szbb ip6_log_time = time_second; 149294838Szbb log(LOG_DEBUG, 150294838Szbb "cannot forward " 151294838Szbb "from %s to %s nxt %d received on %s\n", 152294838Szbb ip6_sprintf(&ip6->ip6_src), 153294838Szbb ip6_sprintf(&ip6->ip6_dst), 154294838Szbb ip6->ip6_nxt, 155294838Szbb if_name(m->m_pkthdr.rcvif)); 156294838Szbb } 157294838Szbb m_freem(m); 158294838Szbb return; 159294838Szbb } 160294838Szbb 161294838Szbb if (ip6->ip6_hlim <= IPV6_HLIMDEC) { 162294838Szbb /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */ 163294838Szbb icmp6_error(m, ICMP6_TIME_EXCEEDED, 164294838Szbb ICMP6_TIME_EXCEED_TRANSIT, 0); 165294838Szbb return; 166294838Szbb } 167294838Szbb ip6->ip6_hlim -= IPV6_HLIMDEC; 168294838Szbb 169294838Szbb /* 170294838Szbb * Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU - 171294838Szbb * size of IPv6 + ICMPv6 headers) bytes of the packet in case 172294838Szbb * we need to generate an ICMP6 message to the src. 173294838Szbb * Thanks to M_EXT, in most cases copy will not occur. 174294838Szbb * 175294838Szbb * It is important to save it before IPsec processing as IPsec 176294838Szbb * processing may modify the mbuf. 177294838Szbb */ 178294838Szbb mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN)); 179294838Szbb 180294838Szbb#ifdef IPSEC 181294838Szbb /* get a security policy for this packet */ 182294838Szbb sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING, 183294838Szbb &error); 184294838Szbb if (sp == NULL) { 185294838Szbb ipsec6stat.out_inval++; 186294838Szbb ip6stat.ip6s_cantforward++; 187294838Szbb if (mcopy) { 188294838Szbb#if 0 189294838Szbb /* XXX: what icmp ? */ 190294838Szbb#else 191294838Szbb m_freem(mcopy); 192294838Szbb#endif 193294838Szbb } 194294838Szbb m_freem(m); 195294838Szbb return; 196294838Szbb } 197294838Szbb 198294838Szbb error = 0; 199294838Szbb 200294838Szbb /* check policy */ 201294838Szbb switch (sp->policy) { 202294838Szbb case IPSEC_POLICY_DISCARD: 203294838Szbb /* 204294838Szbb * This packet is just discarded. 205294838Szbb */ 206294838Szbb ipsec6stat.out_polvio++; 207294838Szbb ip6stat.ip6s_cantforward++; 208294838Szbb key_freesp(sp); 209294838Szbb if (mcopy) { 210294838Szbb#if 0 211294838Szbb /* XXX: what icmp ? */ 212294838Szbb#else 213294838Szbb m_freem(mcopy); 214294838Szbb#endif 215294838Szbb } 216294838Szbb m_freem(m); 217294838Szbb return; 218294838Szbb 219294838Szbb case IPSEC_POLICY_BYPASS: 220294838Szbb case IPSEC_POLICY_NONE: 221294838Szbb /* no need to do IPsec. */ 222294838Szbb key_freesp(sp); 223294838Szbb goto skip_ipsec; 224294838Szbb 225294838Szbb case IPSEC_POLICY_IPSEC: 226294838Szbb if (sp->req == NULL) { 227294838Szbb /* XXX should be panic ? */ 228294838Szbb printf("ip6_forward: No IPsec request specified.\n"); 229294838Szbb ip6stat.ip6s_cantforward++; 230294838Szbb key_freesp(sp); 231294838Szbb if (mcopy) { 232294838Szbb#if 0 233294838Szbb /* XXX: what icmp ? */ 234294838Szbb#else 235294838Szbb m_freem(mcopy); 236294838Szbb#endif 237294838Szbb } 238294838Szbb m_freem(m); 239294838Szbb return; 240294838Szbb } 241294838Szbb /* do IPsec */ 242294838Szbb break; 243294838Szbb 244294838Szbb case IPSEC_POLICY_ENTRUST: 245294838Szbb default: 246294838Szbb /* should be panic ?? */ 247294838Szbb printf("ip6_forward: Invalid policy found. %d\n", sp->policy); 248294838Szbb key_freesp(sp); 249294838Szbb goto skip_ipsec; 250294838Szbb } 251294838Szbb 252294838Szbb { 253294838Szbb struct ipsec_output_state state; 254294838Szbb 255294838Szbb /* 256294838Szbb * All the extension headers will become inaccessible 257294838Szbb * (since they can be encrypted). 258294838Szbb * Don't panic, we need no more updates to extension headers 259294838Szbb * on inner IPv6 packet (since they are now encapsulated). 260294838Szbb * 261294838Szbb * IPv6 [ESP|AH] IPv6 [extension headers] payload 262294838Szbb */ 263294838Szbb bzero(&state, sizeof(state)); 264294838Szbb state.m = m; 265294838Szbb state.ro = NULL; /* update at ipsec6_output_tunnel() */ 266294838Szbb state.dst = NULL; /* update at ipsec6_output_tunnel() */ 267294838Szbb 268294838Szbb error = ipsec6_output_tunnel(&state, sp, 0); 269294838Szbb 270294838Szbb m = state.m; 271294838Szbb key_freesp(sp); 272294838Szbb 273294838Szbb if (error) { 274294838Szbb /* mbuf is already reclaimed in ipsec6_output_tunnel. */ 275294838Szbb switch (error) { 276294838Szbb case EHOSTUNREACH: 277294838Szbb case ENETUNREACH: 278294838Szbb case EMSGSIZE: 279294838Szbb case ENOBUFS: 280294838Szbb case ENOMEM: 281294838Szbb break; 282294838Szbb default: 283294838Szbb printf("ip6_output (ipsec): error code %d\n", error); 284294838Szbb /*fall through*/ 285294838Szbb case ENOENT: 286294838Szbb /* don't show these error codes to the user */ 287294838Szbb break; 288294838Szbb } 289294838Szbb ip6stat.ip6s_cantforward++; 290294838Szbb if (mcopy) { 291294838Szbb#if 0 292294838Szbb /* XXX: what icmp ? */ 293294838Szbb#else 294294838Szbb m_freem(mcopy); 295294838Szbb#endif 296294838Szbb } 297294838Szbb m_freem(m); 298294838Szbb return; 299294838Szbb } 300294838Szbb } 301294838Szbb skip_ipsec: 302294838Szbb#endif /* IPSEC */ 303294838Szbb 304294838Szbb dst = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst; 305294838Szbb if (!srcrt) { 306294838Szbb /* 307294838Szbb * ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst 308294838Szbb */ 309294838Szbb if (ip6_forward_rt.ro_rt == 0 || 310294838Szbb (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) == 0) { 311294838Szbb if (ip6_forward_rt.ro_rt) { 312294838Szbb RTFREE(ip6_forward_rt.ro_rt); 313294838Szbb ip6_forward_rt.ro_rt = 0; 314294838Szbb } 315294838Szbb /* this probably fails but give it a try again */ 316294838Szbb rtalloc_ign((struct route *)&ip6_forward_rt, 317294838Szbb RTF_PRCLONING); 318294838Szbb } 319294838Szbb 320294838Szbb if (ip6_forward_rt.ro_rt == 0) { 321294838Szbb ip6stat.ip6s_noroute++; 322294838Szbb in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute); 323294838Szbb if (mcopy) { 324294838Szbb icmp6_error(mcopy, ICMP6_DST_UNREACH, 325294838Szbb ICMP6_DST_UNREACH_NOROUTE, 0); 326294838Szbb } 327294838Szbb m_freem(m); 328294838Szbb return; 329294838Szbb } 330294838Szbb } else if ((rt = ip6_forward_rt.ro_rt) == 0 || 331294838Szbb !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst->sin6_addr)) { 332294838Szbb if (ip6_forward_rt.ro_rt) { 333294838Szbb RTFREE(ip6_forward_rt.ro_rt); 334294838Szbb ip6_forward_rt.ro_rt = 0; 335294838Szbb } 336294838Szbb bzero(dst, sizeof(*dst)); 337294838Szbb dst->sin6_len = sizeof(struct sockaddr_in6); 338294838Szbb dst->sin6_family = AF_INET6; 339294838Szbb dst->sin6_addr = ip6->ip6_dst; 340294838Szbb 341294838Szbb rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING); 342294838Szbb if (ip6_forward_rt.ro_rt == 0) { 343294838Szbb ip6stat.ip6s_noroute++; 344294838Szbb in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute); 345294838Szbb if (mcopy) { 346294838Szbb icmp6_error(mcopy, ICMP6_DST_UNREACH, 347294838Szbb ICMP6_DST_UNREACH_NOROUTE, 0); 348294838Szbb } 349294838Szbb m_freem(m); 350294838Szbb return; 351294838Szbb } 352294838Szbb } 353294838Szbb rt = ip6_forward_rt.ro_rt; 354294838Szbb 355294838Szbb /* 356294838Szbb * Scope check: if a packet can't be delivered to its destination 357294838Szbb * for the reason that the destination is beyond the scope of the 358294838Szbb * source address, discard the packet and return an icmp6 destination 359294838Szbb * unreachable error with Code 2 (beyond scope of source address). 360294838Szbb * [draft-ietf-ipngwg-icmp-v3-00.txt, Section 3.1] 361294838Szbb */ 362294838Szbb if (in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_src) != 363294838Szbb in6_addr2scopeid(rt->rt_ifp, &ip6->ip6_src)) { 364294838Szbb ip6stat.ip6s_cantforward++; 365294838Szbb ip6stat.ip6s_badscope++; 366294838Szbb in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard); 367294838Szbb 368294838Szbb if (ip6_log_time + ip6_log_interval < time_second) { 369294838Szbb ip6_log_time = time_second; 370294838Szbb log(LOG_DEBUG, 371294838Szbb "cannot forward " 372294838Szbb "src %s, dst %s, nxt %d, rcvif %s, outif %s\n", 373294838Szbb ip6_sprintf(&ip6->ip6_src), 374294838Szbb ip6_sprintf(&ip6->ip6_dst), 375294838Szbb ip6->ip6_nxt, 376294838Szbb if_name(m->m_pkthdr.rcvif), if_name(rt->rt_ifp)); 377294838Szbb } 378294838Szbb if (mcopy) 379294838Szbb icmp6_error(mcopy, ICMP6_DST_UNREACH, 380294838Szbb ICMP6_DST_UNREACH_BEYONDSCOPE, 0); 381294838Szbb m_freem(m); 382294838Szbb return; 383294838Szbb } 384294838Szbb 385294838Szbb if (m->m_pkthdr.len > rt->rt_ifp->if_mtu) { 386294838Szbb in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig); 387294838Szbb if (mcopy) { 388294838Szbb u_long mtu; 389294838Szbb#ifdef IPSEC 390294838Szbb struct secpolicy *sp; 391294838Szbb int ipsecerror; 392294838Szbb size_t ipsechdrsiz; 393294838Szbb#endif 394294838Szbb 395294838Szbb mtu = rt->rt_ifp->if_mtu; 396294838Szbb#ifdef IPSEC 397294838Szbb /* 398294838Szbb * When we do IPsec tunnel ingress, we need to play 399294838Szbb * with if_mtu value (decrement IPsec header size 400294838Szbb * from mtu value). The code is much simpler than v4 401294838Szbb * case, as we have the outgoing interface for 402294838Szbb * encapsulated packet as "rt->rt_ifp". 403294838Szbb */ 404294838Szbb sp = ipsec6_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND, 405294838Szbb IP_FORWARDING, &ipsecerror); 406294838Szbb if (sp) { 407294838Szbb ipsechdrsiz = ipsec6_hdrsiz(mcopy, 408294838Szbb IPSEC_DIR_OUTBOUND, NULL); 409294838Szbb if (ipsechdrsiz < mtu) 410294838Szbb mtu -= ipsechdrsiz; 411294838Szbb } 412294838Szbb 413294838Szbb /* 414294838Szbb * if mtu becomes less than minimum MTU, 415294838Szbb * tell minimum MTU (and I'll need to fragment it). 416294838Szbb */ 417294838Szbb if (mtu < IPV6_MMTU) 418294838Szbb mtu = IPV6_MMTU; 419294838Szbb#endif 420294838Szbb icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu); 421294838Szbb } 422294838Szbb m_freem(m); 423294838Szbb return; 424294838Szbb } 425294838Szbb 426294838Szbb if (rt->rt_flags & RTF_GATEWAY) 427294838Szbb dst = (struct sockaddr_in6 *)rt->rt_gateway; 428294838Szbb 429294838Szbb /* 430294838Szbb * If we are to forward the packet using the same interface 431294838Szbb * as one we got the packet from, perhaps we should send a redirect 432294838Szbb * to sender to shortcut a hop. 433294838Szbb * Only send redirect if source is sending directly to us, 434294838Szbb * and if packet was not source routed (or has any options). 435294838Szbb * Also, don't send redirect if forwarding using a route 436294838Szbb * modified by a redirect. 437294838Szbb */ 438294838Szbb if (rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt && 439294838Szbb (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) { 440294838Szbb if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) != 0) { 441294838Szbb /* 442294838Szbb * If the incoming interface is equal to the outgoing 443294838Szbb * one, and the link attached to the interface is 444294838Szbb * point-to-point, then it will be highly probable 445294838Szbb * that a routing loop occurs. Thus, we immediately 446294838Szbb * drop the packet and send an ICMPv6 error message. 447294838Szbb * 448294838Szbb * type/code is based on suggestion by Rich Draves. 449294838Szbb * not sure if it is the best pick. 450294838Szbb */ 451294838Szbb icmp6_error(mcopy, ICMP6_DST_UNREACH, 452294838Szbb ICMP6_DST_UNREACH_ADDR, 0); 453294838Szbb m_freem(m); 454294838Szbb return; 455294838Szbb } 456294838Szbb type = ND_REDIRECT; 457294838Szbb } 458294838Szbb 459294838Szbb /* 460294838Szbb * Check with the firewall... 461294838Szbb */ 462294838Szbb if (ip6_fw_enable && ip6_fw_chk_ptr) { 463294838Szbb u_short port = 0; 464294838Szbb /* If ipfw says divert, we have to just drop packet */ 465294838Szbb if ((*ip6_fw_chk_ptr)(&ip6, rt->rt_ifp, &port, &m)) { 466294838Szbb m_freem(m); 467294838Szbb goto freecopy; 468294838Szbb } 469294838Szbb if (!m) 470294838Szbb goto freecopy; 471294838Szbb } 472294838Szbb 473294838Szbb /* 474294838Szbb * Fake scoped addresses. Note that even link-local source or 475294838Szbb * destinaion can appear, if the originating node just sends the 476294838Szbb * packet to us (without address resolution for the destination). 477294838Szbb * Since both icmp6_error and icmp6_redirect_output fill the embedded 478294838Szbb * link identifiers, we can do this stuff after making a copy for 479294838Szbb * returning an error. 480294838Szbb */ 481294838Szbb if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) { 482294838Szbb /* 483294838Szbb * See corresponding comments in ip6_output. 484294838Szbb * XXX: but is it possible that ip6_forward() sends a packet 485294838Szbb * to a loopback interface? I don't think so, and thus 486294838Szbb * I bark here. (jinmei@kame.net) 487294838Szbb * XXX: it is common to route invalid packets to loopback. 488294838Szbb * also, the codepath will be visited on use of ::1 in 489294838Szbb * rthdr. (itojun) 490294838Szbb */ 491294838Szbb#if 1 492294838Szbb if (0) 493294838Szbb#else 494294838Szbb if ((rt->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) == 0) 495294838Szbb#endif 496294838Szbb { 497294838Szbb printf("ip6_forward: outgoing interface is loopback. " 498294838Szbb "src %s, dst %s, nxt %d, rcvif %s, outif %s\n", 499294838Szbb ip6_sprintf(&ip6->ip6_src), 500294838Szbb ip6_sprintf(&ip6->ip6_dst), 501294838Szbb ip6->ip6_nxt, if_name(m->m_pkthdr.rcvif), 502294838Szbb if_name(rt->rt_ifp)); 503294838Szbb } 504294838Szbb 505294838Szbb /* we can just use rcvif in forwarding. */ 506294838Szbb origifp = m->m_pkthdr.rcvif; 507294838Szbb } 508294838Szbb else 509294838Szbb origifp = rt->rt_ifp; 510294838Szbb#ifndef SCOPEDROUTING 511294838Szbb /* 512294838Szbb * clear embedded scope identifiers if necessary. 513294838Szbb * in6_clearscope will touch the addresses only when necessary. 514294838Szbb */ 515294838Szbb in6_clearscope(&ip6->ip6_src); 516294838Szbb in6_clearscope(&ip6->ip6_dst); 517294838Szbb#endif 518294838Szbb 519294838Szbb#ifdef PFIL_HOOKS 520294838Szbb /* 521294838Szbb * Run through list of hooks for output packets. 522294838Szbb */ 523294838Szbb m1 = m; 524294838Szbb pfh = pfil_hook_get(PFIL_OUT, &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); 525294838Szbb for (; pfh; pfh = pfh->pfil_link.tqe_next) 526294838Szbb if (pfh->pfil_func) { 527294838Szbb rv = pfh->pfil_func(ip6, sizeof(*ip6), 528294838Szbb rt->rt_ifp, 1, &m1); 529294838Szbb if (rv) { 530294838Szbb error = EHOSTUNREACH; 531294838Szbb goto freecopy; 532294838Szbb } 533294838Szbb m = m1; 534294838Szbb if (m == NULL) 535294838Szbb goto freecopy; 536294838Szbb ip6 = mtod(m, struct ip6_hdr *); 537294838Szbb } 538294838Szbb#endif /* PFIL_HOOKS */ 539294838Szbb 540294838Szbb error = nd6_output(rt->rt_ifp, origifp, m, dst, rt); 541294838Szbb if (error) { 542294838Szbb in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard); 543294838Szbb ip6stat.ip6s_cantforward++; 544294838Szbb } else { 545294838Szbb ip6stat.ip6s_forward++; 546294838Szbb in6_ifstat_inc(rt->rt_ifp, ifs6_out_forward); 547294838Szbb if (type) 548294838Szbb ip6stat.ip6s_redirectsent++; 549294838Szbb else { 550294838Szbb if (mcopy) 551294838Szbb goto freecopy; 552294838Szbb } 553294838Szbb } 554294838Szbb if (mcopy == NULL) 555294838Szbb return; 556294838Szbb 557294838Szbb switch (error) { 558294838Szbb case 0: 559294838Szbb#if 1 560294838Szbb if (type == ND_REDIRECT) { 561294838Szbb icmp6_redirect_output(mcopy, rt); 562294838Szbb return; 563294838Szbb } 564294838Szbb#endif 565294838Szbb goto freecopy; 566294838Szbb 567294838Szbb case EMSGSIZE: 568294838Szbb /* xxx MTU is constant in PPP? */ 569294838Szbb goto freecopy; 570294838Szbb 571294838Szbb case ENOBUFS: 572294838Szbb /* Tell source to slow down like source quench in IP? */ 573294838Szbb goto freecopy; 574294838Szbb 575294838Szbb case ENETUNREACH: /* shouldn't happen, checked above */ 576294838Szbb case EHOSTUNREACH: 577294838Szbb case ENETDOWN: 578294838Szbb case EHOSTDOWN: 579294838Szbb default: 580294838Szbb type = ICMP6_DST_UNREACH; 581294838Szbb code = ICMP6_DST_UNREACH_ADDR; 582294838Szbb break; 583294838Szbb } 584294838Szbb icmp6_error(mcopy, type, code, 0); 585294838Szbb return; 586294838Szbb 587294838Szbb freecopy: 588294838Szbb m_freem(mcopy); 589294838Szbb return; 590294838Szbb} 591294838Szbb