]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
Named realm (Simon Lodal <simon@parknet.dk>)
authorSimon Lodal <simon@parknet.dk>
Sat, 2 Sep 2006 12:37:48 +0000 (12:37 +0000)
committerPatrick McHardy <kaber@trash.net>
Sat, 2 Sep 2006 12:37:48 +0000 (12:37 +0000)
Optionally read realm values from /etc/iproute2/rt_realms

extensions/libipt_realm.c
extensions/libipt_realm.man

index f8152be7f47a0646a5629aded859293f8217f92e..15646778eb3de803f0d84dfb0062c04d45a6245e 100644 (file)
@@ -3,6 +3,8 @@
 #include <netdb.h>
 #include <string.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
 #include <getopt.h>
 #if defined(__GLIBC__) && __GLIBC__ == 2
 #include <net/ethernet.h>
@@ -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. */
index 55e67fcf74251eda6a43b3c1eace084e28aaaeec..b33da0e6aad2e5e44fd6bb4423ae41c17a89388c 100644 (file)
@@ -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).