2 * rt_names.c rtnetlink names DB.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
18 #include <sys/socket.h>
22 #include <asm/types.h>
23 #include <linux/rtnetlink.h>
28 #define NAME_MAX_LEN 512
30 struct rtnl_hash_entry
{
31 struct rtnl_hash_entry
*next
;
36 static int fread_id_name(FILE *fp
, int *id
, char *namebuf
)
38 char buf
[NAME_MAX_LEN
];
40 while (fgets(buf
, sizeof(buf
), fp
)) {
43 while (*p
== ' ' || *p
== '\t')
46 if (*p
== '#' || *p
== '\n' || *p
== 0)
49 if (sscanf(p
, "0x%x %s\n", id
, namebuf
) != 2 &&
50 sscanf(p
, "0x%x %s #", id
, namebuf
) != 2 &&
51 sscanf(p
, "%d %s\n", id
, namebuf
) != 2 &&
52 sscanf(p
, "%d %s #", id
, namebuf
) != 2) {
62 rtnl_hash_initialize(const char *file
, struct rtnl_hash_entry
**hash
, int size
)
64 struct rtnl_hash_entry
*entry
;
67 char namebuf
[NAME_MAX_LEN
] = {0};
70 fp
= fopen(file
, "r");
74 while ((ret
= fread_id_name(fp
, &id
, &namebuf
[0]))) {
76 fprintf(stderr
, "Database %s is corrupted at %s\n",
85 entry
= malloc(sizeof(*entry
));
87 entry
->name
= strdup(namebuf
);
88 entry
->next
= hash
[id
& (size
- 1)];
89 hash
[id
& (size
- 1)] = entry
;
94 static void rtnl_tab_initialize(const char *file
, char **tab
, int size
)
98 char namebuf
[NAME_MAX_LEN
] = {0};
101 fp
= fopen(file
, "r");
105 while ((ret
= fread_id_name(fp
, &id
, &namebuf
[0]))) {
107 fprintf(stderr
, "Database %s is corrupted at %s\n",
112 if (id
< 0 || id
> size
)
115 tab
[id
] = strdup(namebuf
);
120 static char *rtnl_rtprot_tab
[256] = {
121 [RTPROT_UNSPEC
] = "unspec",
122 [RTPROT_REDIRECT
] = "redirect",
123 [RTPROT_KERNEL
] = "kernel",
124 [RTPROT_BOOT
] = "boot",
125 [RTPROT_STATIC
] = "static",
127 [RTPROT_GATED
] = "gated",
129 [RTPROT_MRT
] = "mrt",
130 [RTPROT_ZEBRA
] = "zebra",
131 [RTPROT_BIRD
] = "bird",
132 [RTPROT_BABEL
] = "babel",
133 [RTPROT_DNROUTED
] = "dnrouted",
134 [RTPROT_XORP
] = "xorp",
135 [RTPROT_NTK
] = "ntk",
136 [RTPROT_DHCP
] = "dhcp",
140 static int rtnl_rtprot_init
;
142 static void rtnl_rtprot_initialize(void)
147 rtnl_rtprot_init
= 1;
148 rtnl_tab_initialize(CONFDIR
"/rt_protos",
149 rtnl_rtprot_tab
, 256);
151 d
= opendir(CONFDIR
"/rt_protos.d");
155 while ((de
= readdir(d
)) != NULL
) {
159 if (*de
->d_name
== '.')
162 /* only consider filenames ending in '.conf' */
163 len
= strlen(de
->d_name
);
166 if (strcmp(de
->d_name
+ len
- 5, ".conf"))
169 snprintf(path
, sizeof(path
), CONFDIR
"/rt_protos.d/%s",
171 rtnl_tab_initialize(path
, rtnl_rtprot_tab
, 256);
176 const char *rtnl_rtprot_n2a(int id
, char *buf
, int len
)
178 if (id
< 0 || id
>= 256) {
179 snprintf(buf
, len
, "%u", id
);
182 if (!rtnl_rtprot_tab
[id
]) {
183 if (!rtnl_rtprot_init
)
184 rtnl_rtprot_initialize();
186 if (rtnl_rtprot_tab
[id
])
187 return rtnl_rtprot_tab
[id
];
188 snprintf(buf
, len
, "%u", id
);
192 int rtnl_rtprot_a2n(__u32
*id
, const char *arg
)
195 static unsigned long res
;
199 if (cache
&& strcmp(cache
, arg
) == 0) {
204 if (!rtnl_rtprot_init
)
205 rtnl_rtprot_initialize();
207 for (i
= 0; i
< 256; i
++) {
208 if (rtnl_rtprot_tab
[i
] &&
209 strcmp(rtnl_rtprot_tab
[i
], arg
) == 0) {
210 cache
= rtnl_rtprot_tab
[i
];
217 res
= strtoul(arg
, &end
, 0);
218 if (!end
|| end
== arg
|| *end
|| res
> 255)
225 static char *rtnl_rtscope_tab
[256] = {
226 [RT_SCOPE_UNIVERSE
] = "global",
227 [RT_SCOPE_NOWHERE
] = "nowhere",
228 [RT_SCOPE_HOST
] = "host",
229 [RT_SCOPE_LINK
] = "link",
230 [RT_SCOPE_SITE
] = "site",
233 static int rtnl_rtscope_init
;
235 static void rtnl_rtscope_initialize(void)
237 rtnl_rtscope_init
= 1;
238 rtnl_tab_initialize(CONFDIR
"/rt_scopes",
239 rtnl_rtscope_tab
, 256);
242 const char *rtnl_rtscope_n2a(int id
, char *buf
, int len
)
244 if (id
< 0 || id
>= 256) {
245 snprintf(buf
, len
, "%d", id
);
249 if (!rtnl_rtscope_tab
[id
]) {
250 if (!rtnl_rtscope_init
)
251 rtnl_rtscope_initialize();
254 if (rtnl_rtscope_tab
[id
])
255 return rtnl_rtscope_tab
[id
];
257 snprintf(buf
, len
, "%d", id
);
261 int rtnl_rtscope_a2n(__u32
*id
, const char *arg
)
263 static const char *cache
;
264 static unsigned long res
;
268 if (cache
&& strcmp(cache
, arg
) == 0) {
273 if (!rtnl_rtscope_init
)
274 rtnl_rtscope_initialize();
276 for (i
= 0; i
< 256; i
++) {
277 if (rtnl_rtscope_tab
[i
] &&
278 strcmp(rtnl_rtscope_tab
[i
], arg
) == 0) {
279 cache
= rtnl_rtscope_tab
[i
];
286 res
= strtoul(arg
, &end
, 0);
287 if (!end
|| end
== arg
|| *end
|| res
> 255)
294 static char *rtnl_rtrealm_tab
[256] = {
298 static int rtnl_rtrealm_init
;
300 static void rtnl_rtrealm_initialize(void)
302 rtnl_rtrealm_init
= 1;
303 rtnl_tab_initialize(CONFDIR
"/rt_realms",
304 rtnl_rtrealm_tab
, 256);
307 const char *rtnl_rtrealm_n2a(int id
, char *buf
, int len
)
309 if (id
< 0 || id
>= 256) {
310 snprintf(buf
, len
, "%d", id
);
313 if (!rtnl_rtrealm_tab
[id
]) {
314 if (!rtnl_rtrealm_init
)
315 rtnl_rtrealm_initialize();
317 if (rtnl_rtrealm_tab
[id
])
318 return rtnl_rtrealm_tab
[id
];
319 snprintf(buf
, len
, "%d", id
);
324 int rtnl_rtrealm_a2n(__u32
*id
, const char *arg
)
327 static unsigned long res
;
331 if (cache
&& strcmp(cache
, arg
) == 0) {
336 if (!rtnl_rtrealm_init
)
337 rtnl_rtrealm_initialize();
339 for (i
= 0; i
< 256; i
++) {
340 if (rtnl_rtrealm_tab
[i
] &&
341 strcmp(rtnl_rtrealm_tab
[i
], arg
) == 0) {
342 cache
= rtnl_rtrealm_tab
[i
];
349 res
= strtoul(arg
, &end
, 0);
350 if (!end
|| end
== arg
|| *end
|| res
> 255)
357 static struct rtnl_hash_entry dflt_table_entry
= { .name
= "default" };
358 static struct rtnl_hash_entry main_table_entry
= { .name
= "main" };
359 static struct rtnl_hash_entry local_table_entry
= { .name
= "local" };
361 static struct rtnl_hash_entry
*rtnl_rttable_hash
[256] = {
362 [RT_TABLE_DEFAULT
] = &dflt_table_entry
,
363 [RT_TABLE_MAIN
] = &main_table_entry
,
364 [RT_TABLE_LOCAL
] = &local_table_entry
,
367 static int rtnl_rttable_init
;
369 static void rtnl_rttable_initialize(void)
375 rtnl_rttable_init
= 1;
376 for (i
= 0; i
< 256; i
++) {
377 if (rtnl_rttable_hash
[i
])
378 rtnl_rttable_hash
[i
]->id
= i
;
380 rtnl_hash_initialize(CONFDIR
"/rt_tables",
381 rtnl_rttable_hash
, 256);
383 d
= opendir(CONFDIR
"/rt_tables.d");
387 while ((de
= readdir(d
)) != NULL
) {
391 if (*de
->d_name
== '.')
394 /* only consider filenames ending in '.conf' */
395 len
= strlen(de
->d_name
);
398 if (strcmp(de
->d_name
+ len
- 5, ".conf"))
401 snprintf(path
, sizeof(path
),
402 CONFDIR
"/rt_tables.d/%s", de
->d_name
);
403 rtnl_hash_initialize(path
, rtnl_rttable_hash
, 256);
408 const char *rtnl_rttable_n2a(__u32 id
, char *buf
, int len
)
410 struct rtnl_hash_entry
*entry
;
412 if (!rtnl_rttable_init
)
413 rtnl_rttable_initialize();
414 entry
= rtnl_rttable_hash
[id
& 255];
415 while (entry
&& entry
->id
!= id
)
419 snprintf(buf
, len
, "%u", id
);
423 int rtnl_rttable_a2n(__u32
*id
, const char *arg
)
425 static const char *cache
;
426 static unsigned long res
;
427 struct rtnl_hash_entry
*entry
;
431 if (cache
&& strcmp(cache
, arg
) == 0) {
436 if (!rtnl_rttable_init
)
437 rtnl_rttable_initialize();
439 for (i
= 0; i
< 256; i
++) {
440 entry
= rtnl_rttable_hash
[i
];
441 while (entry
&& strcmp(entry
->name
, arg
))
451 i
= strtoul(arg
, &end
, 0);
452 if (!end
|| end
== arg
|| *end
|| i
> RT_TABLE_MAX
)
459 static char *rtnl_rtdsfield_tab
[256] = {
463 static int rtnl_rtdsfield_init
;
465 static void rtnl_rtdsfield_initialize(void)
467 rtnl_rtdsfield_init
= 1;
468 rtnl_tab_initialize(CONFDIR
"/rt_dsfield",
469 rtnl_rtdsfield_tab
, 256);
472 const char *rtnl_dsfield_n2a(int id
, char *buf
, int len
)
474 if (id
< 0 || id
>= 256) {
475 snprintf(buf
, len
, "%d", id
);
478 if (!rtnl_rtdsfield_tab
[id
]) {
479 if (!rtnl_rtdsfield_init
)
480 rtnl_rtdsfield_initialize();
482 if (rtnl_rtdsfield_tab
[id
])
483 return rtnl_rtdsfield_tab
[id
];
484 snprintf(buf
, len
, "0x%02x", id
);
489 int rtnl_dsfield_a2n(__u32
*id
, const char *arg
)
492 static unsigned long res
;
496 if (cache
&& strcmp(cache
, arg
) == 0) {
501 if (!rtnl_rtdsfield_init
)
502 rtnl_rtdsfield_initialize();
504 for (i
= 0; i
< 256; i
++) {
505 if (rtnl_rtdsfield_tab
[i
] &&
506 strcmp(rtnl_rtdsfield_tab
[i
], arg
) == 0) {
507 cache
= rtnl_rtdsfield_tab
[i
];
514 res
= strtoul(arg
, &end
, 16);
515 if (!end
|| end
== arg
|| *end
|| res
> 255)
522 static struct rtnl_hash_entry dflt_group_entry
= {
523 .id
= 0, .name
= "default"
526 static struct rtnl_hash_entry
*rtnl_group_hash
[256] = {
527 [0] = &dflt_group_entry
,
530 static int rtnl_group_init
;
532 static void rtnl_group_initialize(void)
535 rtnl_hash_initialize(CONFDIR
"/group",
536 rtnl_group_hash
, 256);
539 int rtnl_group_a2n(int *id
, const char *arg
)
541 static const char *cache
;
542 static unsigned long res
;
543 struct rtnl_hash_entry
*entry
;
547 if (cache
&& strcmp(cache
, arg
) == 0) {
552 if (!rtnl_group_init
)
553 rtnl_group_initialize();
555 for (i
= 0; i
< 256; i
++) {
556 entry
= rtnl_group_hash
[i
];
557 while (entry
&& strcmp(entry
->name
, arg
))
567 i
= strtol(arg
, &end
, 0);
568 if (!end
|| end
== arg
|| *end
|| i
< 0)
574 const char *rtnl_group_n2a(int id
, char *buf
, int len
)
576 struct rtnl_hash_entry
*entry
;
579 if (!rtnl_group_init
)
580 rtnl_group_initialize();
582 for (i
= 0; i
< 256; i
++) {
583 entry
= rtnl_group_hash
[i
];
592 snprintf(buf
, len
, "%d", id
);
596 static char *nl_proto_tab
[256] = {
597 [NETLINK_ROUTE
] = "rtnl",
598 [NETLINK_UNUSED
] = "unused",
599 [NETLINK_USERSOCK
] = "usersock",
600 [NETLINK_FIREWALL
] = "fw",
601 [NETLINK_SOCK_DIAG
] = "tcpdiag",
602 [NETLINK_NFLOG
] = "nflog",
603 [NETLINK_XFRM
] = "xfrm",
604 [NETLINK_SELINUX
] = "selinux",
605 [NETLINK_ISCSI
] = "iscsi",
606 [NETLINK_AUDIT
] = "audit",
607 [NETLINK_FIB_LOOKUP
] = "fiblookup",
608 [NETLINK_CONNECTOR
] = "connector",
609 [NETLINK_NETFILTER
] = "nft",
610 [NETLINK_IP6_FW
] = "ip6fw",
611 [NETLINK_DNRTMSG
] = "dec-rt",
612 [NETLINK_KOBJECT_UEVENT
] = "uevent",
613 [NETLINK_GENERIC
] = "genl",
614 [NETLINK_SCSITRANSPORT
] = "scsi-trans",
615 [NETLINK_ECRYPTFS
] = "ecryptfs",
616 [NETLINK_RDMA
] = "rdma",
617 [NETLINK_CRYPTO
] = "crypto",
620 static int nl_proto_init
;
622 static void nl_proto_initialize(void)
625 rtnl_tab_initialize(CONFDIR
"/nl_protos",
629 const char *nl_proto_n2a(int id
, char *buf
, int len
)
631 if (id
< 0 || id
>= 256) {
632 snprintf(buf
, len
, "%u", id
);
637 nl_proto_initialize();
639 if (nl_proto_tab
[id
])
640 return nl_proto_tab
[id
];
642 snprintf(buf
, len
, "%u", id
);
646 int nl_proto_a2n(__u32
*id
, const char *arg
)
649 static unsigned long res
;
653 if (cache
&& strcmp(cache
, arg
) == 0) {
659 nl_proto_initialize();
661 for (i
= 0; i
< 256; i
++) {
662 if (nl_proto_tab
[i
] &&
663 strcmp(nl_proto_tab
[i
], arg
) == 0) {
664 cache
= nl_proto_tab
[i
];
671 res
= strtoul(arg
, &end
, 0);
672 if (!end
|| end
== arg
|| *end
|| res
> 255)