diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-04-04 09:36:57 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-04-04 14:46:23 +0200 |
commit | de8a76da2f374792594ce03a203b3f30e4889f6f (patch) | |
tree | 12b5e1e59358005c3c522955c08aee4795e4829c /freebsd/sys/netpfil | |
parent | Enable bridging by default (diff) | |
download | rtems-libbsd-de8a76da2f374792594ce03a203b3f30e4889f6f.tar.bz2 |
Update to FreeBSD head 2017-04-04
Git mirror commit 642b174daddbd0efd9bb5f242c43f4ab4db6869f.
Diffstat (limited to 'freebsd/sys/netpfil')
-rw-r--r-- | freebsd/sys/netpfil/ipfw/dn_aqm_pie.h | 6 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/dn_heap.h | 2 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/ip_fw2.c | 199 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/ip_fw_dynamic.c | 1 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/ip_fw_eaction.c | 23 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/ip_fw_iface.c | 1 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/ip_fw_log.c | 8 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/ip_fw_nat.c | 1 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/ip_fw_private.h | 26 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/ip_fw_sockopt.c | 27 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/ip_fw_table.c | 22 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/ip_fw_table_value.c | 1 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/nat64/nat64lsn.c | 2 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/nat64/nat64stl.c | 12 | ||||
-rw-r--r-- | freebsd/sys/netpfil/ipfw/nptv6/nptv6.c | 30 | ||||
-rw-r--r-- | freebsd/sys/netpfil/pf/pf.c | 63 | ||||
-rw-r--r-- | freebsd/sys/netpfil/pf/pf_ioctl.c | 14 | ||||
-rw-r--r-- | freebsd/sys/netpfil/pf/pf_lb.c | 2 | ||||
-rw-r--r-- | freebsd/sys/netpfil/pf/pf_osfp.c | 15 |
19 files changed, 278 insertions, 177 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); } diff --git a/freebsd/sys/netpfil/pf/pf.c b/freebsd/sys/netpfil/pf/pf.c index 5b6be3cb..0d7a353e 100644 --- a/freebsd/sys/netpfil/pf/pf.c +++ b/freebsd/sys/netpfil/pf/pf.c @@ -131,6 +131,8 @@ VNET_DEFINE(int, pf_tcp_secret_init); #define V_pf_tcp_secret_init VNET(pf_tcp_secret_init) VNET_DEFINE(int, pf_tcp_iss_off); #define V_pf_tcp_iss_off VNET(pf_tcp_iss_off) +VNET_DECLARE(int, pf_vnet_active); +#define V_pf_vnet_active VNET(pf_vnet_active) /* * Queue for pf_intr() sends. @@ -302,6 +304,7 @@ static void pf_route6(struct mbuf **, struct pf_rule *, int, int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len); extern int pf_end_threads; +extern struct proc *pf_purge_proc; VNET_DEFINE(struct pf_limit, pf_limits[PF_LIMIT_MAX]); @@ -1428,42 +1431,51 @@ pf_purge_thread(void *unused __unused) VNET_ITERATOR_DECL(vnet_iter); u_int idx = 0; - for (;;) { - PF_RULES_RLOCK(); - rw_sleep(pf_purge_thread, &pf_rules_lock, 0, "pftm", hz / 10); - PF_RULES_RUNLOCK(); + sx_xlock(&pf_end_lock); + while (pf_end_threads == 0) { + sx_sleep(pf_purge_thread, &pf_end_lock, 0, "pftm", hz / 10); VNET_LIST_RLOCK(); VNET_FOREACH(vnet_iter) { CURVNET_SET(vnet_iter); - if (pf_end_threads) { - pf_end_threads++; - wakeup(pf_purge_thread); - kproc_exit(0); - } - /* Process 1/interval fraction of the state table every run. */ - idx = pf_purge_expired_states(idx, pf_hashmask / + /* Wait until V_pf_default_rule is initialized. */ + if (V_pf_vnet_active == 0) { + CURVNET_RESTORE(); + continue; + } + + /* + * Process 1/interval fraction of the state + * table every run. + */ + idx = pf_purge_expired_states(idx, pf_hashmask / (V_pf_default_rule.timeout[PFTM_INTERVAL] * 10)); - /* Purge other expired types every PFTM_INTERVAL seconds. */ - if (idx == 0) { /* - * Order is important: - * - states and src nodes reference rules - * - states and rules reference kifs + * Purge other expired types every + * PFTM_INTERVAL seconds. */ - pf_purge_expired_fragments(); - pf_purge_expired_src_nodes(); - pf_purge_unlinked_rules(); - pfi_kif_purge(); - } - CURVNET_RESTORE(); + if (idx == 0) { + /* + * Order is important: + * - states and src nodes reference rules + * - states and rules reference kifs + */ + pf_purge_expired_fragments(); + pf_purge_expired_src_nodes(); + pf_purge_unlinked_rules(); + pfi_kif_purge(); + } + CURVNET_RESTORE(); } VNET_LIST_RUNLOCK(); } - /* not reached */ + + pf_end_threads++; + sx_xunlock(&pf_end_lock); + kproc_exit(0); } void @@ -3559,7 +3571,7 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a, (counter_u64_fetch(r->states_cur) >= r->max_states)) { counter_u64_add(V_pf_status.lcounters[LCNT_STATES], 1); REASON_SET(&reason, PFRES_MAXSTATES); - return (PF_DROP); + goto csfailed; } /* src node for filter rule */ if ((r->rule_flag & PFRULE_SRCTRACK || @@ -6244,6 +6256,9 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) m->m_pkthdr.rcvif->if_bridge != ifp->if_bridge))) fwdir = PF_FWD; + if (dir == PF_FWD) + dir = PF_OUT; + if (!V_pf_status.running) return (PF_PASS); diff --git a/freebsd/sys/netpfil/pf/pf_ioctl.c b/freebsd/sys/netpfil/pf/pf_ioctl.c index 076ed5f8..3cf3eec8 100644 --- a/freebsd/sys/netpfil/pf/pf_ioctl.c +++ b/freebsd/sys/netpfil/pf/pf_ioctl.c @@ -200,9 +200,11 @@ VNET_DEFINE(int, pf_vnet_active); #define V_pf_vnet_active VNET(pf_vnet_active) int pf_end_threads; +struct proc *pf_purge_proc; struct rwlock pf_rules_lock; struct sx pf_ioctl_lock; +struct sx pf_end_lock; /* pfsync */ pfsync_state_import_t *pfsync_state_import_ptr = NULL; @@ -3742,6 +3744,7 @@ pf_load(void) rw_init(&pf_rules_lock, "pf rulesets"); sx_init(&pf_ioctl_lock, "pf ioctl"); + sx_init(&pf_end_lock, "pf end thread"); pf_mtag_initialize(); @@ -3750,7 +3753,7 @@ pf_load(void) return (ENOMEM); pf_end_threads = 0; - error = kproc_create(pf_purge_thread, NULL, NULL, 0, 0, "pf purge"); + error = kproc_create(pf_purge_thread, NULL, &pf_purge_proc, 0, 0, "pf purge"); if (error != 0) return (error); @@ -3778,12 +3781,12 @@ pf_unload_vnet(void) return; } - pf_unload_vnet_purge(); - PF_RULES_WLOCK(); shutdown_pf(); PF_RULES_WUNLOCK(); + pf_unload_vnet_purge(); + pf_normalize_cleanup(); PF_RULES_WLOCK(); pfi_cleanup_vnet(); @@ -3800,11 +3803,13 @@ pf_unload(void) { int error = 0; + sx_xlock(&pf_end_lock); pf_end_threads = 1; while (pf_end_threads < 2) { wakeup_one(pf_purge_thread); - rw_sleep(pf_purge_thread, &pf_rules_lock, 0, "pftmo", 0); + sx_sleep(pf_purge_proc, &pf_end_lock, 0, "pftmo", 0); } + sx_xunlock(&pf_end_lock); if (pf_dev != NULL) destroy_dev(pf_dev); @@ -3813,6 +3818,7 @@ pf_unload(void) rw_destroy(&pf_rules_lock); sx_destroy(&pf_ioctl_lock); + sx_destroy(&pf_end_lock); return (error); } diff --git a/freebsd/sys/netpfil/pf/pf_lb.c b/freebsd/sys/netpfil/pf/pf_lb.c index 033c3879..3fe8dfb6 100644 --- a/freebsd/sys/netpfil/pf/pf_lb.c +++ b/freebsd/sys/netpfil/pf/pf_lb.c @@ -555,7 +555,7 @@ pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction, return (NULL); *nkp = pf_state_key_clone(*skp); if (*nkp == NULL) { - uma_zfree(V_pf_state_key_z, skp); + uma_zfree(V_pf_state_key_z, *skp); *skp = NULL; return (NULL); } diff --git a/freebsd/sys/netpfil/pf/pf_osfp.c b/freebsd/sys/netpfil/pf/pf_osfp.c index 33bef4c8..b6b51636 100644 --- a/freebsd/sys/netpfil/pf/pf_osfp.c +++ b/freebsd/sys/netpfil/pf/pf_osfp.c @@ -21,6 +21,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <rtems/bsd/local/opt_inet6.h> + #include <rtems/bsd/sys/param.h> #include <sys/kernel.h> #include <rtems/bsd/sys/lock.h> @@ -36,7 +38,9 @@ __FBSDID("$FreeBSD$"); #include <net/vnet.h> #include <net/pfvar.h> +#ifdef INET6 #include <netinet/ip6.h> +#endif static MALLOC_DEFINE(M_PFOSFP, "pf_osfp", "pf(4) operating system fingerprints"); #define DPFPRINTF(format, x...) \ @@ -96,7 +100,11 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st struct pf_os_fingerprint fp, *fpresult; int cnt, optlen = 0; const u_int8_t *optp; - char srcname[128]; +#ifdef INET6 + char srcname[INET6_ADDRSTRLEN]; +#else + char srcname[INET_ADDRSTRLEN]; +#endif if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN) return (NULL); @@ -112,7 +120,7 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st fp.fp_ttl = ip->ip_ttl; if (ip->ip_off & htons(IP_DF)) fp.fp_flags |= PF_OSFP_DF; - strlcpy(srcname, inet_ntoa(ip->ip_src), sizeof(srcname)); + inet_ntoa_r(ip->ip_src, srcname); } #ifdef INET6 else if (ip6) { @@ -121,8 +129,7 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const st fp.fp_ttl = ip6->ip6_hlim; fp.fp_flags |= PF_OSFP_DF; fp.fp_flags |= PF_OSFP_INET6; - strlcpy(srcname, ip6_sprintf((struct in6_addr *)&ip6->ip6_src), - sizeof(srcname)); + ip6_sprintf(srcname, (const struct in6_addr *)&ip6->ip6_src); } #endif else |