summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netpfil/ipfw
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-04-04 09:36:57 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-04-04 14:46:23 +0200
commitde8a76da2f374792594ce03a203b3f30e4889f6f (patch)
tree12b5e1e59358005c3c522955c08aee4795e4829c /freebsd/sys/netpfil/ipfw
parentEnable bridging by default (diff)
downloadrtems-libbsd-de8a76da2f374792594ce03a203b3f30e4889f6f.tar.bz2
Update to FreeBSD head 2017-04-04
Git mirror commit 642b174daddbd0efd9bb5f242c43f4ab4db6869f.
Diffstat (limited to 'freebsd/sys/netpfil/ipfw')
-rw-r--r--freebsd/sys/netpfil/ipfw/dn_aqm_pie.h6
-rw-r--r--freebsd/sys/netpfil/ipfw/dn_heap.h2
-rw-r--r--freebsd/sys/netpfil/ipfw/ip_fw2.c199
-rw-r--r--freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c1
-rw-r--r--freebsd/sys/netpfil/ipfw/ip_fw_eaction.c23
-rw-r--r--freebsd/sys/netpfil/ipfw/ip_fw_iface.c1
-rw-r--r--freebsd/sys/netpfil/ipfw/ip_fw_log.c8
-rw-r--r--freebsd/sys/netpfil/ipfw/ip_fw_nat.c1
-rw-r--r--freebsd/sys/netpfil/ipfw/ip_fw_private.h26
-rw-r--r--freebsd/sys/netpfil/ipfw/ip_fw_sockopt.c27
-rw-r--r--freebsd/sys/netpfil/ipfw/ip_fw_table.c22
-rw-r--r--freebsd/sys/netpfil/ipfw/ip_fw_table_value.c1
-rw-r--r--freebsd/sys/netpfil/ipfw/nat64/nat64lsn.c2
-rw-r--r--freebsd/sys/netpfil/ipfw/nat64/nat64stl.c12
-rw-r--r--freebsd/sys/netpfil/ipfw/nptv6/nptv6.c30
15 files changed, 217 insertions, 144 deletions
diff --git a/freebsd/sys/netpfil/ipfw/dn_aqm_pie.h b/freebsd/sys/netpfil/ipfw/dn_aqm_pie.h
index aa2fceba..7512d327 100644
--- a/freebsd/sys/netpfil/ipfw/dn_aqm_pie.h
+++ b/freebsd/sys/netpfil/ipfw/dn_aqm_pie.h
@@ -37,16 +37,16 @@
#define DN_AQM_PIE 2
#define PIE_DQ_THRESHOLD_BITS 14
/* 2^14 =16KB */
-#define PIE_DQ_THRESHOLD (1UL << PIE_DQ_THRESHOLD_BITS)
+#define PIE_DQ_THRESHOLD (1L << PIE_DQ_THRESHOLD_BITS)
#define MEAN_PKTSIZE 800
/* 31-bits because random() generates range from 0->(2**31)-1 */
#define PIE_PROB_BITS 31
-#define PIE_MAX_PROB ((1ULL<<PIE_PROB_BITS) -1)
+#define PIE_MAX_PROB ((1LL<<PIE_PROB_BITS) -1)
/* for 16-bits, we have 3-bits for integer part and 13-bits for fraction */
#define PIE_FIX_POINT_BITS 13
-#define PIE_SCALE (1UL<<PIE_FIX_POINT_BITS)
+#define PIE_SCALE (1L<<PIE_FIX_POINT_BITS)
/* PIE options */
diff --git a/freebsd/sys/netpfil/ipfw/dn_heap.h b/freebsd/sys/netpfil/ipfw/dn_heap.h
index cb6e03ef..bbc11c14 100644
--- a/freebsd/sys/netpfil/ipfw/dn_heap.h
+++ b/freebsd/sys/netpfil/ipfw/dn_heap.h
@@ -85,7 +85,7 @@ enum {
* HEAP_TOP() returns a pointer to the top element of the heap,
* but makes no checks on its existence (XXX should we change ?)
*
- * heap_extract() removes the entry at the top, returing the pointer.
+ * heap_extract() removes the entry at the top, returning the pointer.
* (the key should have been read before).
*
* heap_scan() invokes a callback on each entry of the heap.
diff --git a/freebsd/sys/netpfil/ipfw/ip_fw2.c b/freebsd/sys/netpfil/ipfw/ip_fw2.c
index 945ad170..1425d95f 100644
--- a/freebsd/sys/netpfil/ipfw/ip_fw2.c
+++ b/freebsd/sys/netpfil/ipfw/ip_fw2.c
@@ -384,8 +384,8 @@ iface_match(struct ifnet *ifp, ipfw_insn_if *cmd, struct ip_fw_chain *chain,
/* Check by name or by IP address */
if (cmd->name[0] != '\0') { /* match by name */
if (cmd->name[0] == '\1') /* use tablearg to match */
- return ipfw_lookup_table_extended(chain, cmd->p.kidx, 0,
- &ifp->if_index, tablearg);
+ return ipfw_lookup_table(chain, cmd->p.kidx, 0,
+ &ifp->if_index, tablearg);
/* Check name */
if (cmd->p.glob) {
if (fnmatch(cmd->name, ifp->if_xname, 0) == 0)
@@ -1002,7 +1002,6 @@ ipfw_chk(struct ip_fw_args *args)
int is_ipv4 = 0;
int done = 0; /* flag to exit the outer loop */
- IPFW_RLOCK_TRACKER;
if (m->m_flags & M_SKIP_FIREWALL || (! V_ipfw_vnet_ready))
return (IP_FW_PASS); /* accept */
@@ -1465,96 +1464,142 @@ do { \
src_ip.s_addr);
break;
- case O_IP_SRC_LOOKUP:
case O_IP_DST_LOOKUP:
- if (is_ipv4) {
- uint32_t key =
- (cmd->opcode == O_IP_DST_LOOKUP) ?
- dst_ip.s_addr : src_ip.s_addr;
- uint32_t v = 0;
-
- if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) {
- /* generic lookup. The key must be
- * in 32bit big-endian format.
- */
- v = ((ipfw_insn_u32 *)cmd)->d[1];
- if (v == 0)
- key = dst_ip.s_addr;
- else if (v == 1)
- key = src_ip.s_addr;
- else if (v == 6) /* dscp */
- key = (ip->ip_tos >> 2) & 0x3f;
- else if (offset != 0)
- break;
- else if (proto != IPPROTO_TCP &&
- proto != IPPROTO_UDP)
- break;
- else if (v == 2)
- key = dst_port;
- else if (v == 3)
- key = src_port;
+ {
+ void *pkey;
+ uint32_t vidx, key;
+ uint16_t keylen;
+
+ if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) {
+ /* Determine lookup key type */
+ vidx = ((ipfw_insn_u32 *)cmd)->d[1];
+ if (vidx != 4 /* uid */ &&
+ vidx != 5 /* jail */ &&
+ is_ipv6 == 0 && is_ipv4 == 0)
+ break;
+ /* Determine key length */
+ if (vidx == 0 /* dst-ip */ ||
+ vidx == 1 /* src-ip */)
+ keylen = is_ipv6 ?
+ sizeof(struct in6_addr):
+ sizeof(in_addr_t);
+ else {
+ keylen = sizeof(key);
+ pkey = &key;
+ }
+ if (vidx == 0 /* dst-ip */)
+ pkey = is_ipv4 ? (void *)&dst_ip:
+ (void *)&args->f_id.dst_ip6;
+ else if (vidx == 1 /* src-ip */)
+ pkey = is_ipv4 ? (void *)&src_ip:
+ (void *)&args->f_id.src_ip6;
+ else if (vidx == 6 /* dscp */) {
+ if (is_ipv4)
+ key = ip->ip_tos >> 2;
+ else {
+ key = args->f_id.flow_id6;
+ key = (key & 0x0f) << 2 |
+ (key & 0xf000) >> 14;
+ }
+ key &= 0x3f;
+ } else if (vidx == 2 /* dst-port */ ||
+ vidx == 3 /* src-port */) {
+ /* Skip fragments */
+ if (offset != 0)
+ break;
+ /* Skip proto without ports */
+ if (proto != IPPROTO_TCP &&
+ proto != IPPROTO_UDP &&
+ proto != IPPROTO_SCTP)
+ break;
+ if (vidx == 2 /* dst-port */)
+ key = dst_port;
+ else
+ key = src_port;
+ }
#ifndef USERSPACE
- else if (v == 4 || v == 5) {
- check_uidgid(
- (ipfw_insn_u32 *)cmd,
- args, &ucred_lookup,
+ else if (vidx == 4 /* uid */ ||
+ vidx == 5 /* jail */) {
+ check_uidgid(
+ (ipfw_insn_u32 *)cmd,
+ args, &ucred_lookup,
#ifdef __FreeBSD__
- &ucred_cache);
- if (v == 4 /* O_UID */)
+ &ucred_cache);
+ if (vidx == 4 /* uid */)
#ifndef __rtems__
- key = ucred_cache->cr_uid;
+ key = ucred_cache->cr_uid;
#else /* __rtems__ */
- key = BSD_DEFAULT_UID;
+ key = BSD_DEFAULT_UID;
#endif /* __rtems__ */
- else if (v == 5 /* O_JAIL */)
+ else if (vidx == 5 /* jail */)
#ifndef __rtems__
- key = ucred_cache->cr_prison->pr_id;
+ key = ucred_cache->cr_prison->pr_id;
#else /* __rtems__ */
- key = BSD_DEFAULT_PRISON->pr_id;
+ key = BSD_DEFAULT_PRISON->pr_id;
#endif /* __rtems__ */
#else /* !__FreeBSD__ */
- (void *)&ucred_cache);
- if (v ==4 /* O_UID */)
- key = ucred_cache.uid;
- else if (v == 5 /* O_JAIL */)
- key = ucred_cache.xid;
+ (void *)&ucred_cache);
+ if (vidx == 4 /* uid */)
+ key = ucred_cache.uid;
+ else if (vidx == 5 /* jail */)
+ key = ucred_cache.xid;
#endif /* !__FreeBSD__ */
}
#endif /* !USERSPACE */
else
- break;
- }
- match = ipfw_lookup_table(chain,
- cmd->arg1, key, &v);
- if (!match)
+ break;
+ match = ipfw_lookup_table(chain,
+ cmd->arg1, keylen, pkey, &vidx);
+ if (!match)
+ break;
+ tablearg = vidx;
break;
- if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
- match =
- ((ipfw_insn_u32 *)cmd)->d[0] == v;
- else
- tablearg = v;
+ }
+ /* cmdlen =< F_INSN_SIZE(ipfw_insn_u32) */
+ /* FALLTHROUGH */
+ }
+ case O_IP_SRC_LOOKUP:
+ {
+ void *pkey;
+ uint32_t vidx;
+ uint16_t keylen;
+
+ if (is_ipv4) {
+ keylen = sizeof(in_addr_t);
+ if (cmd->opcode == O_IP_DST_LOOKUP)
+ pkey = &dst_ip;
+ else
+ pkey = &src_ip;
} else if (is_ipv6) {
- uint32_t v = 0;
- void *pkey = (cmd->opcode == O_IP_DST_LOOKUP) ?
- &args->f_id.dst_ip6: &args->f_id.src_ip6;
- match = ipfw_lookup_table_extended(chain,
- cmd->arg1,
- sizeof(struct in6_addr),
- pkey, &v);
- if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
- match = ((ipfw_insn_u32 *)cmd)->d[0] == v;
- if (match)
- tablearg = v;
+ keylen = sizeof(struct in6_addr);
+ if (cmd->opcode == O_IP_DST_LOOKUP)
+ pkey = &args->f_id.dst_ip6;
+ else
+ pkey = &args->f_id.src_ip6;
+ } else
+ break;
+ match = ipfw_lookup_table(chain, cmd->arg1,
+ keylen, pkey, &vidx);
+ if (!match)
+ break;
+ if (cmdlen == F_INSN_SIZE(ipfw_insn_u32)) {
+ match = ((ipfw_insn_u32 *)cmd)->d[0] ==
+ TARG_VAL(chain, vidx, tag);
+ if (!match)
+ break;
}
+ tablearg = vidx;
break;
+ }
case O_IP_FLOW_LOOKUP:
{
uint32_t v = 0;
- match = ipfw_lookup_table_extended(chain,
+ match = ipfw_lookup_table(chain,
cmd->arg1, 0, &args->f_id, &v);
if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
- match = ((ipfw_insn_u32 *)cmd)->d[0] == v;
+ match = ((ipfw_insn_u32 *)cmd)->d[0] ==
+ TARG_VAL(chain, v, tag);
if (match)
tablearg = v;
}
@@ -2583,6 +2628,22 @@ do { \
l = 0; /* in any case exit inner loop */
retval = ipfw_run_eaction(chain, args,
cmd, &done);
+ /*
+ * If both @retval and @done are zero,
+ * consider this as rule matching and
+ * update counters.
+ */
+ if (retval == 0 && done == 0) {
+ IPFW_INC_RULE_COUNTER(f, pktlen);
+ /*
+ * Reset the result of the last
+ * dynamic state lookup.
+ * External action can change
+ * @args content, and it may be
+ * used for new state lookup later.
+ */
+ dyn_dir = MATCH_UNKNOWN;
+ }
break;
default:
diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c b/freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c
index 5694b1d1..e21cb07e 100644
--- a/freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c
+++ b/freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <net/ethernet.h> /* for ETHERTYPE_IP */
#include <net/if.h>
#include <net/if_var.h>
+#include <net/pfil.h>
#include <net/vnet.h>
#include <netinet/in.h>
diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_eaction.c b/freebsd/sys/netpfil/ipfw/ip_fw_eaction.c
index 2c6ba8b9..817aaca4 100644
--- a/freebsd/sys/netpfil/ipfw/ip_fw_eaction.c
+++ b/freebsd/sys/netpfil/ipfw/ip_fw_eaction.c
@@ -1,8 +1,8 @@
#include <machine/rtems-bsd-kernel-space.h>
/*-
- * Copyright (c) 2016 Yandex LLC
- * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org>
+ * Copyright (c) 2016-2017 Yandex LLC
+ * Copyright (c) 2016-2017 Andrey V. Elsukov <ae@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$");
* rules.
* Module should implement opcode handler with type ipfw_eaction_t.
* This handler will be called by ipfw_chk() function when
- * O_EXTERNAL_ACTION opcode will be matched. The handler must return
+ * O_EXTERNAL_ACTION opcode is matched. The handler must return
* value used as return value in ipfw_chk(), i.e. IP_FW_PASS,
* IP_FW_DENY (see ip_fw_private.h).
* Also the last argument must be set by handler. If it is zero,
@@ -71,9 +71,12 @@ __FBSDID("$FreeBSD$");
* This function will return eaction_id, that can be used by module.
*
* It is possible to pass some additional information to external
- * action handler via the O_EXTERNAL_INSTANCE opcode. This opcode
- * will be next after the O_EXTERNAL_ACTION opcode. cmd->arg1 will
- * contain index of named object related to instance of external action.
+ * action handler using O_EXTERNAL_INSTANCE and O_EXTERNAL_DATA opcodes.
+ * Such opcodes should be next after the O_EXTERNAL_ACTION opcode.
+ * For the O_EXTERNAL_INSTANCE opcode the cmd->arg1 contains index of named
+ * object related to an instance of external action.
+ * For the O_EXTERNAL_DATA opcode the cmd contains the data that can be used
+ * by external action handler without needing to create named instance.
*
* In case when eaction module uses named instances, it should register
* opcode rewriting routines for O_EXTERNAL_INSTANCE opcode. The
@@ -286,11 +289,13 @@ reset_eaction_obj(struct ip_fw_chain *ch, uint16_t eaction_id)
/*
* Since named_object related to this instance will be
* also destroyed, truncate the chain of opcodes to
- * remove O_EXTERNAL_INSTANCE opcode.
+ * remove the rest of cmd chain just after O_EXTERNAL_ACTION
+ * opcode.
*/
if (rule->act_ofs < rule->cmd_len - 1) {
- EACTION_DEBUG("truncate rule %d", rule->rulenum);
- rule->cmd_len--;
+ EACTION_DEBUG("truncate rule %d: len %u -> %u",
+ rule->rulenum, rule->cmd_len, rule->act_ofs + 1);
+ rule->cmd_len = rule->act_ofs + 1;
}
}
IPFW_WUNLOCK(ch);
diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_iface.c b/freebsd/sys/netpfil/ipfw/ip_fw_iface.c
index f8973a91..f93c20db 100644
--- a/freebsd/sys/netpfil/ipfw/ip_fw_iface.c
+++ b/freebsd/sys/netpfil/ipfw/ip_fw_iface.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <sys/eventhandler.h>
#include <net/if.h>
#include <net/if_var.h>
+#include <net/pfil.h>
#include <net/vnet.h>
#include <netinet/in.h>
diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_log.c b/freebsd/sys/netpfil/ipfw/ip_fw_log.c
index 658e1256..15b611e6 100644
--- a/freebsd/sys/netpfil/ipfw/ip_fw_log.c
+++ b/freebsd/sys/netpfil/ipfw/ip_fw_log.c
@@ -213,6 +213,7 @@ ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen,
TARG(cmd->arg1, pipe));
break;
case O_FORWARD_IP: {
+ char buf[INET_ADDRSTRLEN];
ipfw_insn_sa *sa = (ipfw_insn_sa *)cmd;
int len;
struct in_addr dummyaddr;
@@ -222,7 +223,7 @@ ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen,
dummyaddr.s_addr = sa->sa.sin_addr.s_addr;
len = snprintf(SNPARGS(action2, 0), "Forward to %s",
- inet_ntoa(dummyaddr));
+ inet_ntoa_r(dummyaddr, buf));
if (sa->sa.sin_port)
snprintf(SNPARGS(action2, len), ":%d",
@@ -265,6 +266,11 @@ ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen,
snprintf(SNPARGS(action2, 0), "Call %d",
cmd->arg1);
break;
+ case O_EXTERNAL_ACTION:
+ snprintf(SNPARGS(action2, 0), "Eaction %s",
+ ((struct named_object *)SRV_OBJECT(chain,
+ cmd->arg1))->name);
+ break;
default:
action = "UNKNOWN";
break;
diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_nat.c b/freebsd/sys/netpfil/ipfw/ip_fw_nat.c
index 58bc1f3c..8baa313a 100644
--- a/freebsd/sys/netpfil/ipfw/ip_fw_nat.c
+++ b/freebsd/sys/netpfil/ipfw/ip_fw_nat.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_var.h>
+#include <net/pfil.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_private.h b/freebsd/sys/netpfil/ipfw/ip_fw_private.h
index 3b483625..b6471a02 100644
--- a/freebsd/sys/netpfil/ipfw/ip_fw_private.h
+++ b/freebsd/sys/netpfil/ipfw/ip_fw_private.h
@@ -272,8 +272,6 @@ struct ip_fw_chain {
void **srvstate; /* runtime service mappings */
#if defined( __linux__ ) || defined( _WIN32 )
spinlock_t rwmtx;
-#else
- struct rmlock rwmtx;
#endif
int static_len; /* total len of static rules (v0) */
uint32_t gencnt; /* NAT generation count */
@@ -414,25 +412,23 @@ struct ipfw_ifc {
#define IPFW_PF_RUNLOCK(p) IPFW_RUNLOCK(p)
#else /* FreeBSD */
#define IPFW_LOCK_INIT(_chain) do { \
- rm_init(&(_chain)->rwmtx, "IPFW static rules"); \
rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \
} while (0)
#define IPFW_LOCK_DESTROY(_chain) do { \
- rm_destroy(&(_chain)->rwmtx); \
rw_destroy(&(_chain)->uh_lock); \
} while (0)
-#define IPFW_RLOCK_ASSERT(_chain) rm_assert(&(_chain)->rwmtx, RA_RLOCKED)
-#define IPFW_WLOCK_ASSERT(_chain) rm_assert(&(_chain)->rwmtx, RA_WLOCKED)
+#define IPFW_RLOCK_ASSERT(_chain) rm_assert(&V_pfil_lock, RA_RLOCKED)
+#define IPFW_WLOCK_ASSERT(_chain) rm_assert(&V_pfil_lock, RA_WLOCKED)
#define IPFW_RLOCK_TRACKER struct rm_priotracker _tracker
-#define IPFW_RLOCK(p) rm_rlock(&(p)->rwmtx, &_tracker)
-#define IPFW_RUNLOCK(p) rm_runlock(&(p)->rwmtx, &_tracker)
-#define IPFW_WLOCK(p) rm_wlock(&(p)->rwmtx)
-#define IPFW_WUNLOCK(p) rm_wunlock(&(p)->rwmtx)
-#define IPFW_PF_RLOCK(p) IPFW_RLOCK(p)
-#define IPFW_PF_RUNLOCK(p) IPFW_RUNLOCK(p)
+#define IPFW_RLOCK(p) rm_rlock(&V_pfil_lock, &_tracker)
+#define IPFW_RUNLOCK(p) rm_runlock(&V_pfil_lock, &_tracker)
+#define IPFW_WLOCK(p) rm_wlock(&V_pfil_lock)
+#define IPFW_WUNLOCK(p) rm_wunlock(&V_pfil_lock)
+#define IPFW_PF_RLOCK(p)
+#define IPFW_PF_RUNLOCK(p)
#endif
#define IPFW_UH_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_RLOCKED)
@@ -741,10 +737,8 @@ struct table_info;
typedef int (table_lookup_t)(struct table_info *ti, void *key, uint32_t keylen,
uint32_t *val);
-int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
- uint32_t *val);
-int ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl,
- uint16_t plen, void *paddr, uint32_t *val);
+int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen,
+ void *paddr, uint32_t *val);
struct named_object *ipfw_objhash_lookup_table_kidx(struct ip_fw_chain *ch,
uint16_t kidx);
int ipfw_ref_table(struct ip_fw_chain *ch, ipfw_obj_ntlv *ntlv, uint16_t *kidx);
diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_sockopt.c b/freebsd/sys/netpfil/ipfw/ip_fw_sockopt.c
index 468e4ad4..d9d37758 100644
--- a/freebsd/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/freebsd/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syslog.h>
#include <sys/fnv_hash.h>
#include <net/if.h>
+#include <net/pfil.h>
#include <net/route.h>
#include <net/vnet.h>
#include <vm/vm.h>
@@ -1738,11 +1739,16 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci)
return (EINVAL);
}
ci->object_opcodes++;
- /* Do we have O_EXTERNAL_INSTANCE opcode? */
+ /*
+ * Do we have O_EXTERNAL_INSTANCE or O_EXTERNAL_DATA
+ * opcode?
+ */
if (l != cmdlen) {
l -= cmdlen;
cmd += cmdlen;
cmdlen = F_LEN(cmd);
+ if (cmd->opcode == O_EXTERNAL_DATA)
+ goto check_action;
if (cmd->opcode != O_EXTERNAL_INSTANCE) {
printf("ipfw: invalid opcode "
"next to external action %u\n",
@@ -1828,6 +1834,8 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci)
break;
case O_IP_SRC_LOOKUP:
+ if (cmdlen > F_INSN_SIZE(ipfw_insn_u32))
+ goto bad_size;
case O_IP_DST_LOOKUP:
if (cmd->arg1 >= V_fw_tables_max) {
printf("ipfw: invalid table number %d\n",
@@ -2618,11 +2626,11 @@ unref_rule_objects(struct ip_fw_chain *ch, struct ip_fw *rule)
continue;
no = rw->find_bykidx(ch, kidx);
- KASSERT(no != NULL, ("table id %d not found", kidx));
+ KASSERT(no != NULL, ("object id %d not found", kidx));
KASSERT(no->subtype == subtype,
- ("wrong type %d (%d) for table id %d",
+ ("wrong type %d (%d) for object id %d",
no->subtype, subtype, kidx));
- KASSERT(no->refcnt > 0, ("refcount for table %d is %d",
+ KASSERT(no->refcnt > 0, ("refcount for object %d is %d",
kidx, no->refcnt));
if (no->refcnt == 1 && rw->destroy_object != NULL)
@@ -2671,7 +2679,14 @@ ref_opcode_object(struct ip_fw_chain *ch, ipfw_insn *cmd, struct tid_info *ti,
return (0);
}
- /* Found. Bump refcount and update kidx. */
+ /*
+ * Object is already exist.
+ * Its subtype should match with expected value.
+ */
+ if (ti->type != no->subtype)
+ return (EINVAL);
+
+ /* Bump refcount and update kidx. */
no->refcnt++;
rw->update(cmd, no->kidx);
return (0);
@@ -3137,7 +3152,7 @@ int
classify_opcode_kidx(ipfw_insn *cmd, uint16_t *puidx)
{
- if (find_op_rw(cmd, puidx, NULL) == 0)
+ if (find_op_rw(cmd, puidx, NULL) == NULL)
return (1);
return (0);
}
diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_table.c b/freebsd/sys/netpfil/ipfw/ip_fw_table.c
index 17c5f017..48a969da 100644
--- a/freebsd/sys/netpfil/ipfw/ip_fw_table.c
+++ b/freebsd/sys/netpfil/ipfw/ip_fw_table.c
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socketvar.h>
#include <sys/queue.h>
#include <net/if.h> /* ip_fw.h requires IFNAMSIZ */
+#include <net/pfil.h>
#include <netinet/in.h>
#include <netinet/ip_var.h> /* struct ipfw_rule_ref */
@@ -407,7 +408,7 @@ prepare_batch_buffer(struct ip_fw_chain *ch, struct table_algo *ta,
error = 0;
ta_buf_sz = ta->ta_buf_size;
if (count == 1) {
- /* Sigle add/delete, use on-stack buffer */
+ /* Single add/delete, use on-stack buffer */
memset(*ta_buf, 0, TA_BUF_SZ);
ta_buf_m = *ta_buf;
} else {
@@ -1659,30 +1660,13 @@ ipfw_unref_table(struct ip_fw_chain *ch, uint16_t kidx)
}
/*
- * Lookup an IP @addr in table @tbl.
- * Stores found value in @val.
- *
- * Returns 1 if @addr was found.
- */
-int
-ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
- uint32_t *val)
-{
- struct table_info *ti;
-
- ti = KIDX_TO_TI(ch, tbl);
-
- return (ti->lookup(ti, &addr, sizeof(in_addr_t), val));
-}
-
-/*
* Lookup an arbtrary key @paddr of legth @plen in table @tbl.
* Stores found value in @val.
*
* Returns 1 if key was found.
*/
int
-ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen,
+ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen,
void *paddr, uint32_t *val)
{
struct table_info *ti;
diff --git a/freebsd/sys/netpfil/ipfw/ip_fw_table_value.c b/freebsd/sys/netpfil/ipfw/ip_fw_table_value.c
index ef42e401..4ef70b8a 100644
--- a/freebsd/sys/netpfil/ipfw/ip_fw_table_value.c
+++ b/freebsd/sys/netpfil/ipfw/ip_fw_table_value.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socketvar.h>
#include <sys/queue.h>
#include <net/if.h> /* ip_fw.h requires IFNAMSIZ */
+#include <net/pfil.h>
#include <netinet/in.h>
#include <netinet/ip_var.h> /* struct ipfw_rule_ref */
diff --git a/freebsd/sys/netpfil/ipfw/nat64/nat64lsn.c b/freebsd/sys/netpfil/ipfw/nat64/nat64lsn.c
index ce666213..ae072a68 100644
--- a/freebsd/sys/netpfil/ipfw/nat64/nat64lsn.c
+++ b/freebsd/sys/netpfil/ipfw/nat64/nat64lsn.c
@@ -217,7 +217,7 @@ nat64lsn_log(struct pfloghdr *plog, struct mbuf *m, sa_family_t family,
uint32_t n, uint32_t sn)
{
- memset(plog, 0, sizeof(plog));
+ memset(plog, 0, sizeof(*plog));
plog->length = PFLOG_REAL_HDRLEN;
plog->af = family;
plog->action = PF_NAT;
diff --git a/freebsd/sys/netpfil/ipfw/nat64/nat64stl.c b/freebsd/sys/netpfil/ipfw/nat64/nat64stl.c
index 36e6e268..552267be 100644
--- a/freebsd/sys/netpfil/ipfw/nat64/nat64stl.c
+++ b/freebsd/sys/netpfil/ipfw/nat64/nat64stl.c
@@ -71,7 +71,7 @@ nat64stl_log(struct pfloghdr *plog, struct mbuf *m, sa_family_t family,
{
static uint32_t pktid = 0;
- memset(plog, 0, sizeof(plog));
+ memset(plog, 0, sizeof(*plog));
plog->length = PFLOG_REAL_HDRLEN;
plog->af = family;
plog->action = PF_NAT;
@@ -186,7 +186,7 @@ nat64stl_handle_icmp6(struct ip_fw_chain *chain, struct nat64stl_cfg *cfg,
* IPv4 mapped address.
*/
ip6i = mtodo(m, hlen);
- if (ipfw_lookup_table_extended(chain, cfg->map64,
+ if (ipfw_lookup_table(chain, cfg->map64,
sizeof(struct in6_addr), &ip6i->ip6_dst, &tablearg) == 0) {
m_freem(m);
return (NAT64RETURN);
@@ -206,6 +206,7 @@ ipfw_nat64stl(struct ip_fw_chain *chain, struct ip_fw_args *args,
{
ipfw_insn *icmd;
struct nat64stl_cfg *cfg;
+ in_addr_t dst4;
uint32_t tablearg;
int ret;
@@ -221,11 +222,12 @@ ipfw_nat64stl(struct ip_fw_chain *chain, struct ip_fw_args *args,
switch (args->f_id.addr_type) {
case 4:
- ret = ipfw_lookup_table(chain, cfg->map46,
- htonl(args->f_id.dst_ip), &tablearg);
+ dst4 = htonl(args->f_id.dst_ip);
+ ret = ipfw_lookup_table(chain, cfg->map46, sizeof(in_addr_t),
+ &dst4, &tablearg);
break;
case 6:
- ret = ipfw_lookup_table_extended(chain, cfg->map64,
+ ret = ipfw_lookup_table(chain, cfg->map64,
sizeof(struct in6_addr), &args->f_id.src_ip6, &tablearg);
break;
default:
diff --git a/freebsd/sys/netpfil/ipfw/nptv6/nptv6.c b/freebsd/sys/netpfil/ipfw/nptv6/nptv6.c
index 4256d028..819ba4fe 100644
--- a/freebsd/sys/netpfil/ipfw/nptv6/nptv6.c
+++ b/freebsd/sys/netpfil/ipfw/nptv6/nptv6.c
@@ -354,24 +354,24 @@ ipfw_nptv6(struct ip_fw_chain *chain, struct ip_fw_args *args,
int ret;
*done = 0; /* try next rule if not matched */
+ ret = IP_FW_DENY;
icmd = cmd + 1;
if (cmd->opcode != O_EXTERNAL_ACTION ||
cmd->arg1 != V_nptv6_eid ||
icmd->opcode != O_EXTERNAL_INSTANCE ||
(cfg = NPTV6_LOOKUP(chain, icmd)) == NULL)
- return (0);
+ return (ret);
/*
* We need act as router, so when forwarding is disabled -
* do nothing.
*/
if (V_ip6_forwarding == 0 || args->f_id.addr_type != 6)
- return (0);
+ return (ret);
/*
* NOTE: we expect ipfw_chk() did m_pullup() up to upper level
* protocol's headers. Also we skip some checks, that ip6_input(),
* ip6_forward(), ip6_fastfwd() and ipfw_chk() already did.
*/
- ret = IP_FW_DENY;
ip6 = mtod(args->m, struct ip6_hdr *);
NPTV6_IPDEBUG("eid %u, oid %u, %s -> %s %d",
cmd->arg1, icmd->arg1,
@@ -386,15 +386,15 @@ ipfw_nptv6(struct ip_fw_chain *chain, struct ip_fw_args *args,
*/
if (IN6_ARE_MASKED_ADDR_EQUAL(&ip6->ip6_dst,
&cfg->internal, &cfg->mask))
- return (0);
+ return (ret);
ret = nptv6_rewrite_internal(cfg, &args->m, 0);
} else if (IN6_ARE_MASKED_ADDR_EQUAL(&ip6->ip6_dst,
&cfg->external, &cfg->mask))
ret = nptv6_rewrite_external(cfg, &args->m, 0);
else
- return (0);
+ return (ret);
/*
- * If address wasn't rewrited - free mbuf.
+ * If address wasn't rewrited - free mbuf and terminate the search.
*/
if (ret != 0) {
if (args->m != NULL) {
@@ -402,14 +402,16 @@ ipfw_nptv6(struct ip_fw_chain *chain, struct ip_fw_args *args,
args->m = NULL; /* mark mbuf as consumed */
}
NPTV6STAT_INC(cfg, dropped);
- }
- /* Terminate the search if one_pass is set */
- *done = V_fw_one_pass;
- /* Update args->f_id when one_pass is off */
- if (*done == 0 && ret == 0) {
- ip6 = mtod(args->m, struct ip6_hdr *);
- args->f_id.src_ip6 = ip6->ip6_src;
- args->f_id.dst_ip6 = ip6->ip6_dst;
+ *done = 1;
+ } else {
+ /* Terminate the search if one_pass is set */
+ *done = V_fw_one_pass;
+ /* Update args->f_id when one_pass is off */
+ if (*done == 0) {
+ ip6 = mtod(args->m, struct ip6_hdr *);
+ args->f_id.src_ip6 = ip6->ip6_src;
+ args->f_id.dst_ip6 = ip6->ip6_dst;
+ }
}
return (ret);
}