From patchwork Wed Mar 7 09:10:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serhey Popovych X-Patchwork-Id: 882482 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="K8rbk58Y"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zx7Cw6WFHz9sfK for ; Wed, 7 Mar 2018 20:10:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751130AbeCGJKw (ORCPT ); Wed, 7 Mar 2018 04:10:52 -0500 Received: from mail-lf0-f68.google.com ([209.85.215.68]:38865 "EHLO mail-lf0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751036AbeCGJKv (ORCPT ); Wed, 7 Mar 2018 04:10:51 -0500 Received: by mail-lf0-f68.google.com with SMTP id i80-v6so2142633lfg.5 for ; Wed, 07 Mar 2018 01:10:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=9W8YrDed7Wi9msIt0RA56U5Zl3YoL4PbWFGekO4pfQM=; b=K8rbk58YcMhtbI1UyonqK6Xekf7qGVGEMMfKSc5IsCavJrwR6bh2IuqvkXPXlZqQXy TLMz3KHWpfhw/DvRrgi/1e7IuitfSGA368p2QSI3M7mhbW7CYhVRTch+Alfb/CUKR5mp GefU7oZFjvigr8kj38Y0NW4MQKt7PVkjfAqwPwreXyc8u0qvQ6TVa8qrkNsesOVWz1qC fjz/lyLOZxB4q5Ln5TEKapHkAP5M35Ypg0v/YIh2SJynjJyQNwVpIJ3Sg6hqnsT+r9hn hRVDdgz5fHEkfdydrq7u0N5mOi7JLytkrYhQHp5HoMuOqltK7bJYc66IJE/P1uOFPRzU zqFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=9W8YrDed7Wi9msIt0RA56U5Zl3YoL4PbWFGekO4pfQM=; b=RcuWOcVUkWFPV8mRvgcNwWIOLhSZvfhIsunaOEoozJlwlI80gixRCIS1WT75cSckUi B7aCUwk+tKraej5CKZCcr6UkDlSLDdmM8UBFkXkffPswF9thOWBvP5xTpcD5U2orRRnF ma0t6jpiPydCq1bDcg0vDxHNxuOGhxuFL8k1qfu+yAvzUgD4wdcMqOXlx6v997bC5MEm MaEnpLIFrnVvDrar0FiAwfXXMy6xnyP/hDS4AU5RgO39G7UOtnxnXFMWFf4xvlCNjssZ zn3aXF2d5Gozh/5+HGSF4op4SH6OWL9Yr2DuHcFEdF68r78YQsiA1iNeN2ie1gPHzpwe bEJw== X-Gm-Message-State: AElRT7Erx/8mHZ0Gil/C9rGviN1rFCW/fye5EIcF+1X6nS9I36pApDdx c3+Q3rW2Hy4+UTVxu52RJJfbkQ== X-Google-Smtp-Source: AG47ELuhjBdIUBKbChL9/84MOQdUNAHN5m1DW2HWA83hSvBVACi5YRs9jsNP6oGyWbtZEsf3JW0v6g== X-Received: by 10.46.73.73 with SMTP id b9mr1835393ljd.129.1520413849185; Wed, 07 Mar 2018 01:10:49 -0800 (PST) Received: from tuxracer.localdomain ([2a01:6d80::195:20:96:53]) by smtp.gmail.com with ESMTPSA id j7sm3643490lfh.46.2018.03.07.01.10.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Mar 2018 01:10:48 -0800 (PST) From: Serhey Popovych To: netfilter-devel@vger.kernel.org Cc: willem.j.debruijn@gmail.com Subject: [PATCH iptables 1/4] xtables: Do not register matches/targets with incompatible revision Date: Wed, 7 Mar 2018 11:10:40 +0200 Message-Id: <1520413843-24456-2-git-send-email-serhe.popovych@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1520413843-24456-1-git-send-email-serhe.popovych@gmail.com> References: <1520413843-24456-1-git-send-email-serhe.popovych@gmail.com> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org If kernel tells revision isn't found/supported at the moment we should keep entity in pending list, not register or bail to do so later. Kernel might still load module for entity we asking it for and this could be slow on some embedded devices. Catch double registration attempts by checking me->next being non-NULL in xtables_register_match() and xtables_register_target(). Signed-off-by: Serhey Popovych --- libxtables/xtables.c | 66 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 57a1102..5aaa238 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -198,8 +198,8 @@ struct xtables_match *xtables_matches; struct xtables_target *xtables_targets; /* Fully register a match/target which was previously partially registered. */ -static void xtables_fully_register_pending_match(struct xtables_match *me); -static void xtables_fully_register_pending_target(struct xtables_target *me); +static bool xtables_fully_register_pending_match(struct xtables_match *me); +static bool xtables_fully_register_pending_target(struct xtables_target *me); void xtables_init(void) { @@ -638,11 +638,11 @@ xtables_find_match(const char *name, enum xtables_tryload tryload, if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { ptr = *dptr; *dptr = (*dptr)->next; - ptr->next = NULL; - xtables_fully_register_pending_match(ptr); - } else { - dptr = &((*dptr)->next); + if (xtables_fully_register_pending_match(ptr)) + continue; + *dptr = ptr; } + dptr = &((*dptr)->next); } for (ptr = xtables_matches; ptr; ptr = ptr->next) { @@ -728,11 +728,11 @@ xtables_find_target(const char *name, enum xtables_tryload tryload) if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { ptr = *dptr; *dptr = (*dptr)->next; - ptr->next = NULL; - xtables_fully_register_pending_target(ptr); - } else { - dptr = &((*dptr)->next); + if (xtables_fully_register_pending_target(ptr)) + continue; + *dptr = ptr; } + dptr = &((*dptr)->next); } for (ptr = xtables_targets; ptr; ptr = ptr->next) { @@ -846,6 +846,12 @@ static void xtables_check_options(const char *name, const struct option *opt) void xtables_register_match(struct xtables_match *me) { + if (me->next) { + fprintf(stderr, "%s: match \"%s\" already registered\n", + xt_params->program_name, me->name); + exit(1); + } + if (me->version == NULL) { fprintf(stderr, "%s: match %s<%u> is missing a version\n", xt_params->program_name, me->name, me->revision); @@ -947,12 +953,17 @@ static int xtables_target_prefer(const struct xtables_target *a, b->revision, b->family); } -static void xtables_fully_register_pending_match(struct xtables_match *me) +static bool xtables_fully_register_pending_match(struct xtables_match *me) { struct xtables_match **i, *old; const char *rn; int compare; + /* See if new match can be used. */ + rn = (me->real_name != NULL) ? me->real_name : me->name; + if (!compatible_match_revision(rn, me->revision)) + return false; + old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); if (old) { compare = xtables_match_prefer(old, me); @@ -967,12 +978,7 @@ static void xtables_fully_register_pending_match(struct xtables_match *me) rn = (old->real_name != NULL) ? old->real_name : old->name; if (compare > 0 && compatible_match_revision(rn, old->revision)) - return; - - /* See if new match can be used. */ - rn = (me->real_name != NULL) ? me->real_name : me->name; - if (!compatible_match_revision(rn, me->revision)) - return; + return true; /* Delete old one. */ for (i = &xtables_matches; *i!=old; i = &(*i)->next); @@ -993,6 +999,8 @@ static void xtables_fully_register_pending_match(struct xtables_match *me) me->m = NULL; me->mflags = 0; + + return true; } void xtables_register_matches(struct xtables_match *match, unsigned int n) @@ -1004,6 +1012,12 @@ void xtables_register_matches(struct xtables_match *match, unsigned int n) void xtables_register_target(struct xtables_target *me) { + if (me->next) { + fprintf(stderr, "%s: target \"%s\" already registered\n", + xt_params->program_name, me->name); + exit(1); + } + if (me->version == NULL) { fprintf(stderr, "%s: target %s<%u> is missing a version\n", xt_params->program_name, me->name, me->revision); @@ -1044,12 +1058,19 @@ void xtables_register_target(struct xtables_target *me) xtables_pending_targets = me; } -static void xtables_fully_register_pending_target(struct xtables_target *me) +static bool xtables_fully_register_pending_target(struct xtables_target *me) { struct xtables_target *old; const char *rn; int compare; + if (strcmp(me->name, "standard") != 0) { + /* See if new target can be used. */ + rn = (me->real_name != NULL) ? me->real_name : me->name; + if (!compatible_target_revision(rn, me->revision)) + return false; + } + old = xtables_find_target(me->name, XTF_DURING_LOAD); if (old) { struct xtables_target **i; @@ -1066,12 +1087,7 @@ static void xtables_fully_register_pending_target(struct xtables_target *me) rn = (old->real_name != NULL) ? old->real_name : old->name; if (compare > 0 && compatible_target_revision(rn, old->revision)) - return; - - /* See if new target can be used. */ - rn = (me->real_name != NULL) ? me->real_name : me->name; - if (!compatible_target_revision(rn, me->revision)) - return; + return true; /* Delete old one. */ for (i = &xtables_targets; *i!=old; i = &(*i)->next); @@ -1090,6 +1106,8 @@ static void xtables_fully_register_pending_target(struct xtables_target *me) xtables_targets = me; me->t = NULL; me->tflags = 0; + + return true; } void xtables_register_targets(struct xtables_target *target, unsigned int n) From patchwork Wed Mar 7 09:10:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serhey Popovych X-Patchwork-Id: 882483 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="QocLUh08"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zx7Cy3SZ0z9sfN for ; Wed, 7 Mar 2018 20:10:54 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751195AbeCGJKx (ORCPT ); Wed, 7 Mar 2018 04:10:53 -0500 Received: from mail-lf0-f68.google.com ([209.85.215.68]:38867 "EHLO mail-lf0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751059AbeCGJKw (ORCPT ); Wed, 7 Mar 2018 04:10:52 -0500 Received: by mail-lf0-f68.google.com with SMTP id i80-v6so2142712lfg.5 for ; Wed, 07 Mar 2018 01:10:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wfgFA8f2ndCKk/wGvU4mT6XvsPSijWW99fIEEL6GHAY=; b=QocLUh08KA48dbqeI6nS5x1mENcWbp8nGk8JxmtNOxCBi4n+a94k05ha8MAf2hq2q5 7QB4OiCApbGhHNuduCGnX+omDAEXVj9odH6jy4vF7IaER2O+9VZdZbsqIo/vXrIscpde 4p5UnTOwF/zW3t/UBj29ITyko+jESZE2BS4n+jSSdHL7W1YFHXPLDBmBeiPwMjpGYIEU QfJ54vbTvPzQYydA0pc+rqi/TiQuGfO6M3LJovdH2TGtVRSADqkFyUnVdvZ3VB9T4GDQ 72+iUMsOtfwoYKq/q+JHxXdoE3+BdP+aZ1BtLEI7w15OqEEq5Dslj6QkNZ8lAZiHsCQN y4jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=wfgFA8f2ndCKk/wGvU4mT6XvsPSijWW99fIEEL6GHAY=; b=ZJiqIfszEe2ySW+OZU1A0J4r9VpBdgaot03zoS6dyC/aiojh7C3xeHIztNioGcdW4e 79u6uksjhwZJv06aHXVvxaD1UYXNUZIazMfpYYmD9TqPfRYzY+1mWz1ufN/3m/zBS0ti mC/bbCPSpbbhIyjhhjPlW7W5e8tG1Cxlrbvrg9V0DMByn/YmxO4ykY2nTztYsWpucz60 iQseY2WmP7GMoim0p9DALb4yV76KDvQdX16Jwgtn/QJB6KKG/HP7ttzEKUo6z1gJxNb2 L9Slp2P6Nhn7xX2A92eEhKkMyA6xg/Edo1fkKeaRVKTumWK+lrGuzga8OWg3oK5ZcJnP wRxg== X-Gm-Message-State: AElRT7GlXUS58pBgj1rwFXN+qBc5iRrWE6AR8TjlOQao4xHiV6q6u3sH wUCmt/wpZZz1PF1t0byk9Xup0A== X-Google-Smtp-Source: AG47ELuk2AsjPOrJc5yeYwT/KuVec7CwzbLm1M3c36avpcwNi7xX87KchgAjvj5KorudpOCvGm3WUw== X-Received: by 10.46.33.156 with SMTP id h28mr10266995lji.126.1520413850359; Wed, 07 Mar 2018 01:10:50 -0800 (PST) Received: from tuxracer.localdomain ([2a01:6d80::195:20:96:53]) by smtp.gmail.com with ESMTPSA id j7sm3643490lfh.46.2018.03.07.01.10.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Mar 2018 01:10:49 -0800 (PST) From: Serhey Popovych To: netfilter-devel@vger.kernel.org Cc: willem.j.debruijn@gmail.com Subject: [PATCH iptables 2/4] xtables: Check match/target size vs XT_ALIGN(size) at register time Date: Wed, 7 Mar 2018 11:10:41 +0200 Message-Id: <1520413843-24456-3-git-send-email-serhe.popovych@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1520413843-24456-1-git-send-email-serhe.popovych@gmail.com> References: <1520413843-24456-1-git-send-email-serhe.popovych@gmail.com> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Size is known at xtables_register_match()/xtables_register_target() calls: no need to defer it to final registration steps. Signed-off-by: Serhey Popovych --- libxtables/xtables.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 5aaa238..33fc158 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -857,6 +857,14 @@ void xtables_register_match(struct xtables_match *me) xt_params->program_name, me->name, me->revision); exit(1); } + + if (me->size != XT_ALIGN(me->size)) { + fprintf(stderr, "%s: match \"%s\" has invalid size %u.\n", + xt_params->program_name, me->name, + (unsigned int)me->size); + exit(1); + } + if (strcmp(me->version, XTABLES_VERSION) != 0) { fprintf(stderr, "%s: match \"%s\" has version \"%s\", " "but \"%s\" is required.\n", @@ -985,13 +993,6 @@ static bool xtables_fully_register_pending_match(struct xtables_match *me) *i = old->next; } - if (me->size != XT_ALIGN(me->size)) { - fprintf(stderr, "%s: match `%s' has invalid size %u.\n", - xt_params->program_name, me->name, - (unsigned int)me->size); - exit(1); - } - /* Append to list. */ for (i = &xtables_matches; *i; i = &(*i)->next); me->next = NULL; @@ -1023,6 +1024,14 @@ void xtables_register_target(struct xtables_target *me) xt_params->program_name, me->name, me->revision); exit(1); } + + if (me->size != XT_ALIGN(me->size)) { + fprintf(stderr, "%s: target \"%s\" has invalid size %u.\n", + xt_params->program_name, me->name, + (unsigned int)me->size); + exit(1); + } + if (strcmp(me->version, XTABLES_VERSION) != 0) { fprintf(stderr, "%s: target \"%s\" has version \"%s\", " "but \"%s\" is required.\n", @@ -1094,13 +1103,6 @@ static bool xtables_fully_register_pending_target(struct xtables_target *me) *i = old->next; } - if (me->size != XT_ALIGN(me->size)) { - fprintf(stderr, "%s: target `%s' has invalid size %u.\n", - xt_params->program_name, me->name, - (unsigned int)me->size); - exit(1); - } - /* Prepend to list. */ me->next = xtables_targets; xtables_targets = me; From patchwork Wed Mar 7 09:10:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serhey Popovych X-Patchwork-Id: 882484 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="kpKMHBnh"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zx7Cz4M72z9sf8 for ; Wed, 7 Mar 2018 20:10:55 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751204AbeCGJKz (ORCPT ); Wed, 7 Mar 2018 04:10:55 -0500 Received: from mail-lf0-f65.google.com ([209.85.215.65]:44508 "EHLO mail-lf0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750989AbeCGJKx (ORCPT ); Wed, 7 Mar 2018 04:10:53 -0500 Received: by mail-lf0-f65.google.com with SMTP id v9-v6so2122922lfa.11 for ; Wed, 07 Mar 2018 01:10:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+GsOODgRP1zGOZPSKr6z8QERLg5R8N/+yDu0uFB0UUM=; b=kpKMHBnhk1QJnctSUVadXSW6+uK/4Uj94quxwnD1pYaCmtY48x3fqrB71Ej4AhJ8Gb ksKgqDYTmw9/SfQMrwxl/Wt5Fdw+sosVibOLFYYXt0lLw+0Jt1fqoMnEVzREGfn0K54p Oap00bCIfaPFSkAnBOQHngJn3+Ea7uImO+o5rpMPfJRJR56bbZnjLbVXERoqBXsTnBWu eWpF9YJC6awOUWKIrbBZ6ixEAfwnXBCPTb8Ciu1Ssrp5HNPBwQ6w3X00cdfZ9LW0ap6n CCfwGukDt0cyPEn2n2Ec7auQ1opUGiptORagrIbHErPUUTbttXTEaO/hz3KKyQfk89DB XhVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+GsOODgRP1zGOZPSKr6z8QERLg5R8N/+yDu0uFB0UUM=; b=I4YzeVOp8WIcqKhfj1l9vvCSVmRUvEMHT76+KZfekBYzUa7ADpqXgUOYMIoOq5pNN0 WVh4u9phMNq+tXs7bpXFdHrLNPvSi+dWlJFDUYclH7H/O8N+D/g9qDW7pCGXUUX69Sqc LXuu4V6s6B9f7t90QoN8MpvD8uum7ZmgcvL4HK4/1qYbsiF5ZUY0zYuGXZ8U9fezc7eU 6uOzheymXcRDblmAps7t8Wr4qRlGWaEMxxSnQ8q+p4yhvdjEjlq1EcD8gvh0tQXnibNp naGAm5toef9Ey28kQREQpnEQ/SDE3z4wvsvfjTZA9B6sQA1VLPDvODheUPXMRX96SQfH foPA== X-Gm-Message-State: APf1xPCJj2EvoOYgHOHGNljwFKhm1dczItVfxyQbobUBmHRhcenfXy0S Bwfhs/+ljcGY56uJCJrkHJTLpg== X-Google-Smtp-Source: AG47ELuFP1Sqy2nEVUEGJ1b2EtWoGcmIwhN/ptC+/G1pius12R98YA+mGKPh9w208LWNYWjvAn5GRg== X-Received: by 10.46.33.230 with SMTP id h99mr15838232lji.47.1520413851531; Wed, 07 Mar 2018 01:10:51 -0800 (PST) Received: from tuxracer.localdomain ([2a01:6d80::195:20:96:53]) by smtp.gmail.com with ESMTPSA id j7sm3643490lfh.46.2018.03.07.01.10.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Mar 2018 01:10:50 -0800 (PST) From: Serhey Popovych To: netfilter-devel@vger.kernel.org Cc: willem.j.debruijn@gmail.com Subject: [PATCH iptables 3/4] xtables: Register all match/target revisions supported by us and kernel Date: Wed, 7 Mar 2018 11:10:42 +0200 Message-Id: <1520413843-24456-4-git-send-email-serhe.popovych@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1520413843-24456-1-git-send-email-serhe.popovych@gmail.com> References: <1520413843-24456-1-git-send-email-serhe.popovych@gmail.com> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Keep the order of matches by appending them; keep order between revisions of same match from most to least recent. All of this keeps xtables_find_match() happy to find most recent supported by kernel revision in the given order. Apply the same for targets, except prepend targets; order between revisions preserved too. All this needed to fix nasty bug related to iptables package update and broken print/save output. After this change all supported revisions of match/target stored in corresponding list with following pattern: xt_matches xt_targets ========== ========== m1 m2 m3 mN tN t1 t2 t3 +-----+--+---+---~~~---+ +---~~~---+---+----+--+ |43210|10|210|revisions| |revisions|210|3210|10| +-----+--+---+---~~~---+ +---~~~---+---+----+--+ Where new [m]atches added to the list tail and new [t]argets added to the list head to preserve previous behaviour. Multiple revisions of single match/target type are grouped together and sorted in descending order. Both this ensures xtables_find_match() and xtables_find_target() behaviour remains the same after change: find highest supported match/target revision given by it's name. Signed-off-by: Serhey Popovych --- libxtables/xtables.c | 95 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 24 deletions(-) diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 33fc158..5a115ff 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -963,7 +963,7 @@ static int xtables_target_prefer(const struct xtables_target *a, static bool xtables_fully_register_pending_match(struct xtables_match *me) { - struct xtables_match **i, *old; + struct xtables_match **i, *old, *pos = NULL; const char *rn; int compare; @@ -973,7 +973,7 @@ static bool xtables_fully_register_pending_match(struct xtables_match *me) return false; old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); - if (old) { + while (old) { compare = xtables_match_prefer(old, me); if (compare == 0) { fprintf(stderr, @@ -984,18 +984,41 @@ static bool xtables_fully_register_pending_match(struct xtables_match *me) /* Now we have two (or more) options, check compatibility. */ rn = (old->real_name != NULL) ? old->real_name : old->name; - if (compare > 0 && - compatible_match_revision(rn, old->revision)) - return true; + if (compare > 0) { + /* Kernel tells old isn't compatible anymore??? */ + if (!compatible_match_revision(rn, old->revision)) { + /* Delete old one. */ + for (i = &xtables_matches; *i != old;) + i = &(*i)->next; + *i = old->next; + } + pos = old; + old = old->next; + if (!old) + break; + if (!extension_cmp(me->name, old->name, old->family)) + break; + continue; + } - /* Delete old one. */ - for (i = &xtables_matches; *i!=old; i = &(*i)->next); - *i = old->next; + /* Found right old */ + pos = old; + break; + } + + if (!pos) { + /* Append to list. */ + for (i = &xtables_matches; *i; i = &(*i)->next); + } else if (compare < 0) { + /* Prepend it */ + for (i = &xtables_matches; *i != pos; i = &(*i)->next); + } else if (compare > 0) { + /* Append it */ + i = &pos->next; + pos = pos->next; } - /* Append to list. */ - for (i = &xtables_matches; *i; i = &(*i)->next); - me->next = NULL; + me->next = pos; *i = me; me->m = NULL; @@ -1069,7 +1092,7 @@ void xtables_register_target(struct xtables_target *me) static bool xtables_fully_register_pending_target(struct xtables_target *me) { - struct xtables_target *old; + struct xtables_target **i, *old, *pos = NULL; const char *rn; int compare; @@ -1081,9 +1104,7 @@ static bool xtables_fully_register_pending_target(struct xtables_target *me) } old = xtables_find_target(me->name, XTF_DURING_LOAD); - if (old) { - struct xtables_target **i; - + while (old) { compare = xtables_target_prefer(old, me); if (compare == 0) { fprintf(stderr, @@ -1094,18 +1115,44 @@ static bool xtables_fully_register_pending_target(struct xtables_target *me) /* Now we have two (or more) options, check compatibility. */ rn = (old->real_name != NULL) ? old->real_name : old->name; - if (compare > 0 && - compatible_target_revision(rn, old->revision)) - return true; + if (compare > 0) { + /* Kernel tells old isn't compatible anymore??? */ + if (!compatible_target_revision(rn, old->revision)) { + /* Delete old one. */ + for (i = &xtables_targets; *i != old;) + i = &(*i)->next; + *i = old->next; + } + pos = old; + old = old->next; + if (!old) + break; + if (!extension_cmp(me->name, old->name, old->family)) + break; + continue; + } - /* Delete old one. */ - for (i = &xtables_targets; *i!=old; i = &(*i)->next); - *i = old->next; + /* Found right old */ + pos = old; + break; } - /* Prepend to list. */ - me->next = xtables_targets; - xtables_targets = me; + if (!pos) { + /* Prepend to list. */ + i = &xtables_targets; + pos = xtables_targets; + } else if (compare < 0) { + /* Prepend it */ + for (i = &xtables_targets; *i != pos; i = &(*i)->next); + } else if (compare > 0) { + /* Append it */ + i = &pos->next; + pos = pos->next; + } + + me->next = pos; + *i = me; + me->t = NULL; me->tflags = 0; From patchwork Wed Mar 7 09:10:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serhey Popovych X-Patchwork-Id: 882485 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="B2bLBISB"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zx7D20VKvz9sfK for ; Wed, 7 Mar 2018 20:10:58 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751176AbeCGJK4 (ORCPT ); Wed, 7 Mar 2018 04:10:56 -0500 Received: from mail-lf0-f65.google.com ([209.85.215.65]:39591 "EHLO mail-lf0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751036AbeCGJKy (ORCPT ); Wed, 7 Mar 2018 04:10:54 -0500 Received: by mail-lf0-f65.google.com with SMTP id f75-v6so2141530lfg.6 for ; Wed, 07 Mar 2018 01:10:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=S/W5CAvKx55BV2XIffobISTJBw/OaEldsKU8xN6t2xw=; b=B2bLBISB3ipibkvdggufRcVeR/8dmJ//RfHVPcJGpZ6tuO/hVw9dGV5Q9cjp8S426+ lLpLAeqC+Ry5uKsEoCv6aACExxlC4kUDTnhg8VT2fCQT83Dv4NQCplq9sq/dsIqdTlZB VLUUc8z81I6UsZ1Q+QgAGSmBxZ3ZPwqe8WLLnWPC4zy12UBdxecCUcT82pwEaP0m5mTb kd1e4gh1vqrUHxikKMZnJMC9Ty3ByNCWKQeL6aV+jmQrOAv19rX64dvPYmA4jn+NqJEW MA0jtvsE3Lbh8bDMPAzM0+rElEkyGS4Fz99coQB1f8uxuJF47Sl3LsIQzMFSMUv09C/f 71XQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=S/W5CAvKx55BV2XIffobISTJBw/OaEldsKU8xN6t2xw=; b=geoHnW6zeIZYgwLmQDJqp7XJSVOCMhlzVeXhq7bOFwt/NTjYxa9ev8ol/aBtLr5G7Y nvpBPgLnD2NoTbtV+5imy8sotMmqlbJCfTYyfcQx5SAYEEqbvTfA5iSLXh0vYOSuC7y1 jdM2Vj+2JbPCBLN98pjpYLZFkPP3MSMCqbEFBVYCJf0pzDsLCLe/cYmMv55XI3eT14Jd ruFcqM5R2+U9ARG/61vVptYlWw0iYxOZ+7ByaT69VLpaa5X8/UpD0UWXieUklHHgRO5f h9yKSozFSGd9OeGyQbaL6huPFrh6LjNylGMNlvYlmQyRebfniwyL7CGzoyIKyvwyHvN1 W7Aw== X-Gm-Message-State: AElRT7EM+CGJZkJnRDx+jXRydwVWXnN5EJi4dCJ4ECRxpSZfW86zNWvh Ngfsgys4WoJ6Cl8Jaur5dJTGsg== X-Google-Smtp-Source: AG47ELtGNApZ9XVMniHmoupK9HKqSJ7t0c4303UQ7p3TJ7aI7ld/La8w1EdFRQu88pMF14uniCTXcQ== X-Received: by 10.25.56.22 with SMTP id f22mr15518823lfa.109.1520413852718; Wed, 07 Mar 2018 01:10:52 -0800 (PST) Received: from tuxracer.localdomain ([2a01:6d80::195:20:96:53]) by smtp.gmail.com with ESMTPSA id j7sm3643490lfh.46.2018.03.07.01.10.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Mar 2018 01:10:51 -0800 (PST) From: Serhey Popovych To: netfilter-devel@vger.kernel.org Cc: willem.j.debruijn@gmail.com Subject: [PATCH iptables 4/4] xtables: Fix rules print/save after iptables update Date: Wed, 7 Mar 2018 11:10:43 +0200 Message-Id: <1520413843-24456-5-git-send-email-serhe.popovych@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1520413843-24456-1-git-send-email-serhe.popovych@gmail.com> References: <1520413843-24456-1-git-send-email-serhe.popovych@gmail.com> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Updating iptables from 1.4.x to 1.6.x brokes rules print/save output and causes rules load after reboot to fail. Here is example from iptables-save(8) output after update: -A CHAIN1 -m set [unsupported revision] -j DROP -A CHAIN1 -m set [unsupported revision] -j DROP Similar output could be obtained via iptables -L CHAIN1. While issue reproduced with xt_set match it is not specific to any match or target module: it is related on how xtables handles revisions. In this particular case we have following situation: 1) Kernel supports revisions from 1 to 4. 2) Rules configured with iptables 1.4.x supporting only revisions from 1 to 3. Choosen highest possible revision 3. 3) Rules printed/saved with iptables 1.6.x supporting revisions from 1 to 4. 4) Xtables registers matches/targets with highest supported revision by the kernel. This is 4 in our case after update to iptables 1.6.x. 5) When printing/saving kernel submits match/target with revision it is configured (3), while iptables thinks that rules configured with highest supported (4). That's causes revision mismatch in during print and "[unsupported revision]" output. To fix this issue we now store all supported by kernel and xtables revisions in xt_matches/xt_targets list sorted in descending order. Introduce helper routines to find match/target with given revision and use them to find right revision to print submitted by kernel entry. Signed-off-by: Serhey Popovych --- include/xtables.h | 6 +++++ iptables/ip6tables.c | 66 ++++++++++++++++++++++++++++++++------------------ iptables/iptables.c | 66 ++++++++++++++++++++++++++++++++------------------ libxtables/xtables.c | 42 ++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 46 deletions(-) diff --git a/include/xtables.h b/include/xtables.h index e9bc3b7..0b19e0f 100644 --- a/include/xtables.h +++ b/include/xtables.h @@ -464,8 +464,14 @@ extern struct option *xtables_merge_options(struct option *origopts, extern int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto); extern struct xtables_match *xtables_find_match(const char *name, enum xtables_tryload, struct xtables_rule_match **match); +extern struct xtables_match *xtables_find_match_revision(const char *name, + enum xtables_tryload tryload, struct xtables_match *match, + int revision); extern struct xtables_target *xtables_find_target(const char *name, enum xtables_tryload); +struct xtables_target *xtables_find_target_revision(const char *name, + enum xtables_tryload tryload, struct xtables_target *target, + int revision); extern int xtables_compatible_revision(const char *name, uint8_t revision, int opt); diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 49bd006..6954c25 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -518,19 +518,23 @@ print_match(const struct xt_entry_match *m, const struct ip6t_ip6 *ip, int numeric) { - const struct xtables_match *match = - xtables_find_match(m->u.user.name, XTF_TRY_LOAD, NULL); + const char *name = m->u.user.name; + const int revision = m->u.user.revision; + struct xtables_match *match, *mt; + match = xtables_find_match(name, XTF_TRY_LOAD, NULL); if (match) { - if (match->print && m->u.user.revision == match->revision) - match->print(ip, m, numeric); + mt = xtables_find_match_revision(name, XTF_TRY_LOAD, + match, revision); + if (mt && mt->print) + mt->print(ip, m, numeric); else if (match->print) printf("%s%s ", match->name, unsupported_rev); else printf("%s ", match->name); } else { - if (m->u.user.name[0]) - printf("UNKNOWN match `%s' ", m->u.user.name); + if (name[0]) + printf("UNKNOWN match `%s' ", name); } /* Don't stop iterating. */ return 0; @@ -544,7 +548,7 @@ print_firewall(const struct ip6t_entry *fw, unsigned int format, struct xtc_handle *const handle) { - const struct xtables_target *target = NULL; + struct xtables_target *target, *tg; const struct xt_entry_target *t; char buf[BUFSIZ]; @@ -651,9 +655,13 @@ print_firewall(const struct ip6t_entry *fw, IP6T_MATCH_ITERATE(fw, print_match, &fw->ipv6, format & FMT_NUMERIC); if (target) { - if (target->print && t->u.user.revision == target->revision) + const int revision = t->u.user.revision; + + tg = xtables_find_target_revision(targname, XTF_TRY_LOAD, + target, revision); + if (tg && tg->print) /* Print the target information. */ - target->print(&fw->ipv6, t, format & FMT_NUMERIC); + tg->print(&fw->ipv6, t, format & FMT_NUMERIC); else if (target->print) printf(" %s%s", target->name, unsupported_rev); } else if (t->u.target_size != sizeof(*t)) @@ -1035,23 +1043,28 @@ static void print_proto(uint16_t proto, int invert) static int print_match_save(const struct xt_entry_match *e, const struct ip6t_ip6 *ip) { - const struct xtables_match *match = - xtables_find_match(e->u.user.name, XTF_TRY_LOAD, NULL); + const char *name = e->u.user.name; + const int revision = e->u.user.revision; + struct xtables_match *match, *mt, *mt2; + match = xtables_find_match(name, XTF_TRY_LOAD, NULL); if (match) { - printf(" -m %s", - match->alias ? match->alias(e) : e->u.user.name); + mt = mt2 = xtables_find_match_revision(name, XTF_TRY_LOAD, + match, revision); + if (!mt2) + mt2 = match; + printf(" -m %s", mt2->alias ? mt2->alias(e) : name); /* some matches don't provide a save function */ - if (match->save && e->u.user.revision == match->revision) - match->save(ip, e); + if (mt && mt->save) + mt->save(ip, e); else if (match->save) printf(unsupported_rev); } else { if (e->u.match_size) { fprintf(stderr, "Can't find library for match `%s'\n", - e->u.user.name); + name); exit(1); } } @@ -1136,18 +1149,25 @@ void print_rule6(const struct ip6t_entry *e, target_name = ip6tc_get_target(e, h); t = ip6t_get_target((struct ip6t_entry *)e); if (t->u.user.name[0]) { - struct xtables_target *target = - xtables_find_target(t->u.user.name, XTF_TRY_LOAD); + const char *name = t->u.user.name; + const int revision = t->u.user.revision; + struct xtables_target *target, *tg, *tg2; + target = xtables_find_target(name, XTF_TRY_LOAD); if (!target) { fprintf(stderr, "Can't find library for target `%s'\n", - t->u.user.name); + name); exit(1); } - printf(" -j %s", target->alias ? target->alias(t) : target_name); - if (target->save && t->u.user.revision == target->revision) - target->save(&e->ipv6, t); + tg = tg2 = xtables_find_target_revision(name, XTF_TRY_LOAD, + target, revision); + if (!tg2) + tg2 = target; + printf(" -j %s", tg2->alias ? tg2->alias(t) : target_name); + + if (tg && tg->save) + tg->save(&e->ipv6, t); else if (target->save) printf(unsupported_rev); else { @@ -1158,7 +1178,7 @@ void print_rule6(const struct ip6t_entry *e, sizeof(struct xt_entry_target)) { fprintf(stderr, "Target `%s' is missing " "save function\n", - t->u.user.name); + name); exit(1); } } diff --git a/iptables/iptables.c b/iptables/iptables.c index 69d19fe..acacf18 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -502,19 +502,23 @@ print_match(const struct xt_entry_match *m, const struct ipt_ip *ip, int numeric) { - const struct xtables_match *match = - xtables_find_match(m->u.user.name, XTF_TRY_LOAD, NULL); + const char *name = m->u.user.name; + const int revision = m->u.user.revision; + struct xtables_match *match, *mt; + match = xtables_find_match(name, XTF_TRY_LOAD, NULL); if (match) { - if (match->print && m->u.user.revision == match->revision) - match->print(ip, m, numeric); + mt = xtables_find_match_revision(name, XTF_TRY_LOAD, + match, revision); + if (mt && mt->print) + mt->print(ip, m, numeric); else if (match->print) printf("%s%s ", match->name, unsupported_rev); else printf("%s ", match->name); } else { - if (m->u.user.name[0]) - printf("UNKNOWN match `%s' ", m->u.user.name); + if (name[0]) + printf("UNKNOWN match `%s' ", name); } /* Don't stop iterating. */ return 0; @@ -528,7 +532,7 @@ print_firewall(const struct ipt_entry *fw, unsigned int format, struct xtc_handle *const handle) { - const struct xtables_target *target = NULL; + struct xtables_target *target, *tg; const struct xt_entry_target *t; uint8_t flags; char buf[BUFSIZ]; @@ -635,9 +639,13 @@ print_firewall(const struct ipt_entry *fw, IPT_MATCH_ITERATE(fw, print_match, &fw->ip, format & FMT_NUMERIC); if (target) { - if (target->print && t->u.user.revision == target->revision) + const int revision = t->u.user.revision; + + tg = xtables_find_target_revision(targname, XTF_TRY_LOAD, + target, revision); + if (tg && tg->print) /* Print the target information. */ - target->print(&fw->ip, t, format & FMT_NUMERIC); + tg->print(&fw->ip, t, format & FMT_NUMERIC); else if (target->print) printf(" %s%s", target->name, unsupported_rev); } else if (t->u.target_size != sizeof(*t)) @@ -1025,23 +1033,28 @@ print_iface(char letter, const char *iface, const unsigned char *mask, static int print_match_save(const struct xt_entry_match *e, const struct ipt_ip *ip) { - const struct xtables_match *match = - xtables_find_match(e->u.user.name, XTF_TRY_LOAD, NULL); + const char *name = e->u.user.name; + const int revision = e->u.user.revision; + struct xtables_match *match, *mt, *mt2; + match = xtables_find_match(name, XTF_TRY_LOAD, NULL); if (match) { - printf(" -m %s", - match->alias ? match->alias(e) : e->u.user.name); + mt = mt2 = xtables_find_match_revision(name, XTF_TRY_LOAD, + match, revision); + if (!mt2) + mt2 = match; + printf(" -m %s", mt2->alias ? mt2->alias(e) : name); /* some matches don't provide a save function */ - if (match->save && e->u.user.revision == match->revision) - match->save(ip, e); + if (mt && mt->save) + mt->save(ip, e); else if (match->save) printf(unsupported_rev); } else { if (e->u.match_size) { fprintf(stderr, "Can't find library for match `%s'\n", - e->u.user.name); + name); exit(1); } } @@ -1125,18 +1138,25 @@ void print_rule4(const struct ipt_entry *e, target_name = iptc_get_target(e, h); t = ipt_get_target((struct ipt_entry *)e); if (t->u.user.name[0]) { - const struct xtables_target *target = - xtables_find_target(t->u.user.name, XTF_TRY_LOAD); + const char *name = t->u.user.name; + const int revision = t->u.user.revision; + struct xtables_target *target, *tg, *tg2; + target = xtables_find_target(name, XTF_TRY_LOAD); if (!target) { fprintf(stderr, "Can't find library for target `%s'\n", - t->u.user.name); + name); exit(1); } - printf(" -j %s", target->alias ? target->alias(t) : target_name); - if (target->save && t->u.user.revision == target->revision) - target->save(&e->ip, t); + tg = tg2 = xtables_find_target_revision(name, XTF_TRY_LOAD, + target, revision); + if (!tg2) + tg2 = target; + printf(" -j %s", tg2->alias ? tg2->alias(t) : target_name); + + if (tg && tg->save) + tg->save(&e->ip, t); else if (target->save) printf(unsupported_rev); else { @@ -1147,7 +1167,7 @@ void print_rule4(const struct ipt_entry *e, sizeof(struct xt_entry_target)) { fprintf(stderr, "Target `%s' is missing " "save function\n", - t->u.user.name); + name); exit(1); } } diff --git a/libxtables/xtables.c b/libxtables/xtables.c index 5a115ff..06044a2 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -709,6 +709,27 @@ xtables_find_match(const char *name, enum xtables_tryload tryload, return ptr; } +struct xtables_match * +xtables_find_match_revision(const char *name, enum xtables_tryload tryload, + struct xtables_match *match, int revision) +{ + if (!match) { + match = xtables_find_match(name, tryload, NULL); + if (!match) + return NULL; + } + + while (1) { + if (match->revision == revision) + return match; + match = match->next; + if (!match) + return NULL; + if (!extension_cmp(name, match->name, match->family)) + return NULL; + } +} + struct xtables_target * xtables_find_target(const char *name, enum xtables_tryload tryload) { @@ -769,6 +790,27 @@ xtables_find_target(const char *name, enum xtables_tryload tryload) return ptr; } +struct xtables_target * +xtables_find_target_revision(const char *name, enum xtables_tryload tryload, + struct xtables_target *target, int revision) +{ + if (!target) { + target = xtables_find_target(name, tryload); + if (!target) + return NULL; + } + + while (1) { + if (target->revision == revision) + return target; + target = target->next; + if (!target) + return NULL; + if (!extension_cmp(name, target->name, target->family)) + return NULL; + } +} + int xtables_compatible_revision(const char *name, uint8_t revision, int opt) { struct xt_get_revision rev;