From owner-svn-src-projects@FreeBSD.ORG Tue Aug 12 15:51:50 2014 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id D8F925B4 for ; Tue, 12 Aug 2014 15:51:50 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C71A122A8 for ; Tue, 12 Aug 2014 15:51:50 +0000 (UTC) Received: from melifaro (uid 1268) (envelope-from melifaro@FreeBSD.org) id 6a8f by svn.freebsd.org (DragonFly Mail Agent v0.9+); Tue, 12 Aug 2014 15:51:49 +0000 From: Alexander V. Chernikov Date: Tue, 12 Aug 2014 15:51:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r269880 - in projects/ipfw: sbin/ipfw sys/netinet sys/netpfil/ipfw X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <53ea3815.6a8f.771861e@svn.freebsd.org> X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Aug 2014 15:51:50 -0000 Author: melifaro Date: Tue Aug 12 15:51:48 2014 New Revision: 269880 URL: http://svnweb.freebsd.org/changeset/base/269880 Log: Change tablearg value to be 0 (try #2). Most of the tablearg-supported opcodes does not accept 0 as valid value: O_TAG, O_TAGGED, O_PIPE, O_QUEUE, O_DIVERT, O_TEE, O_SKIPTO, O_CALLRET, O_NETGRAPH, O_NGTEE, O_NAT treats 0 as invalid input. The rest are O_SETDSCP and O_SETFIB. 'Fix' them by adding high-order bit (0x8000) set for non-tablearg values. Do translation in kernel for old clients (import_rule0 / export_rule0), teach current ipfw(8) binary to add/remove given bit. This change does not affect handling SETDSCP values, but limit O_SETFIB values to 32767 instead of 65k. Since currently we have either old (16) or new (2^32) max fibs, this should not be a big deal: we're definitely OK for former and have to add another opcode to deal with latter, regardless of tablearg value. Modified: projects/ipfw/sbin/ipfw/ipfw2.c projects/ipfw/sbin/ipfw/ipfw2.h projects/ipfw/sys/netinet/ip_fw.h projects/ipfw/sys/netpfil/ipfw/ip_fw2.c projects/ipfw/sys/netpfil/ipfw/ip_fw_dynamic.c projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Modified: projects/ipfw/sbin/ipfw/ipfw2.c ============================================================================== --- projects/ipfw/sbin/ipfw/ipfw2.c Tue Aug 12 14:53:02 2014 (r269879) +++ projects/ipfw/sbin/ipfw/ipfw2.c Tue Aug 12 15:51:48 2014 (r269880) @@ -93,7 +93,7 @@ int ipfw_socket = -1; if (!av[0]) \ errx(EX_USAGE, "%s: missing argument", match_value(s_x, tok)); \ if (_substrcmp(*av, "tablearg") == 0) { \ - arg = IP_FW_TABLEARG; \ + arg = IP_FW_TARG; \ break; \ } \ \ @@ -111,7 +111,7 @@ int ipfw_socket = -1; errx(EX_DATAERR, "%s: argument is out of range (%u..%u): %s", \ match_value(s_x, tok), min, max, *av); \ \ - if (_xval == IP_FW_TABLEARG) \ + if (_xval == IP_FW_TARG) \ errx(EX_DATAERR, "%s: illegal argument value: %s", \ match_value(s_x, tok), *av); \ arg = _xval; \ @@ -123,7 +123,7 @@ PRINT_UINT_ARG(const char *str, uint32_t { if (str != NULL) printf("%s",str); - if (arg == IP_FW_TABLEARG) + if (arg == IP_FW_TARG) printf("tablearg"); else printf("%u", arg); @@ -469,7 +469,7 @@ bprint_uint_arg(struct buf_pr *bp, const if (str != NULL) bprintf(bp, "%s", str); - if (arg == IP_FW_TABLEARG) + if (arg == IP_FW_TARG) bprintf(bp, "tablearg"); else bprintf(bp, "%u", arg); @@ -1386,6 +1386,7 @@ show_static_rule(struct cmdline_opts *co ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */ ipfw_insn_altq *altqptr = NULL; /* set if we find an O_ALTQ */ int or_block = 0; /* we are in an or block */ + uint32_t uval; if ((fo->set_mask & (1 << rule->set)) == 0) { /* disabled mask */ @@ -1556,17 +1557,22 @@ show_static_rule(struct cmdline_opts *co break; case O_SETFIB: - bprint_uint_arg(bp, "setfib ", cmd->arg1); + bprint_uint_arg(bp, "setfib ", cmd->arg1 & 0x7FFF); break; case O_SETDSCP: { const char *code; - if ((code = match_value(f_ipdscp, cmd->arg1)) != NULL) + if (cmd->arg1 == IP_FW_TARG) { + bprint_uint_arg(bp, "setdscp ", cmd->arg1); + break; + } + uval = cmd->arg1 & 0x3F; + if ((code = match_value(f_ipdscp, uval)) != NULL) bprintf(bp, "setdscp %s", code); else - bprint_uint_arg(bp, "setdscp ", cmd->arg1); + bprint_uint_arg(bp, "setdscp ", uval); } break; @@ -3597,11 +3603,11 @@ chkarg: errx(EX_USAGE, "missing argument for %s", *(av - 1)); if (isdigit(**av)) { action->arg1 = strtoul(*av, NULL, 10); - if (action->arg1 <= 0 || action->arg1 >= IP_FW_TABLEARG) + if (action->arg1 <= 0 || action->arg1 >= IP_FW_TARG) errx(EX_DATAERR, "illegal argument for %s", *(av - 1)); } else if (_substrcmp(*av, "tablearg") == 0) { - action->arg1 = IP_FW_TABLEARG; + action->arg1 = IP_FW_TARG; } else if (i == TOK_DIVERT || i == TOK_TEE) { struct servent *s; setservent(1); @@ -3725,7 +3731,7 @@ chkarg: action->opcode = O_SETFIB; NEED1("missing fib number"); if (_substrcmp(*av, "tablearg") == 0) { - action->arg1 = IP_FW_TABLEARG; + action->arg1 = IP_FW_TARG; } else { action->arg1 = strtoul(*av, NULL, 10); if (sysctlbyname("net.fibs", &numfibs, &intsize, @@ -3733,6 +3739,8 @@ chkarg: errx(EX_DATAERR, "fibs not suported.\n"); if (action->arg1 >= numfibs) /* Temporary */ errx(EX_DATAERR, "fib too large.\n"); + /* Add high-order bit to fib to make room for tablearg*/ + action->arg1 |= 0x8000; } av++; break; @@ -3745,13 +3753,16 @@ chkarg: action->opcode = O_SETDSCP; NEED1("missing DSCP code"); if (_substrcmp(*av, "tablearg") == 0) { - action->arg1 = IP_FW_TABLEARG; + action->arg1 = IP_FW_TARG; } else if (isalpha(*av[0])) { if ((code = match_token(f_ipdscp, *av)) == -1) errx(EX_DATAERR, "Unknown DSCP code"); action->arg1 = code; } else action->arg1 = strtoul(*av, NULL, 10); + /* Add high-order bit to DSCP to make room for tablearg */ + if (action->arg1 != IP_FW_TARG) + action->arg1 |= 0x8000; av++; break; } Modified: projects/ipfw/sbin/ipfw/ipfw2.h ============================================================================== --- projects/ipfw/sbin/ipfw/ipfw2.h Tue Aug 12 14:53:02 2014 (r269879) +++ projects/ipfw/sbin/ipfw/ipfw2.h Tue Aug 12 15:51:48 2014 (r269880) @@ -228,6 +228,7 @@ enum tokens { TOK_LOCK, TOK_UNLOCK, }; + /* * the following macro returns an error message if we run out of * arguments. Modified: projects/ipfw/sys/netinet/ip_fw.h ============================================================================== --- projects/ipfw/sys/netinet/ip_fw.h Tue Aug 12 14:53:02 2014 (r269879) +++ projects/ipfw/sys/netinet/ip_fw.h Tue Aug 12 15:51:48 2014 (r269880) @@ -47,18 +47,17 @@ /* * Most commands (queue, pipe, tag, untag, limit...) can have a 16-bit - * argument between 1 and 65534. The value 0 is unused, the value - * 65535 (IP_FW_TABLEARG) is used to represent 'tablearg', i.e. the - * can be 1..65534, or 65535 to indicate the use of a 'tablearg' + * argument between 1 and 65534. The value 0 (IP_FW_TARG) is used + * to represent 'tablearg' value, e.g. indicate the use of a 'tablearg' * result of the most recent table() lookup. * Note that 16bit is only a historical limit, resulting from * the use of a 16-bit fields for that value. In reality, we can have - * 2^32 pipes, queues, tag values and so on, and use 0 as a tablearg. - * Note there are some opcodes where value 0 is perfectly valid (fib, dscp). + * 2^32 pipes, queues, tag values and so on. */ #define IPFW_ARG_MIN 1 #define IPFW_ARG_MAX 65534 -#define IP_FW_TABLEARG 65535 +#define IP_FW_TABLEARG 65535 /* Compat value for old clients */ +#define IP_FW_TARG 0 /* Current tablearg value */ /* * Number of entries in the call stack of the call/return commands. Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw2.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw2.c Tue Aug 12 14:53:02 2014 (r269879) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw2.c Tue Aug 12 15:51:48 2014 (r269880) @@ -810,7 +810,7 @@ jump_fast(struct ip_fw_chain *chain, str * whose version is written in f->next_rule * (horrible hacks to avoid changing the ABI). */ - if (num != IP_FW_TABLEARG && f->cached_id == chain->id) + if (num != IP_FW_TARG && f->cached_id == chain->id) f_pos = f->cached_pos; else { int i = IP_FW_ARG_TABLEARG(num); @@ -822,7 +822,7 @@ jump_fast(struct ip_fw_chain *chain, str else f_pos = ipfw_find_rule(chain, i, 0); /* update the cache */ - if (num != IP_FW_TABLEARG) { + if (num != IP_FW_TARG) { f->cached_id = chain->id; f->cached_pos = f_pos; } @@ -2400,7 +2400,7 @@ do { \ uint32_t fib; IPFW_INC_RULE_COUNTER(f, pktlen); - fib = IP_FW_ARG_TABLEARG(cmd->arg1); + fib = IP_FW_ARG_TABLEARG(cmd->arg1) & 0x7FFFF; if (fib >= rt_numfibs) fib = 0; M_SETFIB(m, fib); @@ -2461,7 +2461,7 @@ do { \ retval = IP_FW_DENY; break; } - if (cmd->arg1 != IP_FW_TABLEARG) + if (cmd->arg1 != IP_FW_TARG) ((ipfw_insn_nat *)cmd)->nat = t; } retval = ipfw_nat_ptr(args, t, m); Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_dynamic.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_dynamic.c Tue Aug 12 14:53:02 2014 (r269879) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_dynamic.c Tue Aug 12 15:51:48 2014 (r269880) @@ -719,7 +719,7 @@ ipfw_install_state(struct ip_fw *rule, i conn_limit = IP_FW_ARG_TABLEARG(cmd->conn_limit); DEB( - if (cmd->conn_limit == IP_FW_TABLEARG) + if (cmd->conn_limit == IP_FW_TARG) printf("ipfw: %s: O_LIMIT rule, conn_limit: %u " "(tablearg)\n", __func__, conn_limit); else Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h Tue Aug 12 14:53:02 2014 (r269879) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h Tue Aug 12 15:51:48 2014 (r269880) @@ -384,7 +384,7 @@ struct ipfw_ifc { #endif -#define IP_FW_ARG_TABLEARG(a) (((a) == IP_FW_TABLEARG) ? tablearg : (a)) +#define IP_FW_ARG_TABLEARG(a) (((a) == IP_FW_TARG) ? tablearg : (a)) /* * The lock is heavily used by ip_fw2.c (the main file) and ip_fw_nat.c * so the variable and the macros must be here. Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Tue Aug 12 14:53:02 2014 (r269879) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Tue Aug 12 15:51:48 2014 (r269880) @@ -375,7 +375,7 @@ export_cntr0_base(struct ip_fw *krule, s } /* - * Copies rule @urule from v1 userland format + * Copies rule @urule from v1 userland format (current). * to kernel @krule. * Assume @krule is zeroed. */ @@ -456,6 +456,7 @@ import_rule0(struct rule_check_info *ci) struct ip_fw *krule; int cmdlen, l; ipfw_insn *cmd; + ipfw_insn_limit *lcmd; ipfw_insn_if *cmdif; urule = (struct ip_fw_rule0 *)ci->urule; @@ -477,36 +478,69 @@ import_rule0(struct rule_check_info *ci) /* * Alter opcodes: - * 1) convert table number in iface opcodes to u16 + * 1) convert tablearg value from 65335 to 0 + * 2) Add high bit to O_SETFIB/O_SETDSCP values (to make room for targ). + * 3) convert table number in iface opcodes to u16 */ - l = urule->cmd_len; - cmd = urule->cmd; + l = krule->cmd_len; + cmd = krule->cmd; cmdlen = 0; - for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { - cmdlen = F_LEN(cmd); + for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { + cmdlen = F_LEN(cmd); + + switch (cmd->opcode) { + /* Opcodes supporting tablearg */ + case O_TAG: + case O_TAGGED: + case O_PIPE: + case O_QUEUE: + case O_DIVERT: + case O_TEE: + case O_SKIPTO: + case O_CALLRETURN: + case O_NETGRAPH: + case O_NGTEE: + case O_NAT: + if (cmd->arg1 == 65535) + cmd->arg1 = IP_FW_TARG; + break; + case O_SETFIB: + case O_SETDSCP: + if (cmd->arg1 == 65535) + cmd->arg1 = IP_FW_TARG; + else + cmd->arg1 |= 0x8000; + break; + case O_LIMIT: + lcmd = (ipfw_insn_limit *)cmd; + if (lcmd->conn_limit == 65535) + lcmd->conn_limit = IP_FW_TARG; + break; + /* Interface tables */ + case O_XMIT: + case O_RECV: + case O_VIA: + /* Interface table, possibly */ + cmdif = (ipfw_insn_if *)cmd; + if (cmdif->name[0] != '\1') + break; - switch (cmd->opcode) { - /* Interface tables */ - case O_XMIT: - case O_RECV: - case O_VIA: - /* Interface table, possibly */ - cmdif = (ipfw_insn_if *)cmd; - if (cmdif->name[0] != '\1') - break; - - cmdif->p.kidx = cmdif->p.glob; - break; - } + cmdif->p.kidx = (uint16_t)cmdif->p.glob; + break; + } } } +/* + * Copies rule @krule from kernel to FreeBSD8 userland format (v0) + */ static void export_rule0(struct ip_fw *krule, struct ip_fw_rule0 *urule, int len) { int cmdlen, l; ipfw_insn *cmd; + ipfw_insn_limit *lcmd; ipfw_insn_if *cmdif; /* copy header */ @@ -526,28 +560,57 @@ export_rule0(struct ip_fw *krule, struct /* * Alter opcodes: - * 1) convert table number in iface opcodes to int + * 1) convert tablearg value from 0 to 65335 + * 2) Remove highest bit from O_SETFIB/O_SETDSCP values. + * 3) convert table number in iface opcodes to int */ l = urule->cmd_len; cmd = urule->cmd; cmdlen = 0; - for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { - cmdlen = F_LEN(cmd); + for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { + cmdlen = F_LEN(cmd); - switch (cmd->opcode) { - /* Interface tables */ - case O_XMIT: - case O_RECV: - case O_VIA: - /* Interface table, possibly */ - cmdif = (ipfw_insn_if *)cmd; - if (cmdif->name[0] != '\1') - break; - - cmdif->p.glob = cmdif->p.kidx; - break; - } + switch (cmd->opcode) { + /* Opcodes supporting tablearg */ + case O_TAG: + case O_TAGGED: + case O_PIPE: + case O_QUEUE: + case O_DIVERT: + case O_TEE: + case O_SKIPTO: + case O_CALLRETURN: + case O_NETGRAPH: + case O_NGTEE: + case O_NAT: + if (cmd->arg1 == IP_FW_TARG) + cmd->arg1 = 65535; + break; + case O_SETFIB: + case O_SETDSCP: + if (cmd->arg1 == IP_FW_TARG) + cmd->arg1 = 65535; + else + cmd->arg1 &= ~0x8000; + break; + case O_LIMIT: + lcmd = (ipfw_insn_limit *)cmd; + if (lcmd->conn_limit == IP_FW_TARG) + lcmd->conn_limit = 65535; + break; + /* Interface tables */ + case O_XMIT: + case O_RECV: + case O_VIA: + /* Interface table, possibly */ + cmdif = (ipfw_insn_if *)cmd; + if (cmdif->name[0] != '\1') + break; + + cmdif->p.glob = cmdif->p.kidx; + break; + } } } @@ -1391,10 +1454,10 @@ check_ipfw_rule_body(ipfw_insn *cmd, int case O_SETFIB: if (cmdlen != F_INSN_SIZE(ipfw_insn)) goto bad_size; - if ((cmd->arg1 != IP_FW_TABLEARG) && - (cmd->arg1 >= rt_numfibs)) { + if ((cmd->arg1 != IP_FW_TARG) && + ((cmd->arg1 & 0x7FFFF) >= rt_numfibs)) { printf("ipfw: invalid fib number %d\n", - cmd->arg1); + cmd->arg1 & 0x7FFFF); return EINVAL; } goto check_action; Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Tue Aug 12 14:53:02 2014 (r269879) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Tue Aug 12 15:51:48 2014 (r269880) @@ -2482,7 +2482,7 @@ classify_table_opcode(ipfw_insn *cmd, ui break; *ptype = IPFW_TABLE_INTERFACE; - *puidx = cmdif->p.glob; + *puidx = cmdif->p.kidx; skip = 0; break; case O_IP_FLOW_LOOKUP: @@ -2515,7 +2515,7 @@ update_table_opcode(ipfw_insn *cmd, uint case O_VIA: /* Interface table, possibly */ cmdif = (ipfw_insn_if *)cmd; - cmdif->p.glob = idx; + cmdif->p.kidx = idx; break; case O_IP_FLOW_LOOKUP: cmd->arg1 = idx;