From owner-svn-src-head@freebsd.org Sun Mar 5 23:48:25 2017 Return-Path: Delivered-To: svn-src-head@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 C2E1FCFBF91; Sun, 5 Mar 2017 23:48:25 +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 818E914B3; Sun, 5 Mar 2017 23:48:25 +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 v25NmOPc032566; Sun, 5 Mar 2017 23:48:24 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v25NmOI1032562; Sun, 5 Mar 2017 23:48:24 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201703052348.v25NmOI1032562@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Sun, 5 Mar 2017 23:48:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r314716 - 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-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 05 Mar 2017 23:48:25 -0000 Author: ae Date: Sun Mar 5 23:48:24 2017 New Revision: 314716 URL: https://svnweb.freebsd.org/changeset/base/314716 Log: Add IPv6 support to O_IP_DST_LOOKUP opcode. o check the size of O_IP_SRC_LOOKUP opcode, it can not exceed the size of ipfw_insn_u32; o rename ipfw_lookup_table_extended() function into ipfw_lookup_table() and remove old ipfw_lookup_table(); o use args->f_id.flow_id6 that is in host byte order to get DSCP value; o add SCTP ports support to 'lookup src/dst-port' opcode; o add IPv6 support to 'lookup src/dst-ip' opcode. PR: 217292 Reviewed by: melifaro MFC after: 2 weeks Sponsored by: Yandex LLC Differential Revision: https://reviews.freebsd.org/D9873 Modified: head/sys/netpfil/ipfw/ip_fw2.c head/sys/netpfil/ipfw/ip_fw_private.h head/sys/netpfil/ipfw/ip_fw_sockopt.c head/sys/netpfil/ipfw/ip_fw_table.c Modified: head/sys/netpfil/ipfw/ip_fw2.c ============================================================================== --- head/sys/netpfil/ipfw/ip_fw2.c Sun Mar 5 22:19:43 2017 (r314715) +++ head/sys/netpfil/ipfw/ip_fw2.c Sun Mar 5 23:48:24 2017 (r314716) @@ -382,8 +382,8 @@ iface_match(struct ifnet *ifp, ipfw_insn /* 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) @@ -1455,86 +1455,130 @@ 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 */) - key = ucred_cache->cr_uid; - else if (v == 5 /* O_JAIL */) - key = ucred_cache->cr_prison->pr_id; + &ucred_cache); + if (vidx == 4 /* uid */) + key = ucred_cache->cr_uid; + else if (vidx == 5 /* jail */) + key = ucred_cache->cr_prison->pr_id; #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] == - TARG_VAL(chain, v, tag); - 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] == - TARG_VAL(chain, v, tag); - 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] == Modified: head/sys/netpfil/ipfw/ip_fw_private.h ============================================================================== --- head/sys/netpfil/ipfw/ip_fw_private.h Sun Mar 5 22:19:43 2017 (r314715) +++ head/sys/netpfil/ipfw/ip_fw_private.h Sun Mar 5 23:48:24 2017 (r314716) @@ -741,10 +741,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); Modified: head/sys/netpfil/ipfw/ip_fw_sockopt.c ============================================================================== --- head/sys/netpfil/ipfw/ip_fw_sockopt.c Sun Mar 5 22:19:43 2017 (r314715) +++ head/sys/netpfil/ipfw/ip_fw_sockopt.c Sun Mar 5 23:48:24 2017 (r314716) @@ -1826,6 +1826,8 @@ check_ipfw_rule_body(ipfw_insn *cmd, int 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", Modified: head/sys/netpfil/ipfw/ip_fw_table.c ============================================================================== --- head/sys/netpfil/ipfw/ip_fw_table.c Sun Mar 5 22:19:43 2017 (r314715) +++ head/sys/netpfil/ipfw/ip_fw_table.c Sun Mar 5 23:48:24 2017 (r314716) @@ -1657,30 +1657,13 @@ ipfw_unref_table(struct ip_fw_chain *ch, } /* - * 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;