From ca9d8c221f0e10cc8dd0c79e922a1dc73ae0ca5f Mon Sep 17 00:00:00 2001 From: Simon Lodal Date: Sat, 2 Sep 2006 12:37:48 +0000 Subject: Named realm (Simon Lodal ) Optionally read realm values from /etc/iproute2/rt_realms --- extensions/libipt_realm.c | 165 +++++++++++++++++++++++++++++++++++++++++--- extensions/libipt_realm.man | 6 +- 2 files changed, 158 insertions(+), 13 deletions(-) diff --git a/extensions/libipt_realm.c b/extensions/libipt_realm.c index f8152be7..15646778 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. */ diff --git a/extensions/libipt_realm.man b/extensions/libipt_realm.man index 55e67fcf..b33da0e6 100644 --- a/extensions/libipt_realm.man +++ b/extensions/libipt_realm.man @@ -1,5 +1,7 @@ This matches the routing realm. Routing realms are used in complex routing setups involving dynamic routing protocols like BGP. .TP -.BI "--realm " "[!]" "value[/mask]" -Matches a given realm number (and optionally mask). +.BI "--realm " "[!] " "value[/mask]" +Matches a given realm number (and optionally mask). If not a number, value +can be a named realm from /etc/iproute2/rt_realms (mask can not be used in +that case). -- cgit v1.2.3