Blame SOURCES/0035-libxtables-Make-sure-extensions-register-in-revision.patch

7cc531
From e6eede725bbd395fb8b385aec4d0a32ce99e842c Mon Sep 17 00:00:00 2001
7cc531
From: Phil Sutter <phil@nwl.cc>
7cc531
Date: Mon, 21 Sep 2020 13:42:06 +0200
7cc531
Subject: [PATCH] libxtables: Make sure extensions register in revision order
7cc531
7cc531
Insert extensions into pending lists in ordered fashion: Group by
7cc531
extension name (and, for matches, family) and order groups by descending
7cc531
revision number.
7cc531
7cc531
This allows to simplify the later full registration considerably. Since
7cc531
that involves kernel compatibility checks, the extra cycles here pay off
7cc531
eventually.
7cc531
7cc531
Signed-off-by: Phil Sutter <phil@nwl.cc>
7cc531
(cherry picked from commit b3ac87038f4e45141831d9ab485a2f627daba3f1)
7cc531
Signed-off-by: Phil Sutter <psutter@redhat.com>
7cc531
---
7cc531
 libxtables/xtables.c | 71 +++++++++++++++++++++++++++++++++++++++-----
7cc531
 1 file changed, 64 insertions(+), 7 deletions(-)
7cc531
7cc531
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
7cc531
index 777c2b08e9896..13139d7f8ad62 100644
7cc531
--- a/libxtables/xtables.c
7cc531
+++ b/libxtables/xtables.c
7cc531
@@ -902,8 +902,14 @@ static void xtables_check_options(const char *name, const struct option *opt)
7cc531
 		}
7cc531
 }
7cc531
 
7cc531
+static int xtables_match_prefer(const struct xtables_match *a,
7cc531
+				const struct xtables_match *b);
7cc531
+
7cc531
 void xtables_register_match(struct xtables_match *me)
7cc531
 {
7cc531
+	struct xtables_match **pos;
7cc531
+	bool seen_myself = false;
7cc531
+
7cc531
 	if (me->next) {
7cc531
 		fprintf(stderr, "%s: match \"%s\" already registered\n",
7cc531
 			xt_params->program_name, me->name);
7cc531
@@ -955,10 +961,34 @@ void xtables_register_match(struct xtables_match *me)
7cc531
 	if (me->extra_opts != NULL)
7cc531
 		xtables_check_options(me->name, me->extra_opts);
7cc531
 
7cc531
-
7cc531
-	/* place on linked list of matches pending full registration */
7cc531
-	me->next = xtables_pending_matches;
7cc531
-	xtables_pending_matches = me;
7cc531
+	/* order into linked list of matches pending full registration */
7cc531
+	for (pos = &xtables_pending_matches; *pos; pos = &(*pos)->next) {
7cc531
+		/* group by name and family */
7cc531
+		if (strcmp(me->name, (*pos)->name) ||
7cc531
+		    me->family != (*pos)->family) {
7cc531
+			if (seen_myself)
7cc531
+				break; /* end of own group, append to it */
7cc531
+			continue;
7cc531
+		}
7cc531
+		/* found own group */
7cc531
+		seen_myself = true;
7cc531
+		if (xtables_match_prefer(me, *pos) >= 0)
7cc531
+			break; /* put preferred items first in group */
7cc531
+	}
7cc531
+	/* if own group was not found, prepend item */
7cc531
+	if (!*pos && !seen_myself)
7cc531
+		pos = &xtables_pending_matches;
7cc531
+
7cc531
+	me->next = *pos;
7cc531
+	*pos = me;
7cc531
+#ifdef DEBUG
7cc531
+	printf("%s: inserted match %s (family %d, revision %d):\n",
7cc531
+			__func__, me->name, me->family, me->revision);
7cc531
+	for (pos = &xtables_pending_matches; *pos; pos = &(*pos)->next) {
7cc531
+		printf("%s:\tmatch %s (family %d, revision %d)\n", __func__,
7cc531
+		       (*pos)->name, (*pos)->family, (*pos)->revision);
7cc531
+	}
7cc531
+#endif
7cc531
 }
7cc531
 
7cc531
 /**
7cc531
@@ -1097,6 +1127,9 @@ void xtables_register_matches(struct xtables_match *match, unsigned int n)
7cc531
 
7cc531
 void xtables_register_target(struct xtables_target *me)
7cc531
 {
7cc531
+	struct xtables_target **pos;
7cc531
+	bool seen_myself = false;
7cc531
+
7cc531
 	if (me->next) {
7cc531
 		fprintf(stderr, "%s: target \"%s\" already registered\n",
7cc531
 			xt_params->program_name, me->name);
7cc531
@@ -1152,9 +1185,33 @@ void xtables_register_target(struct xtables_target *me)
7cc531
 	if (me->family != afinfo->family && me->family != AF_UNSPEC)
7cc531
 		return;
7cc531
 
7cc531
-	/* place on linked list of targets pending full registration */
7cc531
-	me->next = xtables_pending_targets;
7cc531
-	xtables_pending_targets = me;
7cc531
+	/* order into linked list of targets pending full registration */
7cc531
+	for (pos = &xtables_pending_targets; *pos; pos = &(*pos)->next) {
7cc531
+		/* group by name */
7cc531
+		if (!extension_cmp(me->name, (*pos)->name, (*pos)->family)) {
7cc531
+			if (seen_myself)
7cc531
+				break; /* end of own group, append to it */
7cc531
+			continue;
7cc531
+		}
7cc531
+		/* found own group */
7cc531
+		seen_myself = true;
7cc531
+		if (xtables_target_prefer(me, *pos) >= 0)
7cc531
+			break; /* put preferred items first in group */
7cc531
+	}
7cc531
+	/* if own group was not found, prepend item */
7cc531
+	if (!*pos && !seen_myself)
7cc531
+		pos = &xtables_pending_targets;
7cc531
+
7cc531
+	me->next = *pos;
7cc531
+	*pos = me;
7cc531
+#ifdef DEBUG
7cc531
+	printf("%s: inserted target %s (family %d, revision %d):\n",
7cc531
+			__func__, me->name, me->family, me->revision);
7cc531
+	for (pos = &xtables_pending_targets; *pos; pos = &(*pos)->next) {
7cc531
+		printf("%s:\ttarget %s (family %d, revision %d)\n", __func__,
7cc531
+		       (*pos)->name, (*pos)->family, (*pos)->revision);
7cc531
+	}
7cc531
+#endif
7cc531
 }
7cc531
 
7cc531
 static bool xtables_fully_register_pending_target(struct xtables_target *me)
7cc531
-- 
7cc531
2.28.0
7cc531