From owner-svn-src-all@freebsd.org Wed May 18 12:53:22 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E6E58B41322; Wed, 18 May 2016 12:53:22 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C32F71705; Wed, 18 May 2016 12:53:22 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4ICrMXo077046; Wed, 18 May 2016 12:53:22 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4ICrMMR077045; Wed, 18 May 2016 12:53:22 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201605181253.u4ICrMMR077045@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Wed, 18 May 2016 12:53:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r300143 - head/sys/netpfil/ipfw X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 18 May 2016 12:53:23 -0000 Author: ae Date: Wed May 18 12:53:21 2016 New Revision: 300143 URL: https://svnweb.freebsd.org/changeset/base/300143 Log: 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 Modified: head/sys/netpfil/ipfw/ip_fw_dynamic.c Modified: head/sys/netpfil/ipfw/ip_fw_dynamic.c ============================================================================== --- head/sys/netpfil/ipfw/ip_fw_dynamic.c Wed May 18 12:03:57 2016 (r300142) +++ head/sys/netpfil/ipfw/ip_fw_dynamic.c Wed May 18 12:53:21 2016 (r300143) @@ -319,77 +319,15 @@ print_dyn_rule_flags(struct ipfw_flow_id #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_ 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_ 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 *c 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 *c 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 *c 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 *c 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); }