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