ip_fastfwd.c (133497) | ip_fastfwd.c (133920) |
---|---|
1/* 2 * Copyright (c) 2003 Andre Oppermann, Internet Business Solutions AG 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * | 1/* 2 * Copyright (c) 2003 Andre Oppermann, Internet Business Solutions AG 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * |
29 * $FreeBSD: head/sys/netinet/ip_fastfwd.c 133497 2004-08-11 12:32:10Z andre $ | 29 * $FreeBSD: head/sys/netinet/ip_fastfwd.c 133920 2004-08-17 22:05:54Z andre $ |
30 */ 31 32/* 33 * ip_fastforward gets its speed from processing the forwarded packet to 34 * completion (if_output on the other side) without any queues or netisr's. 35 * The receiving interface DMAs the packet into memory, the upper half of 36 * driver calls ip_fastforward, we do our routing table lookup and directly 37 * send it off to the outgoing interface which DMAs the packet to the --- 33 unchanged lines hidden (view full) --- 71 */ 72 73/* 74 * Many thanks to Matt Thomas of NetBSD for basic structure of ip_flow.c which 75 * is being followed here. 76 */ 77 78#include "opt_ipfw.h" | 30 */ 31 32/* 33 * ip_fastforward gets its speed from processing the forwarded packet to 34 * completion (if_output on the other side) without any queues or netisr's. 35 * The receiving interface DMAs the packet into memory, the upper half of 36 * driver calls ip_fastforward, we do our routing table lookup and directly 37 * send it off to the outgoing interface which DMAs the packet to the --- 33 unchanged lines hidden (view full) --- 71 */ 72 73/* 74 * Many thanks to Matt Thomas of NetBSD for basic structure of ip_flow.c which 75 * is being followed here. 76 */ 77 78#include "opt_ipfw.h" |
79#include "opt_ipdn.h" 80#include "opt_ipdivert.h" 81#include "opt_ipfilter.h" | |
82#include "opt_ipstealth.h" 83#include "opt_pfil_hooks.h" 84 85#include <sys/param.h> 86#include <sys/systm.h> 87#include <sys/kernel.h> 88#include <sys/malloc.h> 89#include <sys/mbuf.h> --- 12 unchanged lines hidden (view full) --- 102#include <netinet/in_systm.h> 103#include <netinet/in_var.h> 104#include <netinet/ip.h> 105#include <netinet/ip_var.h> 106#include <netinet/ip_icmp.h> 107 108#include <machine/in_cksum.h> 109 | 79#include "opt_ipstealth.h" 80#include "opt_pfil_hooks.h" 81 82#include <sys/param.h> 83#include <sys/systm.h> 84#include <sys/kernel.h> 85#include <sys/malloc.h> 86#include <sys/mbuf.h> --- 12 unchanged lines hidden (view full) --- 99#include <netinet/in_systm.h> 100#include <netinet/in_var.h> 101#include <netinet/ip.h> 102#include <netinet/ip_var.h> 103#include <netinet/ip_icmp.h> 104 105#include <machine/in_cksum.h> 106 |
110#include <netinet/ip_fw.h> 111#include <netinet/ip_divert.h> 112#include <netinet/ip_dummynet.h> 113 | |
114static int ipfastforward_active = 0; 115SYSCTL_INT(_net_inet_ip, OID_AUTO, fastforwarding, CTLFLAG_RW, 116 &ipfastforward_active, 0, "Enable fast IP forwarding"); 117 118static struct sockaddr_in * 119ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m) 120{ 121 struct sockaddr_in *dst; --- 36 unchanged lines hidden (view full) --- 158 * otherwise 0 is returned and the packet should be delivered 159 * to ip_input for full processing. 160 */ 161int 162ip_fastforward(struct mbuf *m) 163{ 164 struct ip *ip; 165 struct mbuf *m0 = NULL; | 107static int ipfastforward_active = 0; 108SYSCTL_INT(_net_inet_ip, OID_AUTO, fastforwarding, CTLFLAG_RW, 109 &ipfastforward_active, 0, "Enable fast IP forwarding"); 110 111static struct sockaddr_in * 112ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m) 113{ 114 struct sockaddr_in *dst; --- 36 unchanged lines hidden (view full) --- 151 * otherwise 0 is returned and the packet should be delivered 152 * to ip_input for full processing. 153 */ 154int 155ip_fastforward(struct mbuf *m) 156{ 157 struct ip *ip; 158 struct mbuf *m0 = NULL; |
166#ifdef IPDIVERT 167 struct ip *tip; 168 struct mbuf *clone = NULL; 169#endif | |
170 struct route ro; 171 struct sockaddr_in *dst = NULL; 172 struct in_ifaddr *ia = NULL; 173 struct ifaddr *ifa = NULL; 174 struct ifnet *ifp; | 159 struct route ro; 160 struct sockaddr_in *dst = NULL; 161 struct in_ifaddr *ia = NULL; 162 struct ifaddr *ifa = NULL; 163 struct ifnet *ifp; |
175 struct ip_fw_args args; | |
176 struct in_addr odest, dest; 177 u_short sum, ip_len; 178 int error = 0; | 164 struct in_addr odest, dest; 165 u_short sum, ip_len; 166 int error = 0; |
179 int hlen, ipfw, mtu; | 167 int hlen, mtu; 168#ifdef IPFIREWALL_FORWARD 169 struct m_tag *fwd_tag; 170#endif |
180 181 /* 182 * Are we active and forwarding packets? 183 */ 184 if (!ipfastforward_active || !ipforwarding) 185 return 0; 186 187 M_ASSERTVALID(m); --- 182 unchanged lines hidden (view full) --- 370 m == NULL) 371 return 1; 372 373 M_ASSERTVALID(m); 374 M_ASSERTPKTHDR(m); 375 376 ip = mtod(m, struct ip *); /* m may have changed by pfil hook */ 377 dest.s_addr = ip->ip_dst.s_addr; | 171 172 /* 173 * Are we active and forwarding packets? 174 */ 175 if (!ipfastforward_active || !ipforwarding) 176 return 0; 177 178 M_ASSERTVALID(m); --- 182 unchanged lines hidden (view full) --- 361 m == NULL) 362 return 1; 363 364 M_ASSERTVALID(m); 365 M_ASSERTPKTHDR(m); 366 367 ip = mtod(m, struct ip *); /* m may have changed by pfil hook */ 368 dest.s_addr = ip->ip_dst.s_addr; |
378#endif | |
379 380 /* | 369 370 /* |
381 * Run through ipfw for input packets 382 */ 383 if (fw_enable && IPFW_LOADED) { 384 bzero(&args, sizeof(args)); 385 args.m = m; 386 387 ipfw = ip_fw_chk_ptr(&args); 388 m = args.m; 389 390 M_ASSERTVALID(m); 391 M_ASSERTPKTHDR(m); 392 393 /* 394 * Packet denied, drop it 395 */ 396 if ((ipfw & IP_FW_PORT_DENY_FLAG) || m == NULL) 397 goto drop; 398 /* 399 * Send packet to the appropriate pipe 400 */ 401 if (DUMMYNET_LOADED && (ipfw & IP_FW_PORT_DYNT_FLAG) != 0) { 402 ip_dn_io_ptr(m, ipfw & 0xffff, DN_TO_IP_IN, &args); 403 return 1; 404 } 405#ifdef IPDIVERT 406 /* 407 * Divert packet 408 */ 409 if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) { 410 /* 411 * See if this is a fragment 412 */ 413 if (ip->ip_off & (IP_MF | IP_OFFMASK)) 414 goto droptoours; 415 /* 416 * Tee packet 417 */ 418 if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0) 419 clone = divert_clone(m); 420 else 421 clone = m; 422 if (clone == NULL) 423 goto passin; 424 425 /* 426 * Delayed checksums are not compatible 427 */ 428 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 429 in_delayed_cksum(m); 430 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 431 } 432 /* 433 * Restore packet header fields to original values 434 */ 435 tip = mtod(m, struct ip *); 436 tip->ip_len = htons(tip->ip_len); 437 tip->ip_off = htons(tip->ip_off); 438 /* 439 * Deliver packet to divert input routine 440 */ 441 divert_packet(m, 0); 442 /* 443 * If this was not tee, we are done 444 */ 445 m = clone; 446 if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0) 447 return 1; 448 /* Continue if it was tee */ 449 goto passin; 450 } 451#endif 452 if (ipfw == 0 && args.next_hop != NULL) { 453 dest.s_addr = args.next_hop->sin_addr.s_addr; 454 goto passin; 455 } 456 /* 457 * Let through or not? 458 */ 459 if (ipfw != 0) 460 goto drop; 461 } 462passin: 463 ip = mtod(m, struct ip *); /* if m changed during fw processing */ 464 465 /* | |
466 * Destination address changed? 467 */ 468 if (odest.s_addr != dest.s_addr) { 469 /* 470 * Is it now for a local address on this host? 471 */ 472 if (in_localip(dest)) 473 goto forwardlocal; 474 /* 475 * Go on with new destination address 476 */ 477 } | 371 * Destination address changed? 372 */ 373 if (odest.s_addr != dest.s_addr) { 374 /* 375 * Is it now for a local address on this host? 376 */ 377 if (in_localip(dest)) 378 goto forwardlocal; 379 /* 380 * Go on with new destination address 381 */ 382 } |
383#ifdef IPFIREWALL_FORWARD 384 if (m->m_flags & M_FASTFWD_OURS) { 385 /* 386 * ipfw changed it for a local address on this host. 387 */ 388 goto forwardlocal; 389 } 390#endif /* IPFIREWALL_FORWARD */ 391#endif /* PFIL_HOOKS */ |
|
478 479 /* 480 * Step 4: decrement TTL and look up route 481 */ 482 483 /* 484 * Check TTL 485 */ --- 37 unchanged lines hidden (view full) --- 523 goto consumed; 524 } 525 526 M_ASSERTVALID(m); 527 M_ASSERTPKTHDR(m); 528 529 ip = mtod(m, struct ip *); 530 dest.s_addr = ip->ip_dst.s_addr; | 392 393 /* 394 * Step 4: decrement TTL and look up route 395 */ 396 397 /* 398 * Check TTL 399 */ --- 37 unchanged lines hidden (view full) --- 437 goto consumed; 438 } 439 440 M_ASSERTVALID(m); 441 M_ASSERTPKTHDR(m); 442 443 ip = mtod(m, struct ip *); 444 dest.s_addr = ip->ip_dst.s_addr; |
531#endif 532 if (fw_enable && IPFW_LOADED && !args.next_hop) { 533 bzero(&args, sizeof(args)); 534 args.m = m; 535 args.oif = ifp; | |
536 | 445 |
537 ipfw = ip_fw_chk_ptr(&args); 538 m = args.m; 539 540 M_ASSERTVALID(m); 541 M_ASSERTPKTHDR(m); 542 543 if ((ipfw & IP_FW_PORT_DENY_FLAG) || m == NULL) 544 goto drop; 545 546 if (DUMMYNET_LOADED && (ipfw & IP_FW_PORT_DYNT_FLAG) != 0) { 547 /* 548 * XXX note: if the ifp or rt entry are deleted 549 * while a pkt is in dummynet, we are in trouble! 550 */ 551 args.ro = &ro; /* dummynet does not save it */ 552 args.dst = dst; 553 554 ip_dn_io_ptr(m, ipfw & 0xffff, DN_TO_IP_OUT, &args); 555 goto consumed; 556 } 557#ifdef IPDIVERT 558 if (ipfw != 0 && (ipfw & IP_FW_PORT_DYNT_FLAG) == 0) { 559 /* 560 * See if this is a fragment 561 */ 562 if (ip->ip_off & (IP_MF | IP_OFFMASK)) 563 goto droptoours; 564 /* 565 * Tee packet 566 */ 567 if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0) 568 clone = divert_clone(m); 569 else 570 clone = m; 571 if (clone == NULL) 572 goto passout; 573 574 /* 575 * Delayed checksums are not compatible with divert 576 */ 577 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 578 in_delayed_cksum(m); 579 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 580 } 581 /* 582 * Restore packet header fields to original values 583 */ 584 tip = mtod(m, struct ip *); 585 tip->ip_len = htons(tip->ip_len); 586 tip->ip_off = htons(tip->ip_off); 587 /* 588 * Deliver packet to divert input routine 589 */ 590 divert_packet(m, 0); 591 /* 592 * If this was not tee, we are done 593 */ 594 m = clone; 595 if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0) { 596 goto consumed; 597 } 598 /* Continue if it was tee */ 599 goto passout; 600 } 601#endif 602 if (ipfw == 0 && args.next_hop != NULL) { 603 dest.s_addr = args.next_hop->sin_addr.s_addr; 604 goto passout; 605 } 606 /* 607 * Let through or not? 608 */ 609 if (ipfw != 0) 610 goto drop; 611 } 612passout: 613 ip = mtod(m, struct ip *); 614 | |
615 /* 616 * Destination address changed? 617 */ | 446 /* 447 * Destination address changed? 448 */ |
449#ifndef IPFIREWALL_FORWARD |
|
618 if (odest.s_addr != dest.s_addr) { | 450 if (odest.s_addr != dest.s_addr) { |
451#else 452 fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); 453 if (odest.s_addr != dest.s_addr || fwd_tag != NULL) { 454#endif /* IPFIREWALL_FORWARD */ |
|
619 /* 620 * Is it now for a local address on this host? 621 */ | 455 /* 456 * Is it now for a local address on this host? 457 */ |
458#ifndef IPFIREWALL_FORWARD |
|
622 if (in_localip(dest)) { | 459 if (in_localip(dest)) { |
460#else 461 if (in_localip(dest) || m->m_flags & M_FASTFWD_OURS) { 462#endif /* IPFIREWALL_FORWARD */ |
|
623forwardlocal: | 463forwardlocal: |
624 if (args.next_hop) { 625 struct m_tag *mtag = m_tag_get( 626 PACKET_TAG_IPFORWARD, 627 sizeof(struct sockaddr_in *), 628 M_NOWAIT); 629 if (mtag == NULL) { 630 goto drop; 631 } 632 *(struct sockaddr_in **)(mtag+1) = 633 args.next_hop; 634 m_tag_prepend(m, mtag); 635 } 636#ifdef IPDIVERT 637droptoours: /* Used for DIVERT */ 638#endif | |
639 /* for ip_input */ 640 m->m_flags |= M_FASTFWD_OURS; | 464 /* for ip_input */ 465 m->m_flags |= M_FASTFWD_OURS; |
641 642 /* ip still points to the real packet */ | |
643 ip->ip_len = htons(ip->ip_len); 644 ip->ip_off = htons(ip->ip_off); 645 646 /* | 466 ip->ip_len = htons(ip->ip_len); 467 ip->ip_off = htons(ip->ip_off); 468 469 /* |
647 * Return packet for processing by ip_input | 470 * Return packet for processing by ip_input() |
648 */ 649 if (ro.ro_rt) 650 RTFREE(ro.ro_rt); 651 return 0; 652 } 653 /* 654 * Redo route lookup with new destination address 655 */ | 471 */ 472 if (ro.ro_rt) 473 RTFREE(ro.ro_rt); 474 return 0; 475 } 476 /* 477 * Redo route lookup with new destination address 478 */ |
479#ifdef IPFIREWALL_FORWARD 480 if (fwd_tag) { 481 if (!in_localip(ip->ip_src) && !in_localaddr(ip->ip_dst)) 482 dest.s_addr = ((struct sockaddr_in *)(fwd_tag+1))->sin_addr.s_addr; 483 //bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in)); 484 m_tag_delete(m, fwd_tag); 485 } 486#endif /* IPFIREWALL_FORWARD */ |
|
656 RTFREE(ro.ro_rt); 657 if ((dst = ip_findroute(&ro, dest, m)) == NULL) 658 return 1; /* icmp unreach already sent */ 659 ifp = ro.ro_rt->rt_ifp; 660 } | 487 RTFREE(ro.ro_rt); 488 if ((dst = ip_findroute(&ro, dest, m)) == NULL) 489 return 1; /* icmp unreach already sent */ 490 ifp = ro.ro_rt->rt_ifp; 491 } |
492#endif /* PFIL_HOOKS */ |
|
661 662 /* 663 * Step 6: send off the packet 664 */ 665 666 /* 667 * Check if route is dampned (when ARP is unable to resolve) 668 */ --- 111 unchanged lines hidden --- | 493 494 /* 495 * Step 6: send off the packet 496 */ 497 498 /* 499 * Check if route is dampned (when ARP is unable to resolve) 500 */ --- 111 unchanged lines hidden --- |