Deleted Added
full compact
ip_fw2.c (201150) ip_fw2.c (201527)
1/*-
2 * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 10 unchanged lines hidden (view full) ---

19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 10 unchanged lines hidden (view full) ---

19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
27__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw2.c 201150 2009-12-29 00:02:57Z luigi $");
27__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw2.c 201527 2010-01-04 19:01:22Z luigi $");
28
29/*
30 * The FreeBSD IP packet firewall, main file
31 */
32
33#if !defined(KLD_MODULE)
34#include "opt_ipfw.h"
35#include "opt_ipdivert.h"

--- 33 unchanged lines hidden (view full) ---

69#include <netinet/in.h>
70#include <netinet/in_var.h>
71#include <netinet/in_pcb.h>
72#include <netinet/ip.h>
73#include <netinet/ip_var.h>
74#include <netinet/ip_icmp.h>
75#include <netinet/ip_fw.h>
76#include <netinet/ipfw/ip_fw_private.h>
28
29/*
30 * The FreeBSD IP packet firewall, main file
31 */
32
33#if !defined(KLD_MODULE)
34#include "opt_ipfw.h"
35#include "opt_ipdivert.h"

--- 33 unchanged lines hidden (view full) ---

69#include <netinet/in.h>
70#include <netinet/in_var.h>
71#include <netinet/in_pcb.h>
72#include <netinet/ip.h>
73#include <netinet/ip_var.h>
74#include <netinet/ip_icmp.h>
75#include <netinet/ip_fw.h>
76#include <netinet/ipfw/ip_fw_private.h>
77#include <netinet/ip_divert.h>
78#include <netinet/ip_carp.h>
79#include <netinet/pim.h>
80#include <netinet/tcp_var.h>
81#include <netinet/udp.h>
82#include <netinet/udp_var.h>
83#include <netinet/sctp.h>
84
85#include <netinet/ip6.h>

--- 469 unchanged lines hidden (view full) ---

555 struct mbuf *m0;
556 m0 = ipfw_send_pkt(args->m, &(args->f_id),
557 ntohl(tcp->th_seq), ntohl(tcp->th_ack),
558 tcp->th_flags | TH_RST);
559 if (m0 != NULL)
560 ip6_output(m0, NULL, NULL, 0, NULL, NULL,
561 NULL);
562 }
77#include <netinet/ip_carp.h>
78#include <netinet/pim.h>
79#include <netinet/tcp_var.h>
80#include <netinet/udp.h>
81#include <netinet/udp_var.h>
82#include <netinet/sctp.h>
83
84#include <netinet/ip6.h>

--- 469 unchanged lines hidden (view full) ---

554 struct mbuf *m0;
555 m0 = ipfw_send_pkt(args->m, &(args->f_id),
556 ntohl(tcp->th_seq), ntohl(tcp->th_ack),
557 tcp->th_flags | TH_RST);
558 if (m0 != NULL)
559 ip6_output(m0, NULL, NULL, 0, NULL, NULL,
560 NULL);
561 }
563 m_freem(m);
562 FREE_PKT(m);
564 } else if (code != ICMP6_UNREACH_RST) { /* Send an ICMPv6 unreach. */
565#if 0
566 /*
567 * Unlike above, the mbufs need to line up with the ip6 hdr,
568 * as the contents are read. We need to m_adj() the
569 * needed amount.
570 * The mbuf will however be thrown away so we can adjust it.
571 * Remember we did an m_pullup on it already so we
572 * can make some assumptions about contiguousness.
573 */
574 if (args->L3offset)
575 m_adj(m, args->L3offset);
576#endif
577 icmp6_error(m, ICMP6_DST_UNREACH, code, 0);
578 } else
563 } else if (code != ICMP6_UNREACH_RST) { /* Send an ICMPv6 unreach. */
564#if 0
565 /*
566 * Unlike above, the mbufs need to line up with the ip6 hdr,
567 * as the contents are read. We need to m_adj() the
568 * needed amount.
569 * The mbuf will however be thrown away so we can adjust it.
570 * Remember we did an m_pullup on it already so we
571 * can make some assumptions about contiguousness.
572 */
573 if (args->L3offset)
574 m_adj(m, args->L3offset);
575#endif
576 icmp6_error(m, ICMP6_DST_UNREACH, code, 0);
577 } else
579 m_freem(m);
578 FREE_PKT(m);
580
581 args->m = NULL;
582}
583
584#endif /* INET6 */
585
586
587/*

--- 10 unchanged lines hidden (view full) ---

598 * Remember we did an m_pullup on it already so we
599 * can make some assumptions about contiguousness.
600 */
601 if (args->L3offset)
602 m_adj(m, args->L3offset);
603#endif
604 if (code != ICMP_REJECT_RST) { /* Send an ICMP unreach */
605 /* We need the IP header in host order for icmp_error(). */
579
580 args->m = NULL;
581}
582
583#endif /* INET6 */
584
585
586/*

--- 10 unchanged lines hidden (view full) ---

597 * Remember we did an m_pullup on it already so we
598 * can make some assumptions about contiguousness.
599 */
600 if (args->L3offset)
601 m_adj(m, args->L3offset);
602#endif
603 if (code != ICMP_REJECT_RST) { /* Send an ICMP unreach */
604 /* We need the IP header in host order for icmp_error(). */
606 if (args->eh != NULL) {
607 SET_HOST_IPLEN(ip);
608 }
605 SET_HOST_IPLEN(ip);
609 icmp_error(args->m, ICMP_UNREACH, code, 0L, 0);
610 } else if (args->f_id.proto == IPPROTO_TCP) {
611 struct tcphdr *const tcp =
612 L3HDR(struct tcphdr, mtod(args->m, struct ip *));
613 if ( (tcp->th_flags & TH_RST) == 0) {
614 struct mbuf *m;
615 m = ipfw_send_pkt(args->m, &(args->f_id),
616 ntohl(tcp->th_seq), ntohl(tcp->th_ack),
617 tcp->th_flags | TH_RST);
618 if (m != NULL)
619 ip_output(m, NULL, NULL, 0, NULL, NULL);
620 }
606 icmp_error(args->m, ICMP_UNREACH, code, 0L, 0);
607 } else if (args->f_id.proto == IPPROTO_TCP) {
608 struct tcphdr *const tcp =
609 L3HDR(struct tcphdr, mtod(args->m, struct ip *));
610 if ( (tcp->th_flags & TH_RST) == 0) {
611 struct mbuf *m;
612 m = ipfw_send_pkt(args->m, &(args->f_id),
613 ntohl(tcp->th_seq), ntohl(tcp->th_ack),
614 tcp->th_flags | TH_RST);
615 if (m != NULL)
616 ip_output(m, NULL, NULL, 0, NULL, NULL);
617 }
621 m_freem(args->m);
618 FREE_PKT(args->m);
622 } else
619 } else
623 m_freem(args->m);
620 FREE_PKT(args->m);
624 args->m = NULL;
625}
626
627/*
628 * Support for uid/gid/jail lookup. These tests are expensive
629 * (because we may need to look into the list of active sockets)
630 * so we cache the results. ugid_lookupp is 0 if we have not
631 * yet done a lookup, 1 if we succeeded, and -1 if we tried

--- 72 unchanged lines hidden (view full) ---

704 else if (insn->o.opcode == O_GID)
705 match = groupmember((gid_t)insn->d[0], *uc);
706 else if (insn->o.opcode == O_JAIL)
707 match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]);
708 return match;
709}
710
711/*
621 args->m = NULL;
622}
623
624/*
625 * Support for uid/gid/jail lookup. These tests are expensive
626 * (because we may need to look into the list of active sockets)
627 * so we cache the results. ugid_lookupp is 0 if we have not
628 * yet done a lookup, 1 if we succeeded, and -1 if we tried

--- 72 unchanged lines hidden (view full) ---

701 else if (insn->o.opcode == O_GID)
702 match = groupmember((gid_t)insn->d[0], *uc);
703 else if (insn->o.opcode == O_JAIL)
704 match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]);
705 return match;
706}
707
708/*
712 * Helper function to write the matching rule into args
709 * Helper function to set args with info on the rule after the matching
710 * one. slot is precise, whereas we guess rule_id as they are
711 * assigned sequentially.
713 */
714static inline void
715set_match(struct ip_fw_args *args, int slot,
716 struct ip_fw_chain *chain)
717{
712 */
713static inline void
714set_match(struct ip_fw_args *args, int slot,
715 struct ip_fw_chain *chain)
716{
718 args->chain_id = chain->id;
719 args->slot = slot + 1; /* we use 0 as a marker */
720 args->rule_id = chain->map[slot]->id;
721 args->rulenum = chain->map[slot]->rulenum;
717 args->rule.chain_id = chain->id;
718 args->rule.slot = slot + 1; /* we use 0 as a marker */
719 args->rule.rule_id = 1 + chain->map[slot]->id;
720 args->rule.rulenum = chain->map[slot]->rulenum;
722}
723
724/*
725 * The main check routine for the firewall.
726 *
727 * All arguments are in args so we can modify them and return them
728 * back to the caller.
729 *

--- 8 unchanged lines hidden (view full) ---

738 * The incoming interface is in the mbuf. (in)
739 * args->divert_rule (in/out)
740 * Skip up to the first rule past this rule number;
741 * upon return, non-zero port number for divert or tee.
742 *
743 * args->rule Pointer to the last matching rule (in/out)
744 * args->next_hop Socket we are forwarding to (out).
745 * args->f_id Addresses grabbed from the packet (out)
721}
722
723/*
724 * The main check routine for the firewall.
725 *
726 * All arguments are in args so we can modify them and return them
727 * back to the caller.
728 *

--- 8 unchanged lines hidden (view full) ---

737 * The incoming interface is in the mbuf. (in)
738 * args->divert_rule (in/out)
739 * Skip up to the first rule past this rule number;
740 * upon return, non-zero port number for divert or tee.
741 *
742 * args->rule Pointer to the last matching rule (in/out)
743 * args->next_hop Socket we are forwarding to (out).
744 * args->f_id Addresses grabbed from the packet (out)
746 * args->cookie a cookie depending on rule action
745 * args->rule.info a cookie depending on rule action
747 *
748 * Return value:
749 *
750 * IP_FW_PASS the packet must be accepted
751 * IP_FW_DENY the packet must be dropped
752 * IP_FW_DIVERT divert packet, port in m_tag
753 * IP_FW_TEE tee packet, port in m_tag
754 * IP_FW_DUMMYNET to dummynet, pipe in args->cookie
755 * IP_FW_NETGRAPH into netgraph, cookie args->cookie
746 *
747 * Return value:
748 *
749 * IP_FW_PASS the packet must be accepted
750 * IP_FW_DENY the packet must be dropped
751 * IP_FW_DIVERT divert packet, port in m_tag
752 * IP_FW_TEE tee packet, port in m_tag
753 * IP_FW_DUMMYNET to dummynet, pipe in args->cookie
754 * IP_FW_NETGRAPH into netgraph, cookie args->cookie
755 * args->rule contains the matching rule,
756 * args->rule.info has additional information.
756 *
757 */
758int
759ipfw_chk(struct ip_fw_args *args)
760{
761
762 /*
763 * Local variables holding state while processing a packet:

--- 28 unchanged lines hidden (view full) ---

792 * executed. This will speed up the processing of rules with
793 * these types of constraints, as well as decrease contention
794 * on pcb related locks.
795 */
796 struct ucred *ucred_cache = NULL;
797 int ucred_lookup = 0;
798
799 /*
757 *
758 */
759int
760ipfw_chk(struct ip_fw_args *args)
761{
762
763 /*
764 * Local variables holding state while processing a packet:

--- 28 unchanged lines hidden (view full) ---

793 * executed. This will speed up the processing of rules with
794 * these types of constraints, as well as decrease contention
795 * on pcb related locks.
796 */
797 struct ucred *ucred_cache = NULL;
798 int ucred_lookup = 0;
799
800 /*
800 * divinput_flags If non-zero, set to the IP_FW_DIVERT_*_FLAG
801 * associated with a packet input on a divert socket. This
802 * will allow to distinguish traffic and its direction when
803 * it originates from a divert socket.
804 */
805 u_int divinput_flags = 0;
806
807 /*
808 * oif | args->oif If NULL, ipfw_chk has been called on the
809 * inbound path (ether_input, ip_input).
810 * If non-NULL, ipfw_chk has been called on the outbound path
811 * (ether_output, ip_output).
812 */
813 struct ifnet *oif = args->oif;
814
815 int f_pos = 0; /* index of current rule in the array */

--- 41 unchanged lines hidden (view full) ---

857 /*
858 * dyn_dir = MATCH_UNKNOWN when rules unchecked,
859 * MATCH_NONE when checked and not matched (q = NULL),
860 * MATCH_FORWARD or MATCH_REVERSE otherwise (q != NULL)
861 */
862 int dyn_dir = MATCH_UNKNOWN;
863 ipfw_dyn_rule *q = NULL;
864 struct ip_fw_chain *chain = &V_layer3_chain;
801 * oif | args->oif If NULL, ipfw_chk has been called on the
802 * inbound path (ether_input, ip_input).
803 * If non-NULL, ipfw_chk has been called on the outbound path
804 * (ether_output, ip_output).
805 */
806 struct ifnet *oif = args->oif;
807
808 int f_pos = 0; /* index of current rule in the array */

--- 41 unchanged lines hidden (view full) ---

850 /*
851 * dyn_dir = MATCH_UNKNOWN when rules unchecked,
852 * MATCH_NONE when checked and not matched (q = NULL),
853 * MATCH_FORWARD or MATCH_REVERSE otherwise (q != NULL)
854 */
855 int dyn_dir = MATCH_UNKNOWN;
856 ipfw_dyn_rule *q = NULL;
857 struct ip_fw_chain *chain = &V_layer3_chain;
865 struct m_tag *mtag;
866
867 /*
868 * We store in ulp a pointer to the upper layer protocol header.
869 * In the ipv4 case this is easy to determine from the header,
870 * but for ipv6 we might have some additional headers in the middle.
871 * ulp is NULL if not found.
872 */
873 void *ulp = NULL; /* upper layer protocol pointer. */

--- 211 unchanged lines hidden (view full) ---

1085 args->f_id.addr_type = 4;
1086
1087 /*
1088 * Collect parameters into local variables for faster matching.
1089 */
1090 proto = ip->ip_p;
1091 src_ip = ip->ip_src;
1092 dst_ip = ip->ip_dst;
858
859 /*
860 * We store in ulp a pointer to the upper layer protocol header.
861 * In the ipv4 case this is easy to determine from the header,
862 * but for ipv6 we might have some additional headers in the middle.
863 * ulp is NULL if not found.
864 */
865 void *ulp = NULL; /* upper layer protocol pointer. */

--- 211 unchanged lines hidden (view full) ---

1077 args->f_id.addr_type = 4;
1078
1079 /*
1080 * Collect parameters into local variables for faster matching.
1081 */
1082 proto = ip->ip_p;
1083 src_ip = ip->ip_src;
1084 dst_ip = ip->ip_dst;
1093#ifndef HAVE_NET_IPLEN
1094 if (args->eh == NULL) { /* on l3 these are in host format */
1095 offset = ip->ip_off & IP_OFFMASK;
1096 iplen = ip->ip_len;
1097 } else
1098#endif /* !HAVE_NET_IPLEN */
1099 { /* otherwise they are in net format */
1100 offset = ntohs(ip->ip_off) & IP_OFFMASK;
1101 iplen = ntohs(ip->ip_len);
1102 }
1085 offset = ntohs(ip->ip_off) & IP_OFFMASK;
1086 iplen = ntohs(ip->ip_len);
1103 pktlen = iplen < pktlen ? iplen : pktlen;
1104
1105 if (offset == 0) {
1106 switch (proto) {
1107 case IPPROTO_TCP:
1108 PULLUP_TO(hlen, ulp, struct tcphdr);
1109 dst_port = TCP(ulp)->th_dport;
1110 src_port = TCP(ulp)->th_sport;

--- 27 unchanged lines hidden (view full) ---

1138 args->f_id.dst_port = dst_port = ntohs(dst_port);
1139 }
1140
1141 IPFW_RLOCK(chain);
1142 if (! V_ipfw_vnet_ready) { /* shutting down, leave NOW. */
1143 IPFW_RUNLOCK(chain);
1144 return (IP_FW_PASS); /* accept */
1145 }
1087 pktlen = iplen < pktlen ? iplen : pktlen;
1088
1089 if (offset == 0) {
1090 switch (proto) {
1091 case IPPROTO_TCP:
1092 PULLUP_TO(hlen, ulp, struct tcphdr);
1093 dst_port = TCP(ulp)->th_dport;
1094 src_port = TCP(ulp)->th_sport;

--- 27 unchanged lines hidden (view full) ---

1122 args->f_id.dst_port = dst_port = ntohs(dst_port);
1123 }
1124
1125 IPFW_RLOCK(chain);
1126 if (! V_ipfw_vnet_ready) { /* shutting down, leave NOW. */
1127 IPFW_RUNLOCK(chain);
1128 return (IP_FW_PASS); /* accept */
1129 }
1146 /* XXX divert should be handled same as other tags */
1147 mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
1148 if (args->slot) {
1130 if (args->rule.slot) {
1149 /*
1150 * Packet has already been tagged as a result of a previous
1151 * match on rule args->rule aka args->rule_id (PIPE, QUEUE,
1131 /*
1132 * Packet has already been tagged as a result of a previous
1133 * match on rule args->rule aka args->rule_id (PIPE, QUEUE,
1152 * REASS, NETGRAPH and similar, never a skipto).
1134 * REASS, NETGRAPH, DIVERT/TEE...)
1153 * Validate the slot and continue from the next one
1154 * if still present, otherwise do a lookup.
1155 */
1135 * Validate the slot and continue from the next one
1136 * if still present, otherwise do a lookup.
1137 */
1156 if (V_fw_one_pass) {
1157 IPFW_RUNLOCK(chain);
1158 return (IP_FW_PASS);
1159 }
1160 f_pos = (args->chain_id == chain->id) ?
1161 args->slot /* already incremented */ :
1162 ipfw_find_rule(chain, args->rulenum, args->rule_id+1);
1138 f_pos = (args->rule.chain_id == chain->id) ?
1139 args->rule.slot :
1140 ipfw_find_rule(chain, args->rule.rulenum,
1141 args->rule.rule_id);
1163 } else {
1142 } else {
1164 /*
1165 * Find the starting rule. It can be either the first
1166 * one, or the one after divert_rule if asked so.
1167 */
1168 int skipto = mtag ? divert_cookie(mtag) : 0;
1169
1170 f_pos = 0;
1143 f_pos = 0;
1171 if (args->eh == NULL && skipto != 0) {
1172 if (skipto >= IPFW_DEFAULT_RULE) {
1173 IPFW_RUNLOCK(chain);
1174 return (IP_FW_DENY); /* invalid */
1175 }
1176 f_pos = ipfw_find_rule(chain, skipto+1, 0);
1177 }
1178 }
1144 }
1179 /* reset divert rule to avoid confusion later */
1180 if (mtag) {
1181 divinput_flags = divert_info(mtag) &
1182 (IP_FW_DIVERT_OUTPUT_FLAG | IP_FW_DIVERT_LOOPBACK_FLAG);
1183 m_tag_delete(m, mtag);
1184 }
1185
1186 /*
1187 * Now scan the rules, and parse microinstructions for each rule.
1188 * We have two nested loops and an inner switch. Sometimes we
1189 * need to break out of one or both loops, or re-enter one of
1190 * the loops with updated variables. Loop variables are:
1191 *
1192 * f_pos (outer loop) points to the current rule.

--- 134 unchanged lines hidden (view full) ---

1327 match = (oif == NULL);
1328 break;
1329
1330 case O_LAYER2:
1331 match = (args->eh != NULL);
1332 break;
1333
1334 case O_DIVERTED:
1145
1146 /*
1147 * Now scan the rules, and parse microinstructions for each rule.
1148 * We have two nested loops and an inner switch. Sometimes we
1149 * need to break out of one or both loops, or re-enter one of
1150 * the loops with updated variables. Loop variables are:
1151 *
1152 * f_pos (outer loop) points to the current rule.

--- 134 unchanged lines hidden (view full) ---

1287 match = (oif == NULL);
1288 break;
1289
1290 case O_LAYER2:
1291 match = (args->eh != NULL);
1292 break;
1293
1294 case O_DIVERTED:
1335 match = (cmd->arg1 & 1 && divinput_flags &
1336 IP_FW_DIVERT_LOOPBACK_FLAG) ||
1337 (cmd->arg1 & 2 && divinput_flags &
1338 IP_FW_DIVERT_OUTPUT_FLAG);
1295 {
1296 /* For diverted packets, args->rule.info
1297 * contains the divert port (in host format)
1298 * reason and direction.
1299 */
1300 uint32_t i = args->rule.info;
1301 match = (i&IPFW_IS_MASK) == IPFW_IS_DIVERT &&
1302 cmd->arg1 & ((i & IPFW_INFO_IN) ? 1 : 2);
1303 }
1339 break;
1340
1341 case O_PROTO:
1342 /*
1343 * We do not allow an arg of 0 so the
1344 * check of "proto" only suffices.
1345 */
1346 match = (proto == cmd->arg1);

--- 403 unchanged lines hidden (view full) ---

1750 break;
1751#endif
1752
1753 case O_IP4:
1754 match = is_ipv4;
1755 break;
1756
1757 case O_TAG: {
1304 break;
1305
1306 case O_PROTO:
1307 /*
1308 * We do not allow an arg of 0 so the
1309 * check of "proto" only suffices.
1310 */
1311 match = (proto == cmd->arg1);

--- 403 unchanged lines hidden (view full) ---

1715 break;
1716#endif
1717
1718 case O_IP4:
1719 match = is_ipv4;
1720 break;
1721
1722 case O_TAG: {
1723 struct m_tag *mtag;
1758 uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ?
1759 tablearg : cmd->arg1;
1760
1761 /* Packet is already tagged with this tag? */
1762 mtag = m_tag_locate(m, MTAG_IPFW, tag, NULL);
1763
1764 /* We have `untag' action when F_NOT flag is
1765 * present. And we must remove this mtag from
1766 * mbuf and reset `match' to zero (`match' will
1767 * be inversed later).
1768 * Otherwise we should allocate new mtag and
1769 * push it into mbuf.
1770 */
1771 if (cmd->len & F_NOT) { /* `untag' action */
1772 if (mtag != NULL)
1773 m_tag_delete(m, mtag);
1724 uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ?
1725 tablearg : cmd->arg1;
1726
1727 /* Packet is already tagged with this tag? */
1728 mtag = m_tag_locate(m, MTAG_IPFW, tag, NULL);
1729
1730 /* We have `untag' action when F_NOT flag is
1731 * present. And we must remove this mtag from
1732 * mbuf and reset `match' to zero (`match' will
1733 * be inversed later).
1734 * Otherwise we should allocate new mtag and
1735 * push it into mbuf.
1736 */
1737 if (cmd->len & F_NOT) { /* `untag' action */
1738 if (mtag != NULL)
1739 m_tag_delete(m, mtag);
1740 match = 0;
1774 } else if (mtag == NULL) {
1775 if ((mtag = m_tag_alloc(MTAG_IPFW,
1776 tag, 0, M_NOWAIT)) != NULL)
1777 m_tag_prepend(m, mtag);
1741 } else if (mtag == NULL) {
1742 if ((mtag = m_tag_alloc(MTAG_IPFW,
1743 tag, 0, M_NOWAIT)) != NULL)
1744 m_tag_prepend(m, mtag);
1745 match = 1;
1778 }
1746 }
1779 match = (cmd->len & F_NOT) ? 0: 1;
1780 break;
1781 }
1782
1783 case O_FIB: /* try match the specified fib */
1784 if (args->f_id.fib == cmd->arg1)
1785 match = 1;
1786 break;
1787
1788 case O_TAGGED: {
1747 break;
1748 }
1749
1750 case O_FIB: /* try match the specified fib */
1751 if (args->f_id.fib == cmd->arg1)
1752 match = 1;
1753 break;
1754
1755 case O_TAGGED: {
1756 struct m_tag *mtag;
1789 uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ?
1790 tablearg : cmd->arg1;
1791
1792 if (cmdlen == 1) {
1793 match = m_tag_locate(m, MTAG_IPFW,
1794 tag, NULL) != NULL;
1795 break;
1796 }

--- 124 unchanged lines hidden (view full) ---

1921 retval = 0; /* accept */
1922 l = 0; /* exit inner loop */
1923 done = 1; /* exit outer loop */
1924 break;
1925
1926 case O_PIPE:
1927 case O_QUEUE:
1928 set_match(args, f_pos, chain);
1757 uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ?
1758 tablearg : cmd->arg1;
1759
1760 if (cmdlen == 1) {
1761 match = m_tag_locate(m, MTAG_IPFW,
1762 tag, NULL) != NULL;
1763 break;
1764 }

--- 124 unchanged lines hidden (view full) ---

1889 retval = 0; /* accept */
1890 l = 0; /* exit inner loop */
1891 done = 1; /* exit outer loop */
1892 break;
1893
1894 case O_PIPE:
1895 case O_QUEUE:
1896 set_match(args, f_pos, chain);
1929 args->cookie = (cmd->arg1 == IP_FW_TABLEARG) ?
1897 args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ?
1930 tablearg : cmd->arg1;
1898 tablearg : cmd->arg1;
1931 if (cmd->opcode == O_QUEUE)
1932 args->cookie |= 0x80000000;
1899 if (cmd->opcode == O_PIPE)
1900 args->rule.info |= IPFW_IS_PIPE;
1901 if (V_fw_one_pass)
1902 args->rule.info |= IPFW_ONEPASS;
1933 retval = IP_FW_DUMMYNET;
1934 l = 0; /* exit inner loop */
1935 done = 1; /* exit outer loop */
1936 break;
1937
1938 case O_DIVERT:
1939 case O_TEE:
1940 if (args->eh) /* not on layer 2 */
1941 break;
1942 /* otherwise this is terminal */
1943 l = 0; /* exit inner loop */
1944 done = 1; /* exit outer loop */
1903 retval = IP_FW_DUMMYNET;
1904 l = 0; /* exit inner loop */
1905 done = 1; /* exit outer loop */
1906 break;
1907
1908 case O_DIVERT:
1909 case O_TEE:
1910 if (args->eh) /* not on layer 2 */
1911 break;
1912 /* otherwise this is terminal */
1913 l = 0; /* exit inner loop */
1914 done = 1; /* exit outer loop */
1945 mtag = m_tag_get(PACKET_TAG_DIVERT,
1946 sizeof(struct divert_tag),
1947 M_NOWAIT);
1948 if (mtag == NULL) {
1949 retval = IP_FW_DENY;
1950 } else {
1951 struct divert_tag *dt;
1952 dt = (struct divert_tag *)(mtag+1);
1953 dt->cookie = f->rulenum;
1954 if (cmd->arg1 == IP_FW_TABLEARG)
1955 dt->info = tablearg;
1956 else
1957 dt->info = cmd->arg1;
1958 m_tag_prepend(m, mtag);
1959 retval = (cmd->opcode == O_DIVERT) ?
1915 retval = (cmd->opcode == O_DIVERT) ?
1960 IP_FW_DIVERT : IP_FW_TEE;
1916 IP_FW_DIVERT : IP_FW_TEE;
1961 }
1917 set_match(args, f_pos, chain);
1918 args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ?
1919 tablearg : cmd->arg1;
1962 break;
1963
1964 case O_COUNT:
1965 f->pcnt++; /* update stats */
1966 f->bcnt += pktlen;
1967 f->timestamp = time_uptime;
1968 l = 0; /* exit inner loop */
1969 break;

--- 99 unchanged lines hidden (view full) ---

2069 retval = IP_FW_PASS;
2070 l = 0; /* exit inner loop */
2071 done = 1; /* exit outer loop */
2072 break;
2073
2074 case O_NETGRAPH:
2075 case O_NGTEE:
2076 set_match(args, f_pos, chain);
1920 break;
1921
1922 case O_COUNT:
1923 f->pcnt++; /* update stats */
1924 f->bcnt += pktlen;
1925 f->timestamp = time_uptime;
1926 l = 0; /* exit inner loop */
1927 break;

--- 99 unchanged lines hidden (view full) ---

2027 retval = IP_FW_PASS;
2028 l = 0; /* exit inner loop */
2029 done = 1; /* exit outer loop */
2030 break;
2031
2032 case O_NETGRAPH:
2033 case O_NGTEE:
2034 set_match(args, f_pos, chain);
2077 args->cookie = (cmd->arg1 == IP_FW_TABLEARG) ?
2035 args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ?
2078 tablearg : cmd->arg1;
2079 retval = (cmd->opcode == O_NETGRAPH) ?
2080 IP_FW_NETGRAPH : IP_FW_NGTEE;
2081 l = 0; /* exit inner loop */
2082 done = 1; /* exit outer loop */
2083 break;
2084
2085 case O_SETFIB:

--- 35 unchanged lines hidden (view full) ---

2121 break;
2122
2123 case O_REASS: {
2124 int ip_off;
2125
2126 f->pcnt++;
2127 f->bcnt += pktlen;
2128 l = 0; /* in any case exit inner loop */
2036 tablearg : cmd->arg1;
2037 retval = (cmd->opcode == O_NETGRAPH) ?
2038 IP_FW_NETGRAPH : IP_FW_NGTEE;
2039 l = 0; /* exit inner loop */
2040 done = 1; /* exit outer loop */
2041 break;
2042
2043 case O_SETFIB:

--- 35 unchanged lines hidden (view full) ---

2079 break;
2080
2081 case O_REASS: {
2082 int ip_off;
2083
2084 f->pcnt++;
2085 f->bcnt += pktlen;
2086 l = 0; /* in any case exit inner loop */
2129
2130#ifndef HAVE_NET_IPLEN
2131 if (args->eh == NULL)
2132 ip_off = ip->ip_off;
2133 else
2134#endif /* !HAVE_NET_IPLEN */
2135 ip_off = ntohs(ip->ip_off);
2136
2137 /* if not fragmented, go to next rule */
2138 if ((ip_off & (IP_MF | IP_OFFMASK)) == 0)
2139 break;
2140 /*
2141 * ip_reass() expects len & off in host
2087 ip_off = ntohs(ip->ip_off);
2088
2089 /* if not fragmented, go to next rule */
2090 if ((ip_off & (IP_MF | IP_OFFMASK)) == 0)
2091 break;
2092 /*
2093 * ip_reass() expects len & off in host
2142 * byte order: fix them in case we come
2143 * from layer2.
2094 * byte order.
2144 */
2095 */
2145 if (args->eh != NULL) {
2146 SET_HOST_IPLEN(ip);
2147 }
2096 SET_HOST_IPLEN(ip);
2148
2149 args->m = m = ip_reass(m);
2150
2151 /*
2097
2098 args->m = m = ip_reass(m);
2099
2100 /*
2152 * IP header checksum fixup after
2153 * reassembly and leave header
2154 * in network byte order.
2101 * do IP header checksum fixup.
2155 */
2156 if (m == NULL) { /* fragment got swallowed */
2157 retval = IP_FW_DENY;
2158 } else { /* good, packet complete */
2159 int hlen;
2160
2161 ip = mtod(m, struct ip *);
2162 hlen = ip->ip_hl << 2;
2102 */
2103 if (m == NULL) { /* fragment got swallowed */
2104 retval = IP_FW_DENY;
2105 } else { /* good, packet complete */
2106 int hlen;
2107
2108 ip = mtod(m, struct ip *);
2109 hlen = ip->ip_hl << 2;
2163 /* revert len. & off to net format if needed */
2164 if (args->eh != NULL) {
2165 SET_NET_IPLEN(ip);
2166 }
2110 SET_NET_IPLEN(ip);
2167 ip->ip_sum = 0;
2168 if (hlen == sizeof(struct ip))
2169 ip->ip_sum = in_cksum_hdr(ip);
2170 else
2171 ip->ip_sum = in_cksum(m, hlen);
2172 retval = IP_FW_REASS;
2173 set_match(args, f_pos, chain);
2174 }

--- 321 unchanged lines hidden ---
2111 ip->ip_sum = 0;
2112 if (hlen == sizeof(struct ip))
2113 ip->ip_sum = in_cksum_hdr(ip);
2114 else
2115 ip->ip_sum = in_cksum(m, hlen);
2116 retval = IP_FW_REASS;
2117 set_match(args, f_pos, chain);
2118 }

--- 321 unchanged lines hidden ---