Deleted Added
full compact
ip_fw2.c (231852) ip_fw2.c (232865)
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 231852 2012-02-17 02:39:58Z bz $");
27__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw2.c 232865 2012-03-12 14:07:57Z melifaro $");
28
29/*
30 * The FreeBSD IP packet firewall, main file
31 */
32
33#include "opt_ipfw.h"
34#include "opt_ipdivert.h"
35#include "opt_inet.h"

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

111static int default_to_accept = 1;
112#else
113static int default_to_accept;
114#endif
115
116VNET_DEFINE(int, autoinc_step);
117VNET_DEFINE(int, fw_one_pass) = 1;
118
28
29/*
30 * The FreeBSD IP packet firewall, main file
31 */
32
33#include "opt_ipfw.h"
34#include "opt_ipdivert.h"
35#include "opt_inet.h"

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

111static int default_to_accept = 1;
112#else
113static int default_to_accept;
114#endif
115
116VNET_DEFINE(int, autoinc_step);
117VNET_DEFINE(int, fw_one_pass) = 1;
118
119/* Use 128 tables by default */
120VNET_DEFINE(int, fw_tables_max) = IPFW_TABLES_MAX;
121
119/*
120 * Each rule belongs to one of 32 different sets (0..31).
121 * The variable set_disable contains one bit per set.
122 * If the bit is set, all rules in the corresponding set
123 * are disabled. Set RESVD_SET(31) is reserved for the default rule
124 * and rules that are not deleted by the flush command,
125 * and CANNOT be disabled.
126 * Rules in set RESVD_SET can only be deleted individually.

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

140struct cfg_nat *(*lookup_nat_ptr)(struct nat_list *, int);
141ipfw_nat_cfg_t *ipfw_nat_cfg_ptr;
142ipfw_nat_cfg_t *ipfw_nat_del_ptr;
143ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr;
144ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
145
146#ifdef SYSCTL_NODE
147uint32_t dummy_def = IPFW_DEFAULT_RULE;
122/*
123 * Each rule belongs to one of 32 different sets (0..31).
124 * The variable set_disable contains one bit per set.
125 * If the bit is set, all rules in the corresponding set
126 * are disabled. Set RESVD_SET(31) is reserved for the default rule
127 * and rules that are not deleted by the flush command,
128 * and CANNOT be disabled.
129 * Rules in set RESVD_SET can only be deleted individually.

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

143struct cfg_nat *(*lookup_nat_ptr)(struct nat_list *, int);
144ipfw_nat_cfg_t *ipfw_nat_cfg_ptr;
145ipfw_nat_cfg_t *ipfw_nat_del_ptr;
146ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr;
147ipfw_nat_cfg_t *ipfw_nat_get_log_ptr;
148
149#ifdef SYSCTL_NODE
150uint32_t dummy_def = IPFW_DEFAULT_RULE;
148uint32_t dummy_tables_max = IPFW_TABLES_MAX;
149
150SYSBEGIN(f3)
151
152SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
153SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, one_pass,
154 CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_one_pass), 0,
155 "Only do a single pass through ipfw when using dummynet(4)");
156SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step,

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

161 "Log matches to ipfw rules");
162SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit,
163 CTLFLAG_RW, &VNET_NAME(verbose_limit), 0,
164 "Set upper limit of matches of ipfw rules logged");
165SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
166 &dummy_def, 0,
167 "The default/max possible rule number.");
168SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
151
152SYSBEGIN(f3)
153
154SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
155SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, one_pass,
156 CTLFLAG_RW | CTLFLAG_SECURE3, &VNET_NAME(fw_one_pass), 0,
157 "Only do a single pass through ipfw when using dummynet(4)");
158SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, autoinc_step,

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

163 "Log matches to ipfw rules");
164SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit,
165 CTLFLAG_RW, &VNET_NAME(verbose_limit), 0,
166 "Set upper limit of matches of ipfw rules logged");
167SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
168 &dummy_def, 0,
169 "The default/max possible rule number.");
170SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
169 &dummy_tables_max, 0,
171 &V_fw_tables_max, 0,
170 "The maximum number of tables.");
171SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
172 &default_to_accept, 0,
173 "Make the default rule accept all packets.");
174TUNABLE_INT("net.inet.ip.fw.default_to_accept", &default_to_accept);
172 "The maximum number of tables.");
173SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, default_to_accept, CTLFLAG_RDTUN,
174 &default_to_accept, 0,
175 "Make the default rule accept all packets.");
176TUNABLE_INT("net.inet.ip.fw.default_to_accept", &default_to_accept);
177TUNABLE_INT("net.inet.ip.fw.tables_max", &V_fw_tables_max);
175SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, static_count,
176 CTLFLAG_RD, &VNET_NAME(layer3_chain.n_rules), 0,
177 "Number of static rules");
178
179#ifdef INET6
180SYSCTL_DECL(_net_inet6_ip6);
181SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
182SYSCTL_VNET_INT(_net_inet6_ip6_fw, OID_AUTO, deny_unknown_exthdrs,

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

336 break;
337
338 }
339 }
340 return (flags_match(cmd, bits));
341}
342
343static int
178SYSCTL_VNET_INT(_net_inet_ip_fw, OID_AUTO, static_count,
179 CTLFLAG_RD, &VNET_NAME(layer3_chain.n_rules), 0,
180 "Number of static rules");
181
182#ifdef INET6
183SYSCTL_DECL(_net_inet6_ip6);
184SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
185SYSCTL_VNET_INT(_net_inet6_ip6_fw, OID_AUTO, deny_unknown_exthdrs,

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

339 break;
340
341 }
342 }
343 return (flags_match(cmd, bits));
344}
345
346static int
344iface_match(struct ifnet *ifp, ipfw_insn_if *cmd)
347iface_match(struct ifnet *ifp, ipfw_insn_if *cmd, struct ip_fw_chain *chain, uint32_t *tablearg)
345{
346 if (ifp == NULL) /* no iface with this packet, match fails */
347 return 0;
348 /* Check by name or by IP address */
349 if (cmd->name[0] != '\0') { /* match by name */
348{
349 if (ifp == NULL) /* no iface with this packet, match fails */
350 return 0;
351 /* Check by name or by IP address */
352 if (cmd->name[0] != '\0') { /* match by name */
353 if (cmd->name[0] == '\1') /* use tablearg to match */
354 return ipfw_lookup_table_extended(chain, cmd->p.glob,
355 ifp->if_xname, tablearg, IPFW_TABLE_INTERFACE);
350 /* Check name */
351 if (cmd->p.glob) {
352 if (fnmatch(cmd->name, ifp->if_xname, 0) == 0)
353 return(1);
354 } else {
355 if (strncmp(ifp->if_xname, cmd->name, IFNAMSIZ) == 0)
356 return(1);
357 }

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

1307 &ucred_cache);
1308#else
1309 (void *)&ucred_cache);
1310#endif
1311 break;
1312
1313 case O_RECV:
1314 match = iface_match(m->m_pkthdr.rcvif,
356 /* Check name */
357 if (cmd->p.glob) {
358 if (fnmatch(cmd->name, ifp->if_xname, 0) == 0)
359 return(1);
360 } else {
361 if (strncmp(ifp->if_xname, cmd->name, IFNAMSIZ) == 0)
362 return(1);
363 }

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

1313 &ucred_cache);
1314#else
1315 (void *)&ucred_cache);
1316#endif
1317 break;
1318
1319 case O_RECV:
1320 match = iface_match(m->m_pkthdr.rcvif,
1315 (ipfw_insn_if *)cmd);
1321 (ipfw_insn_if *)cmd, chain, &tablearg);
1316 break;
1317
1318 case O_XMIT:
1322 break;
1323
1324 case O_XMIT:
1319 match = iface_match(oif, (ipfw_insn_if *)cmd);
1325 match = iface_match(oif, (ipfw_insn_if *)cmd,
1326 chain, &tablearg);
1320 break;
1321
1322 case O_VIA:
1323 match = iface_match(oif ? oif :
1327 break;
1328
1329 case O_VIA:
1330 match = iface_match(oif ? oif :
1324 m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd);
1331 m->m_pkthdr.rcvif, (ipfw_insn_if *)cmd,
1332 chain, &tablearg);
1325 break;
1326
1327 case O_MACADDR2:
1328 if (args->eh != NULL) { /* have MAC header */
1329 u_int32_t *want = (u_int32_t *)
1330 ((ipfw_insn_mac *)cmd)->addr;
1331 u_int32_t *mask = (u_int32_t *)
1332 ((ipfw_insn_mac *)cmd)->mask;

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

1443 cmd->arg1, key, &v);
1444 if (!match)
1445 break;
1446 if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
1447 match =
1448 ((ipfw_insn_u32 *)cmd)->d[0] == v;
1449 else
1450 tablearg = v;
1333 break;
1334
1335 case O_MACADDR2:
1336 if (args->eh != NULL) { /* have MAC header */
1337 u_int32_t *want = (u_int32_t *)
1338 ((ipfw_insn_mac *)cmd)->addr;
1339 u_int32_t *mask = (u_int32_t *)
1340 ((ipfw_insn_mac *)cmd)->mask;

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

1451 cmd->arg1, key, &v);
1452 if (!match)
1453 break;
1454 if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
1455 match =
1456 ((ipfw_insn_u32 *)cmd)->d[0] == v;
1457 else
1458 tablearg = v;
1459 } else if (is_ipv6) {
1460 uint32_t v = 0;
1461 void *pkey = (cmd->opcode == O_IP_DST_LOOKUP) ?
1462 &args->f_id.dst_ip6: &args->f_id.src_ip6;
1463 match = ipfw_lookup_table_extended(chain,
1464 cmd->arg1, pkey, &v,
1465 IPFW_TABLE_CIDR);
1466 if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
1467 match = ((ipfw_insn_u32 *)cmd)->d[0] == v;
1468 if (match)
1469 tablearg = v;
1451 }
1452 break;
1453
1454 case O_IP_SRC_MASK:
1455 case O_IP_DST_MASK:
1456 if (is_ipv4) {
1457 uint32_t a =
1458 (cmd->opcode == O_IP_DST_MASK) ?

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

2561#endif
2562#ifdef IPFIREWALL_VERBOSE_LIMIT
2563 V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
2564#endif
2565#ifdef IPFIREWALL_NAT
2566 LIST_INIT(&chain->nat);
2567#endif
2568
1470 }
1471 break;
1472
1473 case O_IP_SRC_MASK:
1474 case O_IP_DST_MASK:
1475 if (is_ipv4) {
1476 uint32_t a =
1477 (cmd->opcode == O_IP_DST_MASK) ?

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

2580#endif
2581#ifdef IPFIREWALL_VERBOSE_LIMIT
2582 V_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
2583#endif
2584#ifdef IPFIREWALL_NAT
2585 LIST_INIT(&chain->nat);
2586#endif
2587
2588 /* Check user-supplied number for validness */
2589 if (V_fw_tables_max < 0)
2590 V_fw_tables_max = IPFW_TABLES_MAX;
2591 if (V_fw_tables_max > 65534)
2592 V_fw_tables_max = 65534;
2593
2569 /* insert the default rule and create the initial map */
2570 chain->n_rules = 1;
2571 chain->static_len = sizeof(struct ip_fw);
2594 /* insert the default rule and create the initial map */
2595 chain->n_rules = 1;
2596 chain->static_len = sizeof(struct ip_fw);
2572 chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_NOWAIT | M_ZERO);
2597 chain->map = malloc(sizeof(struct ip_fw *), M_IPFW, M_WAITOK | M_ZERO);
2573 if (chain->map)
2598 if (chain->map)
2574 rule = malloc(chain->static_len, M_IPFW, M_NOWAIT | M_ZERO);
2575 if (rule == NULL) {
2576 if (chain->map)
2577 free(chain->map, M_IPFW);
2578 printf("ipfw2: ENOSPC initializing default rule "
2579 "(support disabled)\n");
2580 return (ENOSPC);
2581 }
2599 rule = malloc(chain->static_len, M_IPFW, M_WAITOK | M_ZERO);
2582 error = ipfw_init_tables(chain);
2583 if (error) {
2600 error = ipfw_init_tables(chain);
2601 if (error) {
2584 panic("init_tables"); /* XXX Marko fix this ! */
2602 printf("ipfw2: setting up tables failed\n");
2603 free(chain->map, M_IPFW);
2604 free(rule, M_IPFW);
2605 return (ENOSPC);
2585 }
2586
2587 /* fill and insert the default rule */
2588 rule->act_ofs = 0;
2589 rule->rulenum = IPFW_DEFAULT_RULE;
2590 rule->cmd_len = 1;
2591 rule->set = RESVD_SET;
2592 rule->cmd[0].len = 1;

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

2639 (void)ipfw_attach_hooks(0 /* detach */);
2640 V_ip_fw_chk_ptr = NULL;
2641 V_ip_fw_ctl_ptr = NULL;
2642 IPFW_UH_WLOCK(chain);
2643 IPFW_UH_WUNLOCK(chain);
2644 IPFW_UH_WLOCK(chain);
2645
2646 IPFW_WLOCK(chain);
2606 }
2607
2608 /* fill and insert the default rule */
2609 rule->act_ofs = 0;
2610 rule->rulenum = IPFW_DEFAULT_RULE;
2611 rule->cmd_len = 1;
2612 rule->set = RESVD_SET;
2613 rule->cmd[0].len = 1;

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

2660 (void)ipfw_attach_hooks(0 /* detach */);
2661 V_ip_fw_chk_ptr = NULL;
2662 V_ip_fw_ctl_ptr = NULL;
2663 IPFW_UH_WLOCK(chain);
2664 IPFW_UH_WUNLOCK(chain);
2665 IPFW_UH_WLOCK(chain);
2666
2667 IPFW_WLOCK(chain);
2668 ipfw_dyn_uninit(0); /* run the callout_drain */
2647 IPFW_WUNLOCK(chain);
2669 IPFW_WUNLOCK(chain);
2648 IPFW_WLOCK(chain);
2649
2670
2650 ipfw_dyn_uninit(0); /* run the callout_drain */
2651 ipfw_destroy_tables(chain);
2652 reap = NULL;
2671 ipfw_destroy_tables(chain);
2672 reap = NULL;
2673 IPFW_WLOCK(chain);
2653 for (i = 0; i < chain->n_rules; i++) {
2654 rule = chain->map[i];
2655 rule->x_next = reap;
2656 reap = rule;
2657 }
2658 if (chain->map)
2659 free(chain->map, M_IPFW);
2660 IPFW_WUNLOCK(chain);

--- 79 unchanged lines hidden ---
2674 for (i = 0; i < chain->n_rules; i++) {
2675 rule = chain->map[i];
2676 rule->x_next = reap;
2677 reap = rule;
2678 }
2679 if (chain->map)
2680 free(chain->map, M_IPFW);
2681 IPFW_WUNLOCK(chain);

--- 79 unchanged lines hidden ---