diff options
author | ae <ae@FreeBSD.org> | 2016-05-18 12:53:21 +0000 |
---|---|---|
committer | ae <ae@FreeBSD.org> | 2016-05-18 12:53:21 +0000 |
commit | 9d4244757ddf516b246ec5134bff023722354db7 (patch) | |
tree | 4030deb9a874d554304ac1931a3bda35b3a2dff3 /sys/netpfil | |
parent | 54336eef75323c51ab0b6399102309818fa3d988 (diff) | |
download | FreeBSD-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.c | 165 |
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); } |