Deleted Added
full compact
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 ---