summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej Zenczykowski <maze@google.com>2011-04-04 15:31:43 +0200
committerPatrick McHardy <kaber@trash.net>2011-04-04 15:31:43 +0200
commit2c6ac071a9c660b61a76565d1024d372deac8a98 (patch)
tree772761160fc86b1be650fa185fb55338fd7225e7
parentcf3e52d00b7d3fedf98ef7710c337c441270d936 (diff)
xtables: delay (statically built) match/target initialization
Matches and targets built into the iptables static binary will always be registered as the binary starts up, this may potentially (as a result of kernel version support checking) result in modules being autoloaded. This is undesirable (for example it may cause CONNMARK target to load and thus cause the kernel to load the conntrack module, which isn't a no-op). Transition to a system where matches and targets are registered into a pending list, from whence they get fully registered only when required. Signed-off-by: Maciej Zenczykowski <maze@google.com> Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--xtables.c58
1 files changed, 53 insertions, 5 deletions
diff --git a/xtables.c b/xtables.c
index 7d367423..4c708b8e 100644
--- a/xtables.c
+++ b/xtables.c
@@ -174,10 +174,18 @@ static const char *xtables_libdir;
/* the path to command to load kernel module */
const char *xtables_modprobe_program;
-/* Keeping track of external matches and targets: linked lists. */
+/* Keep track of matches/targets pending full registration: linked lists. */
+struct xtables_match *xtables_pending_matches;
+struct xtables_target *xtables_pending_targets;
+
+/* Keep track of fully registered external matches/targets: linked lists. */
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);
+
void xtables_init(void)
{
xtables_libdir = getenv("XTABLES_LIBDIR");
@@ -556,6 +564,7 @@ struct xtables_match *
xtables_find_match(const char *name, enum xtables_tryload tryload,
struct xtables_rule_match **matches)
{
+ struct xtables_match **dptr;
struct xtables_match *ptr;
const char *icmp6 = "icmp6";
@@ -571,6 +580,18 @@ xtables_find_match(const char *name, enum xtables_tryload tryload,
(strcmp(name,"icmp6") == 0) )
name = icmp6;
+ /* Trigger delayed initialization */
+ for (dptr = &xtables_pending_matches; *dptr; ) {
+ if (strcmp(name, (*dptr)->name) == 0) {
+ ptr = *dptr;
+ *dptr = (*dptr)->next;
+ ptr->next = NULL;
+ xtables_fully_register_pending_match(ptr);
+ } else {
+ dptr = &((*dptr)->next);
+ }
+ }
+
for (ptr = xtables_matches; ptr; ptr = ptr->next) {
if (strcmp(name, ptr->name) == 0) {
struct xtables_match *clone;
@@ -636,6 +657,7 @@ xtables_find_match(const char *name, enum xtables_tryload tryload,
struct xtables_target *
xtables_find_target(const char *name, enum xtables_tryload tryload)
{
+ struct xtables_target **dptr;
struct xtables_target *ptr;
/* Standard target? */
@@ -646,6 +668,18 @@ xtables_find_target(const char *name, enum xtables_tryload tryload)
|| strcmp(name, XTC_LABEL_RETURN) == 0)
name = "standard";
+ /* Trigger delayed initialization */
+ for (dptr = &xtables_pending_targets; *dptr; ) {
+ if (strcmp(name, (*dptr)->name) == 0) {
+ ptr = *dptr;
+ *dptr = (*dptr)->next;
+ ptr->next = NULL;
+ xtables_fully_register_pending_target(ptr);
+ } else {
+ dptr = &((*dptr)->next);
+ }
+ }
+
for (ptr = xtables_targets; ptr; ptr = ptr->next) {
if (strcmp(name, ptr->name) == 0)
break;
@@ -757,8 +791,6 @@ static void xtables_check_options(const char *name, const struct option *opt)
void xtables_register_match(struct xtables_match *me)
{
- struct xtables_match **i, *old;
-
if (me->version == NULL) {
fprintf(stderr, "%s: match %s<%u> is missing a version\n",
xt_params->program_name, me->name, me->revision);
@@ -792,6 +824,15 @@ void xtables_register_match(struct xtables_match *me)
if (me->family != afinfo->family && me->family != AF_UNSPEC)
return;
+ /* place on linked list of matches pending full registration */
+ me->next = xtables_pending_matches;
+ xtables_pending_matches = me;
+}
+
+static void xtables_fully_register_pending_match(struct xtables_match *me)
+{
+ struct xtables_match **i, *old;
+
old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
if (old) {
if (old->revision == me->revision &&
@@ -845,8 +886,6 @@ void xtables_register_matches(struct xtables_match *match, unsigned int n)
void xtables_register_target(struct xtables_target *me)
{
- struct xtables_target *old;
-
if (me->version == NULL) {
fprintf(stderr, "%s: target %s<%u> is missing a version\n",
xt_params->program_name, me->name, me->revision);
@@ -880,6 +919,15 @@ void xtables_register_target(struct xtables_target *me)
if (me->family != afinfo->family && me->family != AF_UNSPEC)
return;
+ /* place on linked list of targets pending full registration */
+ me->next = xtables_pending_targets;
+ xtables_pending_targets = me;
+}
+
+static void xtables_fully_register_pending_target(struct xtables_target *me)
+{
+ struct xtables_target *old;
+
old = xtables_find_target(me->name, XTF_DURING_LOAD);
if (old) {
struct xtables_target **i;