]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - lib/rt_names.c
libnetlink: Add filter function to rtnl_neighdump_req
[mirror_iproute2.git] / lib / rt_names.c
index 620f3115a2a999bd02bd179e4b0f2296fb37c021..66d5f2f0722b80a7764315a8122b2fcc7fd0f138 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <syslog.h>
 #include <fcntl.h>
 #include <string.h>
 #include <sys/time.h>
 #include <sys/socket.h>
+#include <dirent.h>
+#include <limits.h>
 
 #include <asm/types.h>
 #include <linux/rtnetlink.h>
 
 #include "rt_names.h"
+#include "utils.h"
+
+#define NAME_MAX_LEN 512
 
 struct rtnl_hash_entry {
-       struct rtnl_hash_entry *next;
-       char *                  name;
+       struct rtnl_hash_entry  *next;
+       const char              *name;
        unsigned int            id;
 };
 
-static void
-rtnl_hash_initialize(char *file, struct rtnl_hash_entry **hash, int size)
+static int fread_id_name(FILE *fp, int *id, char *namebuf)
 {
-       struct rtnl_hash_entry *entry;
-       char buf[512];
-       FILE *fp;
+       char buf[NAME_MAX_LEN];
 
-       fp = fopen(file, "r");
-       if (!fp)
-               return;
        while (fgets(buf, sizeof(buf), fp)) {
                char *p = buf;
-               int id;
-               char namebuf[512];
 
                while (*p == ' ' || *p == '\t')
                        p++;
+
                if (*p == '#' || *p == '\n' || *p == 0)
                        continue;
-               if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2 &&
-                   sscanf(p, "0x%x %s #", &id, namebuf) != 2 &&
-                   sscanf(p, "%d %s\n", &id, namebuf) != 2 &&
-                   sscanf(p, "%d %s #", &id, namebuf) != 2) {
+
+               if (sscanf(p, "0x%x %s\n", id, namebuf) != 2 &&
+                               sscanf(p, "0x%x %s #", id, namebuf) != 2 &&
+                               sscanf(p, "%d %s\n", id, namebuf) != 2 &&
+                               sscanf(p, "%d %s #", id, namebuf) != 2) {
+                       strcpy(namebuf, p);
+                       return -1;
+               }
+               return 1;
+       }
+       return 0;
+}
+
+static void
+rtnl_hash_initialize(const char *file, struct rtnl_hash_entry **hash, int size)
+{
+       struct rtnl_hash_entry *entry;
+       FILE *fp;
+       int id;
+       char namebuf[NAME_MAX_LEN] = {0};
+       int ret;
+
+       fp = fopen(file, "r");
+       if (!fp)
+               return;
+
+       while ((ret = fread_id_name(fp, &id, &namebuf[0]))) {
+               if (ret == -1) {
                        fprintf(stderr, "Database %s is corrupted at %s\n",
-                               file, p);
+                                       file, namebuf);
+                       fclose(fp);
                        return;
                }
 
-               if (id<0)
+               if (id < 0)
                        continue;
+
                entry = malloc(sizeof(*entry));
                entry->id   = id;
                entry->name = strdup(namebuf);
@@ -68,33 +91,25 @@ rtnl_hash_initialize(char *file, struct rtnl_hash_entry **hash, int size)
        fclose(fp);
 }
 
-static void rtnl_tab_initialize(char *file, char **tab, int size)
+static void rtnl_tab_initialize(const char *file, char **tab, int size)
 {
-       char buf[512];
        FILE *fp;
+       int id;
+       char namebuf[NAME_MAX_LEN] = {0};
+       int ret;
 
        fp = fopen(file, "r");
        if (!fp)
                return;
-       while (fgets(buf, sizeof(buf), fp)) {
-               char *p = buf;
-               int id;
-               char namebuf[512];
 
-               while (*p == ' ' || *p == '\t')
-                       p++;
-               if (*p == '#' || *p == '\n' || *p == 0)
-                       continue;
-               if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2 &&
-                   sscanf(p, "0x%x %s #", &id, namebuf) != 2 &&
-                   sscanf(p, "%d %s\n", &id, namebuf) != 2 &&
-                   sscanf(p, "%d %s #", &id, namebuf) != 2) {
+       while ((ret = fread_id_name(fp, &id, &namebuf[0]))) {
+               if (ret == -1) {
                        fprintf(stderr, "Database %s is corrupted at %s\n",
-                               file, p);
+                                       file, namebuf);
+                       fclose(fp);
                        return;
                }
-
-               if (id<0 || id>size)
+               if (id < 0 || id > size)
                        continue;
 
                tab[id] = strdup(namebuf);
@@ -102,38 +117,71 @@ static void rtnl_tab_initialize(char *file, char **tab, int size)
        fclose(fp);
 }
 
-static char * rtnl_rtprot_tab[256] = {
-       [RTPROT_UNSPEC] = "none",
-       [RTPROT_REDIRECT] ="redirect",
-       [RTPROT_KERNEL] = "kernel",
-       [RTPROT_BOOT] = "boot",
-       [RTPROT_STATIC] = "static",
-
-       [RTPROT_GATED] = "gated",
-       [RTPROT_RA] = "ra",
-       [RTPROT_MRT] =  "mrt",
-       [RTPROT_ZEBRA] ="zebra",
-       [RTPROT_BIRD] = "bird",
+static char *rtnl_rtprot_tab[256] = {
+       [RTPROT_UNSPEC]   = "unspec",
+       [RTPROT_REDIRECT] = "redirect",
+       [RTPROT_KERNEL]   = "kernel",
+       [RTPROT_BOOT]     = "boot",
+       [RTPROT_STATIC]   = "static",
+
+       [RTPROT_GATED]    = "gated",
+       [RTPROT_RA]       = "ra",
+       [RTPROT_MRT]      = "mrt",
+       [RTPROT_ZEBRA]    = "zebra",
+       [RTPROT_BIRD]     = "bird",
+       [RTPROT_BABEL]    = "babel",
        [RTPROT_DNROUTED] = "dnrouted",
-       [RTPROT_XORP] = "xorp",
-       [RTPROT_NTK] = "ntk",
+       [RTPROT_XORP]     = "xorp",
+       [RTPROT_NTK]      = "ntk",
+       [RTPROT_DHCP]     = "dhcp",
+       [RTPROT_BGP]      = "bgp",
+       [RTPROT_ISIS]     = "isis",
+       [RTPROT_OSPF]     = "ospf",
+       [RTPROT_RIP]      = "rip",
+       [RTPROT_EIGRP]    = "eigrp",
 };
 
 
-
 static int rtnl_rtprot_init;
 
 static void rtnl_rtprot_initialize(void)
 {
+       struct dirent *de;
+       DIR *d;
+
        rtnl_rtprot_init = 1;
-       rtnl_tab_initialize("/etc/iproute2/rt_protos",
+       rtnl_tab_initialize(CONFDIR "/rt_protos",
                            rtnl_rtprot_tab, 256);
+
+       d = opendir(CONFDIR "/rt_protos.d");
+       if (!d)
+               return;
+
+       while ((de = readdir(d)) != NULL) {
+               char path[PATH_MAX];
+               size_t len;
+
+               if (*de->d_name == '.')
+                       continue;
+
+               /* only consider filenames ending in '.conf' */
+               len = strlen(de->d_name);
+               if (len <= 5)
+                       continue;
+               if (strcmp(de->d_name + len - 5, ".conf"))
+                       continue;
+
+               snprintf(path, sizeof(path), CONFDIR "/rt_protos.d/%s",
+                        de->d_name);
+               rtnl_tab_initialize(path, rtnl_rtprot_tab, 256);
+       }
+       closedir(d);
 }
 
-char * rtnl_rtprot_n2a(int id, char *buf, int len)
+const char *rtnl_rtprot_n2a(int id, char *buf, int len)
 {
-       if (id<0 || id>=256) {
-               snprintf(buf, len, "%d", id);
+       if (id < 0 || id >= 256) {
+               snprintf(buf, len, "%u", id);
                return buf;
        }
        if (!rtnl_rtprot_tab[id]) {
@@ -142,13 +190,13 @@ char * rtnl_rtprot_n2a(int id, char *buf, int len)
        }
        if (rtnl_rtprot_tab[id])
                return rtnl_rtprot_tab[id];
-       snprintf(buf, len, "%d", id);
+       snprintf(buf, len, "%u", id);
        return buf;
 }
 
-int rtnl_rtprot_a2n(__u32 *id, char *arg)
+int rtnl_rtprot_a2n(__u32 *id, const char *arg)
 {
-       static char *cache = NULL;
+       static char *cache;
        static unsigned long res;
        char *end;
        int i;
@@ -161,7 +209,7 @@ int rtnl_rtprot_a2n(__u32 *id, char *arg)
        if (!rtnl_rtprot_init)
                rtnl_rtprot_initialize();
 
-       for (i=0; i<256; i++) {
+       for (i = 0; i < 256; i++) {
                if (rtnl_rtprot_tab[i] &&
                    strcmp(rtnl_rtprot_tab[i], arg) == 0) {
                        cache = rtnl_rtprot_tab[i];
@@ -179,9 +227,12 @@ int rtnl_rtprot_a2n(__u32 *id, char *arg)
 }
 
 
-
-static char * rtnl_rtscope_tab[256] = {
-       "global",
+static char *rtnl_rtscope_tab[256] = {
+       [RT_SCOPE_UNIVERSE]     = "global",
+       [RT_SCOPE_NOWHERE]      = "nowhere",
+       [RT_SCOPE_HOST]         = "host",
+       [RT_SCOPE_LINK]         = "link",
+       [RT_SCOPE_SITE]         = "site",
 };
 
 static int rtnl_rtscope_init;
@@ -189,33 +240,32 @@ static int rtnl_rtscope_init;
 static void rtnl_rtscope_initialize(void)
 {
        rtnl_rtscope_init = 1;
-       rtnl_rtscope_tab[255] = "nowhere";
-       rtnl_rtscope_tab[254] = "host";
-       rtnl_rtscope_tab[253] = "link";
-       rtnl_rtscope_tab[200] = "site";
-       rtnl_tab_initialize("/etc/iproute2/rt_scopes",
+       rtnl_tab_initialize(CONFDIR "/rt_scopes",
                            rtnl_rtscope_tab, 256);
 }
 
-char * rtnl_rtscope_n2a(int id, char *buf, int len)
+const char *rtnl_rtscope_n2a(int id, char *buf, int len)
 {
-       if (id<0 || id>=256) {
+       if (id < 0 || id >= 256) {
                snprintf(buf, len, "%d", id);
                return buf;
        }
+
        if (!rtnl_rtscope_tab[id]) {
                if (!rtnl_rtscope_init)
                        rtnl_rtscope_initialize();
        }
+
        if (rtnl_rtscope_tab[id])
                return rtnl_rtscope_tab[id];
+
        snprintf(buf, len, "%d", id);
        return buf;
 }
 
-int rtnl_rtscope_a2n(__u32 *id, char *arg)
+int rtnl_rtscope_a2n(__u32 *id, const char *arg)
 {
-       static char *cache = NULL;
+       static const char *cache;
        static unsigned long res;
        char *end;
        int i;
@@ -228,7 +278,7 @@ int rtnl_rtscope_a2n(__u32 *id, char *arg)
        if (!rtnl_rtscope_init)
                rtnl_rtscope_initialize();
 
-       for (i=0; i<256; i++) {
+       for (i = 0; i < 256; i++) {
                if (rtnl_rtscope_tab[i] &&
                    strcmp(rtnl_rtscope_tab[i], arg) == 0) {
                        cache = rtnl_rtscope_tab[i];
@@ -246,8 +296,7 @@ int rtnl_rtscope_a2n(__u32 *id, char *arg)
 }
 
 
-
-static char * rtnl_rtrealm_tab[256] = {
+static char *rtnl_rtrealm_tab[256] = {
        "unknown",
 };
 
@@ -256,13 +305,13 @@ static int rtnl_rtrealm_init;
 static void rtnl_rtrealm_initialize(void)
 {
        rtnl_rtrealm_init = 1;
-       rtnl_tab_initialize("/etc/iproute2/rt_realms",
+       rtnl_tab_initialize(CONFDIR "/rt_realms",
                            rtnl_rtrealm_tab, 256);
 }
 
-char * rtnl_rtrealm_n2a(int id, char *buf, int len)
+const char *rtnl_rtrealm_n2a(int id, char *buf, int len)
 {
-       if (id<0 || id>=256) {
+       if (id < 0 || id >= 256) {
                snprintf(buf, len, "%d", id);
                return buf;
        }
@@ -277,9 +326,9 @@ char * rtnl_rtrealm_n2a(int id, char *buf, int len)
 }
 
 
-int rtnl_rtrealm_a2n(__u32 *id, char *arg)
+int rtnl_rtrealm_a2n(__u32 *id, const char *arg)
 {
-       static char *cache = NULL;
+       static char *cache;
        static unsigned long res;
        char *end;
        int i;
@@ -292,7 +341,7 @@ int rtnl_rtrealm_a2n(__u32 *id, char *arg)
        if (!rtnl_rtrealm_init)
                rtnl_rtrealm_initialize();
 
-       for (i=0; i<256; i++) {
+       for (i = 0; i < 256; i++) {
                if (rtnl_rtrealm_tab[i] &&
                    strcmp(rtnl_rtrealm_tab[i], arg) == 0) {
                        cache = rtnl_rtrealm_tab[i];
@@ -310,33 +359,61 @@ int rtnl_rtrealm_a2n(__u32 *id, char *arg)
 }
 
 
-static struct rtnl_hash_entry dflt_table_entry  = { .id = 253, .name = "default" };
-static struct rtnl_hash_entry main_table_entry  = { .id = 254, .name = "main" };
-static struct rtnl_hash_entry local_table_entry = { .id = 255, .name = "local" };
+static struct rtnl_hash_entry dflt_table_entry  = { .name = "default" };
+static struct rtnl_hash_entry main_table_entry  = { .name = "main" };
+static struct rtnl_hash_entry local_table_entry = { .name = "local" };
 
-static struct rtnl_hash_entry * rtnl_rttable_hash[256] = {
-       [253] = &dflt_table_entry,
-       [254] = &main_table_entry,
-       [255] = &local_table_entry,
+static struct rtnl_hash_entry *rtnl_rttable_hash[256] = {
+       [RT_TABLE_DEFAULT] = &dflt_table_entry,
+       [RT_TABLE_MAIN]    = &main_table_entry,
+       [RT_TABLE_LOCAL]   = &local_table_entry,
 };
 
 static int rtnl_rttable_init;
 
 static void rtnl_rttable_initialize(void)
 {
+       struct dirent *de;
+       DIR *d;
+       int i;
+
        rtnl_rttable_init = 1;
-       rtnl_hash_initialize("/etc/iproute2/rt_tables",
+       for (i = 0; i < 256; i++) {
+               if (rtnl_rttable_hash[i])
+                       rtnl_rttable_hash[i]->id = i;
+       }
+       rtnl_hash_initialize(CONFDIR "/rt_tables",
                             rtnl_rttable_hash, 256);
+
+       d = opendir(CONFDIR "/rt_tables.d");
+       if (!d)
+               return;
+
+       while ((de = readdir(d)) != NULL) {
+               char path[PATH_MAX];
+               size_t len;
+
+               if (*de->d_name == '.')
+                       continue;
+
+               /* only consider filenames ending in '.conf' */
+               len = strlen(de->d_name);
+               if (len <= 5)
+                       continue;
+               if (strcmp(de->d_name + len - 5, ".conf"))
+                       continue;
+
+               snprintf(path, sizeof(path),
+                        CONFDIR "/rt_tables.d/%s", de->d_name);
+               rtnl_hash_initialize(path, rtnl_rttable_hash, 256);
+       }
+       closedir(d);
 }
 
-char * rtnl_rttable_n2a(int id, char *buf, int len)
+const char *rtnl_rttable_n2a(__u32 id, char *buf, int len)
 {
        struct rtnl_hash_entry *entry;
 
-       if (id >= RT_TABLE_MAX) {
-               snprintf(buf, len, "%u", id);
-               return buf;
-       }
        if (!rtnl_rttable_init)
                rtnl_rttable_initialize();
        entry = rtnl_rttable_hash[id & 255];
@@ -348,13 +425,13 @@ char * rtnl_rttable_n2a(int id, char *buf, int len)
        return buf;
 }
 
-int rtnl_rttable_a2n(__u32 *id, char *arg)
+int rtnl_rttable_a2n(__u32 *id, const char *arg)
 {
-       static char *cache = NULL;
+       static const char *cache;
        static unsigned long res;
        struct rtnl_hash_entry *entry;
        char *end;
-       int i;
+       unsigned long i;
 
        if (cache && strcmp(cache, arg) == 0) {
                *id = res;
@@ -364,7 +441,7 @@ int rtnl_rttable_a2n(__u32 *id, char *arg)
        if (!rtnl_rttable_init)
                rtnl_rttable_initialize();
 
-       for (i=0; i<256; i++) {
+       for (i = 0; i < 256; i++) {
                entry = rtnl_rttable_hash[i];
                while (entry && strcmp(entry->name, arg))
                        entry = entry->next;
@@ -384,7 +461,7 @@ int rtnl_rttable_a2n(__u32 *id, char *arg)
 }
 
 
-static char * rtnl_rtdsfield_tab[256] = {
+static char *rtnl_rtdsfield_tab[256] = {
        "0",
 };
 
@@ -393,13 +470,13 @@ static int rtnl_rtdsfield_init;
 static void rtnl_rtdsfield_initialize(void)
 {
        rtnl_rtdsfield_init = 1;
-       rtnl_tab_initialize("/etc/iproute2/rt_dsfield",
+       rtnl_tab_initialize(CONFDIR "/rt_dsfield",
                            rtnl_rtdsfield_tab, 256);
 }
 
-char * rtnl_dsfield_n2a(int id, char *buf, int len)
+const char *rtnl_dsfield_n2a(int id, char *buf, int len)
 {
-       if (id<0 || id>=256) {
+       if (id < 0 || id >= 256) {
                snprintf(buf, len, "%d", id);
                return buf;
        }
@@ -414,9 +491,9 @@ char * rtnl_dsfield_n2a(int id, char *buf, int len)
 }
 
 
-int rtnl_dsfield_a2n(__u32 *id, char *arg)
+int rtnl_dsfield_a2n(__u32 *id, const char *arg)
 {
-       static char *cache = NULL;
+       static char *cache;
        static unsigned long res;
        char *end;
        int i;
@@ -429,7 +506,7 @@ int rtnl_dsfield_a2n(__u32 *id, char *arg)
        if (!rtnl_rtdsfield_init)
                rtnl_rtdsfield_initialize();
 
-       for (i=0; i<256; i++) {
+       for (i = 0; i < 256; i++) {
                if (rtnl_rtdsfield_tab[i] &&
                    strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
                        cache = rtnl_rtdsfield_tab[i];
@@ -446,3 +523,159 @@ int rtnl_dsfield_a2n(__u32 *id, char *arg)
        return 0;
 }
 
+
+static struct rtnl_hash_entry dflt_group_entry = {
+       .id = 0, .name = "default"
+};
+
+static struct rtnl_hash_entry *rtnl_group_hash[256] = {
+       [0] = &dflt_group_entry,
+};
+
+static int rtnl_group_init;
+
+static void rtnl_group_initialize(void)
+{
+       rtnl_group_init = 1;
+       rtnl_hash_initialize(CONFDIR "/group",
+                            rtnl_group_hash, 256);
+}
+
+int rtnl_group_a2n(int *id, const char *arg)
+{
+       static const char *cache;
+       static unsigned long res;
+       struct rtnl_hash_entry *entry;
+       char *end;
+       int i;
+
+       if (cache && strcmp(cache, arg) == 0) {
+               *id = res;
+               return 0;
+       }
+
+       if (!rtnl_group_init)
+               rtnl_group_initialize();
+
+       for (i = 0; i < 256; i++) {
+               entry = rtnl_group_hash[i];
+               while (entry && strcmp(entry->name, arg))
+                       entry = entry->next;
+               if (entry) {
+                       cache = entry->name;
+                       res = entry->id;
+                       *id = res;
+                       return 0;
+               }
+       }
+
+       i = strtol(arg, &end, 0);
+       if (!end || end == arg || *end || i < 0)
+               return -1;
+       *id = i;
+       return 0;
+}
+
+const char *rtnl_group_n2a(int id, char *buf, int len)
+{
+       struct rtnl_hash_entry *entry;
+       int i;
+
+       if (!rtnl_group_init)
+               rtnl_group_initialize();
+
+       for (i = 0; i < 256; i++) {
+               entry = rtnl_group_hash[i];
+
+               while (entry) {
+                       if (entry->id == id)
+                               return entry->name;
+                       entry = entry->next;
+               }
+       }
+
+       snprintf(buf, len, "%d", id);
+       return buf;
+}
+
+static char *nl_proto_tab[256] = {
+       [NETLINK_ROUTE]          = "rtnl",
+       [NETLINK_UNUSED]         = "unused",
+       [NETLINK_USERSOCK]       = "usersock",
+       [NETLINK_FIREWALL]       = "fw",
+       [NETLINK_SOCK_DIAG]      = "tcpdiag",
+       [NETLINK_NFLOG]          = "nflog",
+       [NETLINK_XFRM]           = "xfrm",
+       [NETLINK_SELINUX]        = "selinux",
+       [NETLINK_ISCSI]          = "iscsi",
+       [NETLINK_AUDIT]          = "audit",
+       [NETLINK_FIB_LOOKUP]     = "fiblookup",
+       [NETLINK_CONNECTOR]      = "connector",
+       [NETLINK_NETFILTER]      = "nft",
+       [NETLINK_IP6_FW]         = "ip6fw",
+       [NETLINK_DNRTMSG]        = "dec-rt",
+       [NETLINK_KOBJECT_UEVENT] = "uevent",
+       [NETLINK_GENERIC]        = "genl",
+       [NETLINK_SCSITRANSPORT]  = "scsi-trans",
+       [NETLINK_ECRYPTFS]       = "ecryptfs",
+       [NETLINK_RDMA]           = "rdma",
+       [NETLINK_CRYPTO]         = "crypto",
+};
+
+static int nl_proto_init;
+
+static void nl_proto_initialize(void)
+{
+       nl_proto_init = 1;
+       rtnl_tab_initialize(CONFDIR "/nl_protos",
+                           nl_proto_tab, 256);
+}
+
+const char *nl_proto_n2a(int id, char *buf, int len)
+{
+       if (id < 0 || id >= 256) {
+               snprintf(buf, len, "%u", id);
+               return buf;
+       }
+
+       if (!nl_proto_init)
+               nl_proto_initialize();
+
+       if (nl_proto_tab[id])
+               return nl_proto_tab[id];
+
+       snprintf(buf, len, "%u", id);
+       return buf;
+}
+
+int nl_proto_a2n(__u32 *id, const char *arg)
+{
+       static char *cache;
+       static unsigned long res;
+       char *end;
+       int i;
+
+       if (cache && strcmp(cache, arg) == 0) {
+               *id = res;
+               return 0;
+       }
+
+       if (!nl_proto_init)
+               nl_proto_initialize();
+
+       for (i = 0; i < 256; i++) {
+               if (nl_proto_tab[i] &&
+                   strcmp(nl_proto_tab[i], arg) == 0) {
+                       cache = nl_proto_tab[i];
+                       res = i;
+                       *id = res;
+                       return 0;
+               }
+       }
+
+       res = strtoul(arg, &end, 0);
+       if (!end || end == arg || *end || res > 255)
+               return -1;
+       *id = res;
+       return 0;
+}