From 817f008a2f26b7295b9a251c7a10e0d95cfa9198 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kaber/emailAddress=kaber@netfilter.org" Date: Sat, 2 Sep 2006 12:37:48 +0000 Subject: [PATCH] Named realm (Simon Lodal ) Optionally read realm values from /etc/iproute2/rt_realms --- extensions/libipt_realm.c | 165 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 154 insertions(+), 11 deletions(-) (limited to 'extensions/libipt_realm.c') diff --git a/extensions/libipt_realm.c b/extensions/libipt_realm.c index f8152be..1564677 100644 --- a/extensions/libipt_realm.c +++ b/extensions/libipt_realm.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #if defined(__GLIBC__) && __GLIBC__ == 2 #include @@ -28,6 +30,128 @@ static struct option opts[] = { {0} }; +struct realmname { + int id; + char* name; + int len; + struct realmname* next; +}; + +/* array of realms from /etc/iproute2/rt_realms */ +static struct realmname *realms = NULL; +/* 1 if loading failed */ +static int rdberr = 0; + + +void load_realms() +{ + const char* rfnm = "/etc/iproute2/rt_realms"; + char buf[512]; + FILE *fil; + char *cur, *nxt; + int id; + struct realmname *oldnm = NULL, *newnm = NULL; + + fil = fopen(rfnm, "r"); + if (!fil) { + rdberr = 1; + return; + } + + while (fgets(buf, sizeof(buf), fil)) { + cur = buf; + while ((*cur == ' ') || (*cur == '\t')) + cur++; + if ((*cur == '#') || (*cur == '\n') || (*cur == 0)) + continue; + + /* iproute2 allows hex and dec format */ + errno = 0; + id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) ? 10 : 16); + if ((nxt == cur) || errno) + continue; + + /* same boundaries as in iproute2 */ + if (id < 0 || id > 255) + continue; + cur = nxt; + + if (!isspace(*cur)) + continue; + while ((*cur == ' ') || (*cur == '\t')) + cur++; + if ((*cur == '#') || (*cur == '\n') || (*cur == 0)) + continue; + nxt = cur; + while ((*nxt != 0) && !isspace(*nxt)) + nxt++; + if (nxt == cur) + continue; + + /* found valid data */ + newnm = (struct realmname*)malloc(sizeof(struct realmname)); + if (newnm == NULL) { + perror("libipt_realm: malloc failed"); + exit(1); + } + newnm->id = id; + newnm->len = nxt - cur; + newnm->name = (char*)malloc(newnm->len + 1); + if (newnm->name == NULL) { + perror("libipt_realm: malloc failed"); + exit(1); + } + strncpy(newnm->name, cur, newnm->len); + newnm->name[newnm->len] = 0; + newnm->next = NULL; + + if (oldnm) + oldnm->next = newnm; + else + realms = newnm; + oldnm = newnm; + } + + fclose(fil); +} + +/* get realm id for name, -1 if error/not found */ +int realm_name2id(const char* name) +{ + struct realmname* cur; + + if ((realms == NULL) && (rdberr == 0)) + load_realms(); + cur = realms; + if (cur == NULL) + return -1; + while (cur) { + if (!strncmp(name, cur->name, cur->len + 1)) + return cur->id; + cur = cur->next; + } + return -1; +} + +/* get realm name for id, NULL if error/not found */ +const char* realm_id2name(int id) +{ + struct realmname* cur; + + if ((realms == NULL) && (rdberr == 0)) + load_realms(); + cur = realms; + if (cur == NULL) + return NULL; + while (cur) { + if (id == cur->id) + return cur->name; + cur = cur->next; + } + return NULL; +} + + /* Function which parses command options; returns true if it ate an option */ static int @@ -37,19 +161,30 @@ parse(int c, char **argv, int invert, unsigned int *flags, struct ipt_entry_match **match) { struct ipt_realm_info *realminfo = (struct ipt_realm_info *)(*match)->data; + int id; switch (c) { char *end; case '1': check_inverse(argv[optind-1], &invert, &optind, 0); - optarg = argv[optind-1]; + end = optarg = argv[optind-1]; realminfo->id = strtoul(optarg, &end, 0); - if (*end == '/') { - realminfo->mask = strtoul(end+1, &end, 0); - } else + if (end != optarg && (*end == '/' || *end == '\0')) { + if (*end == '/') + realminfo->mask = strtoul(end+1, &end, 0); + else + realminfo->mask = 0xffffffff; + if (*end != '\0' || end == optarg) + exit_error(PARAMETER_PROBLEM, + "Bad realm value `%s'", optarg); + } else { + id = realm_name2id(optarg); + if (id == -1) + exit_error(PARAMETER_PROBLEM, + "Realm `%s' not found", optarg); + realminfo->id = (u_int32_t)id; realminfo->mask = 0xffffffff; - if (*end != '\0' || end == optarg) - exit_error(PARAMETER_PROBLEM, "Bad realm value `%s'", optarg); + } if (invert) realminfo->invert = 1; *flags = 1; @@ -62,12 +197,20 @@ parse(int c, char **argv, int invert, unsigned int *flags, } static void -print_realm(unsigned long id, unsigned long mask) +print_realm(unsigned long id, unsigned long mask, int numeric) { + const char* name = NULL; + if (mask != 0xffffffff) printf("0x%lx/0x%lx ", id, mask); - else - printf("0x%lx ", id); + else { + if (numeric == 0) + name = realm_id2name(id); + if (name) + printf("%s ", name); + else + printf("0x%lx ", id); + } } /* Prints out the matchinfo. */ @@ -82,7 +225,7 @@ print(const struct ipt_ip *ip, printf("! "); printf("realm "); - print_realm(ri->id, ri->mask); + print_realm(ri->id, ri->mask, numeric); } @@ -96,7 +239,7 @@ save(const struct ipt_ip *ip, const struct ipt_entry_match *match) printf("! "); printf("--realm "); - print_realm(ri->id, ri->mask); + print_realm(ri->id, ri->mask, 0); } /* Final check; must have specified --mark. */ -- cgit v1.2.3