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

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