From owner-svn-src-head@FreeBSD.ORG Tue Dec 15 09:46:28 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 134361065676; Tue, 15 Dec 2009 09:46:28 +0000 (UTC) (envelope-from luigi@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 0255E8FC15; Tue, 15 Dec 2009 09:46:28 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nBF9kRU3056944; Tue, 15 Dec 2009 09:46:27 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nBF9kRHE056939; Tue, 15 Dec 2009 09:46:27 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <200912150946.nBF9kRHE056939@svn.freebsd.org> From: Luigi Rizzo Date: Tue, 15 Dec 2009 09:46:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r200567 - in head: sbin/ipfw sys/netinet/ipfw X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 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: Tue, 15 Dec 2009 09:46:28 -0000 Author: luigi Date: Tue Dec 15 09:46:27 2009 New Revision: 200567 URL: http://svn.freebsd.org/changeset/base/200567 Log: implement a new match option, lookup {dst-ip|src-ip|dst-port|src-port|uid|jail} N which searches the specified field in table N and sets tablearg accordingly. With dst-ip or src-ip the option replicates two existing options. When used with other arguments, the option can be useful to quickly dispatch traffic based on other fields. Work supported by the Onelab project. MFC after: 1 week Modified: head/sbin/ipfw/ipfw.8 head/sbin/ipfw/ipfw2.c head/sbin/ipfw/ipfw2.h head/sys/netinet/ipfw/ip_fw2.c Modified: head/sbin/ipfw/ipfw.8 ============================================================================== --- head/sbin/ipfw/ipfw.8 Tue Dec 15 09:32:35 2009 (r200566) +++ head/sbin/ipfw/ipfw.8 Tue Dec 15 09:46:27 2009 (r200567) @@ -1391,6 +1391,20 @@ of source and destination addresses and specified. Currently, only IPv4 flows are supported. +.It Cm lookup Bro Cm dst-ip | dst-port | src-ip | src-port | uid | jail Brc Ar N +Search an entry in lookup table +.Ar N +that matches the field specified as argument. +If not found, the match fails. +Otherwise, the match succeeds and +.Cm tablearg +is set to the value extracted from the table. +.Br +This option can be useful to quickly dispatch traffic based on +certain packet fields. +See the +.Sx LOOKUP TABLES +section below for more information on lookup tables. .It Cm { MAC | mac } Ar dst-mac src-mac Match packets with a given .Ar dst-mac Modified: head/sbin/ipfw/ipfw2.c ============================================================================== --- head/sbin/ipfw/ipfw2.c Tue Dec 15 09:32:35 2009 (r200566) +++ head/sbin/ipfw/ipfw2.c Tue Dec 15 09:46:27 2009 (r200567) @@ -224,6 +224,15 @@ static struct _s_x rule_action_params[] { NULL, 0 } /* terminator */ }; +/* + * The 'lookup' instruction accepts one of the following arguments. + * -1 is a terminator for the list. + * Arguments are passed as v[1] in O_DST_LOOKUP options. + */ +static int lookup_key[] = { + TOK_DSTIP, TOK_SRCIP, TOK_DSTPORT, TOK_SRCPORT, + TOK_UID, TOK_JAIL, -1 }; + static struct _s_x rule_options[] = { { "tagged", TOK_TAGGED }, { "uid", TOK_UID }, @@ -290,6 +299,7 @@ static struct _s_x rule_options[] = { { "dst-ip6", TOK_DSTIP6}, { "src-ipv6", TOK_SRCIP6}, { "src-ip6", TOK_SRCIP6}, + { "lookup", TOK_LOOKUP}, { "//", TOK_COMMENT }, { "not", TOK_NOT }, /* pseudo option */ @@ -742,6 +752,16 @@ print_ip(ipfw_insn_ip *cmd, char const * int len = F_LEN((ipfw_insn *)cmd); uint32_t *a = ((ipfw_insn_u32 *)cmd)->d; + if (cmd->o.opcode == O_IP_DST_LOOKUP && len > F_INSN_SIZE(ipfw_insn_u32)) { + uint32_t d = a[1]; + const char *arg = ""; + + if (d < sizeof(lookup_key)/sizeof(lookup_key[0])) + arg = match_value(rule_options, lookup_key[d]); + printf("%s lookup %s %d", cmd->o.len & F_NOT ? " not": "", + arg, cmd->o.arg1); + return; + } printf("%s%s ", cmd->o.len & F_NOT ? " not": "", s); if (cmd->o.opcode == O_IP_SRC_ME || cmd->o.opcode == O_IP_DST_ME) { @@ -3479,6 +3499,31 @@ read_options: ac--; av++; break; + case TOK_LOOKUP: { + ipfw_insn_u32 *c = (ipfw_insn_u32 *)cmd; + char *p; + int j; + + if (ac < 2) + errx(EX_USAGE, "format: lookup argument tablenum"); + cmd->opcode = O_IP_DST_LOOKUP; + cmd->len |= F_INSN_SIZE(ipfw_insn) + 2; + i = match_token(rule_options, *av); + for (j = 0; lookup_key[j] >= 0 ; j++) { + if (i == lookup_key[j]) + break; + } + if (lookup_key[j] <= 0) + errx(EX_USAGE, "format: cannot lookup on %s", *av); + c->d[1] = j; // i converted to option + ac--; av++; + cmd->arg1 = strtoul(*av, &p, 0); + if (p && *p) + errx(EX_USAGE, "format: lookup argument tablenum"); + ac--; av++; + } + break; + default: errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s); } Modified: head/sbin/ipfw/ipfw2.h ============================================================================== --- head/sbin/ipfw/ipfw2.h Tue Dec 15 09:32:35 2009 (r200566) +++ head/sbin/ipfw/ipfw2.h Tue Dec 15 09:46:27 2009 (r200567) @@ -186,6 +186,7 @@ enum tokens { TOK_FIB, TOK_SETFIB, + TOK_LOOKUP, }; /* * the following macro returns an error message if we run out of Modified: head/sys/netinet/ipfw/ip_fw2.c ============================================================================== --- head/sys/netinet/ipfw/ip_fw2.c Tue Dec 15 09:32:35 2009 (r200566) +++ head/sys/netinet/ipfw/ip_fw2.c Tue Dec 15 09:46:27 2009 (r200567) @@ -2819,6 +2819,36 @@ do { \ dst_ip.s_addr : src_ip.s_addr; uint32_t v = 0; + if (cmdlen > F_INSN_SIZE(ipfw_insn_u32)) { + /* generic lookup */ + v = ((ipfw_insn_u32 *)cmd)->d[1]; + if (v == 0) + a = dst_ip.s_addr; + else if (v == 1) + a = src_ip.s_addr; + else if (offset != 0) + break; + else if (proto != IPPROTO_TCP && + proto != IPPROTO_UDP) + break; + else if (v == 2) + a = dst_port; + else if (v == 3) + a = src_port; + else if (v == 4 || v == 5) { + check_uidgid( + (ipfw_insn_u32 *)cmd, + proto, oif, + dst_ip, dst_port, + src_ip, src_port, &ucred_cache, + &ucred_lookup, args->inp); + if (v == 4 /* O_UID */) + a = ucred_cache->cr_uid; + else if (v == 5 /* O_JAIL */) + a = ucred_cache->cr_prison->pr_id; + } else + break; + } match = lookup_table(chain, cmd->arg1, a, &v); if (!match) @@ -4160,6 +4190,7 @@ check_ipfw_struct(struct ip_fw *rule, in return (EINVAL); } if (cmdlen != F_INSN_SIZE(ipfw_insn) && + cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 1 && cmdlen != F_INSN_SIZE(ipfw_insn_u32)) goto bad_size; break;