summaryrefslogtreecommitdiffstats
path: root/sys/netpfil
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2016-05-18 12:53:21 +0000
committerae <ae@FreeBSD.org>2016-05-18 12:53:21 +0000
commit9d4244757ddf516b246ec5134bff023722354db7 (patch)
tree4030deb9a874d554304ac1931a3bda35b3a2dff3 /sys/netpfil
parent54336eef75323c51ab0b6399102309818fa3d988 (diff)
downloadFreeBSD-src-9d4244757ddf516b246ec5134bff023722354db7.zip
FreeBSD-src-9d4244757ddf516b246ec5134bff023722354db7.tar.gz
Move protocol state handling code from lookup_dyn_rule_locked() function
into dyn_update_proto_state(). This allows eliminate the second state lookup in the ipfw_install_state(). Also remove MATCH_* macros, they are defined in ip_fw_private.h as enum. Obtained from: Yandex LLC Sponsored by: Yandex LLC
Diffstat (limited to 'sys/netpfil')
-rw-r--r--sys/netpfil/ipfw/ip_fw_dynamic.c165
1 files changed, 86 insertions, 79 deletions
diff --git a/sys/netpfil/ipfw/ip_fw_dynamic.c b/sys/netpfil/ipfw/ip_fw_dynamic.c
index 991de22..23e950d 100644
--- a/sys/netpfil/ipfw/ip_fw_dynamic.c
+++ b/sys/netpfil/ipfw/ip_fw_dynamic.c
@@ -319,77 +319,15 @@ print_dyn_rule_flags(struct ipfw_flow_id *id, int dyn_type, int log_flags,
#define TIME_LEQ(a,b) ((int)((a)-(b)) <= 0)
#define TIME_LE(a,b) ((int)((a)-(b)) < 0)
-/*
- * Lookup a dynamic rule, locked version.
- */
-static ipfw_dyn_rule *
-lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int i, int *match_direction,
- struct tcphdr *tcp)
+static void
+dyn_update_proto_state(ipfw_dyn_rule *q, const struct ipfw_flow_id *id,
+ const struct tcphdr *tcp, int dir)
{
- /*
- * Stateful ipfw extensions.
- * Lookup into dynamic session queue.
- */
-#define MATCH_REVERSE 0
-#define MATCH_FORWARD 1
-#define MATCH_NONE 2
-#define MATCH_UNKNOWN 3
- int dir = MATCH_NONE;
- ipfw_dyn_rule *prev, *q = NULL;
-
- IPFW_BUCK_ASSERT(i);
-
- for (prev = NULL, q = V_ipfw_dyn_v[i].head; q; prev = q, q = q->next) {
- if (q->dyn_type == O_LIMIT_PARENT && q->count)
- continue;
-
- if (pkt->proto != q->id.proto || q->dyn_type == O_LIMIT_PARENT)
- continue;
-
- if (IS_IP6_FLOW_ID(pkt)) {
- if (IN6_ARE_ADDR_EQUAL(&pkt->src_ip6, &q->id.src_ip6) &&
- IN6_ARE_ADDR_EQUAL(&pkt->dst_ip6, &q->id.dst_ip6) &&
- pkt->src_port == q->id.src_port &&
- pkt->dst_port == q->id.dst_port) {
- dir = MATCH_FORWARD;
- break;
- }
- if (IN6_ARE_ADDR_EQUAL(&pkt->src_ip6, &q->id.dst_ip6) &&
- IN6_ARE_ADDR_EQUAL(&pkt->dst_ip6, &q->id.src_ip6) &&
- pkt->src_port == q->id.dst_port &&
- pkt->dst_port == q->id.src_port) {
- dir = MATCH_REVERSE;
- break;
- }
- } else {
- if (pkt->src_ip == q->id.src_ip &&
- pkt->dst_ip == q->id.dst_ip &&
- pkt->src_port == q->id.src_port &&
- pkt->dst_port == q->id.dst_port) {
- dir = MATCH_FORWARD;
- break;
- }
- if (pkt->src_ip == q->id.dst_ip &&
- pkt->dst_ip == q->id.src_ip &&
- pkt->src_port == q->id.dst_port &&
- pkt->dst_port == q->id.src_port) {
- dir = MATCH_REVERSE;
- break;
- }
- }
- }
- if (q == NULL)
- goto done; /* q = NULL, not found */
-
- if (prev != NULL) { /* found and not in front */
- prev->next = q->next;
- q->next = V_ipfw_dyn_v[i].head;
- V_ipfw_dyn_v[i].head = q;
- }
- if (pkt->proto == IPPROTO_TCP) { /* update state according to flags */
- uint32_t ack;
- u_char flags = pkt->_flags & (TH_FIN | TH_SYN | TH_RST);
+ uint32_t ack;
+ u_char flags;
+ if (id->proto == IPPROTO_TCP) {
+ flags = id->_flags & (TH_FIN | TH_SYN | TH_RST);
#define BOTH_SYN (TH_SYN | (TH_SYN << 8))
#define BOTH_FIN (TH_FIN | (TH_FIN << 8))
#define TCP_FLAGS (TH_FLAGS | (TH_FLAGS << 8))
@@ -432,7 +370,8 @@ lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int i, int *match_direction,
case BOTH_SYN | BOTH_FIN: /* both sides closed */
if (V_dyn_fin_lifetime >= V_dyn_keepalive_period)
- V_dyn_fin_lifetime = V_dyn_keepalive_period - 1;
+ V_dyn_fin_lifetime =
+ V_dyn_keepalive_period - 1;
q->expire = time_uptime + V_dyn_fin_lifetime;
break;
@@ -446,16 +385,86 @@ lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int i, int *match_direction,
printf("invalid state: 0x%x\n", q->state);
#endif
if (V_dyn_rst_lifetime >= V_dyn_keepalive_period)
- V_dyn_rst_lifetime = V_dyn_keepalive_period - 1;
+ V_dyn_rst_lifetime =
+ V_dyn_keepalive_period - 1;
q->expire = time_uptime + V_dyn_rst_lifetime;
break;
}
- } else if (pkt->proto == IPPROTO_UDP) {
+ } else if (id->proto == IPPROTO_UDP) {
q->expire = time_uptime + V_dyn_udp_lifetime;
} else {
/* other protocols */
q->expire = time_uptime + V_dyn_short_lifetime;
}
+}
+
+/*
+ * Lookup a dynamic rule, locked version.
+ */
+static ipfw_dyn_rule *
+lookup_dyn_rule_locked(struct ipfw_flow_id *pkt, int i, int *match_direction,
+ struct tcphdr *tcp)
+{
+ /*
+ * Stateful ipfw extensions.
+ * Lookup into dynamic session queue.
+ */
+ ipfw_dyn_rule *prev, *q = NULL;
+ int dir;
+
+ IPFW_BUCK_ASSERT(i);
+
+ dir = MATCH_NONE;
+ for (prev = NULL, q = V_ipfw_dyn_v[i].head; q; prev = q, q = q->next) {
+ if (q->dyn_type == O_LIMIT_PARENT && q->count)
+ continue;
+
+ if (pkt->proto != q->id.proto || q->dyn_type == O_LIMIT_PARENT)
+ continue;
+
+ if (IS_IP6_FLOW_ID(pkt)) {
+ if (IN6_ARE_ADDR_EQUAL(&pkt->src_ip6, &q->id.src_ip6) &&
+ IN6_ARE_ADDR_EQUAL(&pkt->dst_ip6, &q->id.dst_ip6) &&
+ pkt->src_port == q->id.src_port &&
+ pkt->dst_port == q->id.dst_port) {
+ dir = MATCH_FORWARD;
+ break;
+ }
+ if (IN6_ARE_ADDR_EQUAL(&pkt->src_ip6, &q->id.dst_ip6) &&
+ IN6_ARE_ADDR_EQUAL(&pkt->dst_ip6, &q->id.src_ip6) &&
+ pkt->src_port == q->id.dst_port &&
+ pkt->dst_port == q->id.src_port) {
+ dir = MATCH_REVERSE;
+ break;
+ }
+ } else {
+ if (pkt->src_ip == q->id.src_ip &&
+ pkt->dst_ip == q->id.dst_ip &&
+ pkt->src_port == q->id.src_port &&
+ pkt->dst_port == q->id.dst_port) {
+ dir = MATCH_FORWARD;
+ break;
+ }
+ if (pkt->src_ip == q->id.dst_ip &&
+ pkt->dst_ip == q->id.src_ip &&
+ pkt->src_port == q->id.dst_port &&
+ pkt->dst_port == q->id.src_port) {
+ dir = MATCH_REVERSE;
+ break;
+ }
+ }
+ }
+ if (q == NULL)
+ goto done; /* q = NULL, not found */
+
+ if (prev != NULL) { /* found and not in front */
+ prev->next = q->next;
+ q->next = V_ipfw_dyn_v[i].head;
+ V_ipfw_dyn_v[i].head = q;
+ }
+
+ /* update state according to flags */
+ dyn_update_proto_state(q, pkt, tcp, dir);
done:
if (match_direction != NULL)
*match_direction = dir;
@@ -678,7 +687,7 @@ ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
ipfw_insn_limit *cmd, struct ip_fw_args *args, uint32_t tablearg)
{
ipfw_dyn_rule *q;
- int i;
+ int i, dir;
DEB(print_dyn_rule(&args->f_id, cmd->o.opcode, "install_state", "");)
@@ -686,8 +695,7 @@ ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
IPFW_BUCK_LOCK(i);
- q = lookup_dyn_rule_locked(&args->f_id, i, NULL, NULL);
-
+ q = lookup_dyn_rule_locked(&args->f_id, i, &dir, NULL);
if (q != NULL) { /* should never occur */
DEB(
if (last_log != time_uptime) {
@@ -786,7 +794,8 @@ ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
IPFW_BUCK_UNLOCK(pindex);
IPFW_BUCK_LOCK(i);
- q = add_dyn_rule(&args->f_id, i, O_LIMIT, (struct ip_fw *)parent);
+ q = add_dyn_rule(&args->f_id, i, O_LIMIT,
+ (struct ip_fw *)parent);
if (q == NULL) {
/* Decrement index and notify caller */
IPFW_BUCK_UNLOCK(i);
@@ -807,9 +816,7 @@ ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
return (1); /* Notify caller about failure */
}
- /* XXX just set lifetime */
- lookup_dyn_rule_locked(&args->f_id, i, NULL, NULL);
-
+ dyn_update_proto_state(q, &args->f_id, NULL, dir);
IPFW_BUCK_UNLOCK(i);
return (0);
}
OpenPOWER on IntegriCloud