diff options
Diffstat (limited to 'xtables.c')
-rw-r--r-- | xtables.c | 58 |
1 files changed, 53 insertions, 5 deletions
@@ -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; |