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 --- |