]> git.proxmox.com Git - mirror_iproute2.git/blame - lib/rt_names.c
Merge branch 'master' into next
[mirror_iproute2.git] / lib / rt_names.c
CommitLineData
aba5acdf
SH
1/*
2 * rt_names.c rtnetlink names DB.
3 *
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.
8 *
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
aba5acdf
SH
15#include <fcntl.h>
16#include <string.h>
17#include <sys/time.h>
b88fd9f4 18#include <sys/socket.h>
13ada95d 19#include <dirent.h>
4a36b4c2 20#include <limits.h>
b88fd9f4
SH
21
22#include <asm/types.h>
23#include <linux/rtnetlink.h>
24
25#include "rt_names.h"
f6793eec 26#include "utils.h"
fb72129b 27
f00073e8 28#define NAME_MAX_LEN 512
29
9c47d877 30struct rtnl_hash_entry {
68ef5072
SH
31 struct rtnl_hash_entry *next;
32 const char *name;
9c47d877
PM
33 unsigned int id;
34};
35
f00073e8 36static int fread_id_name(FILE *fp, int *id, char *namebuf)
37{
38 char buf[NAME_MAX_LEN];
39
40 while (fgets(buf, sizeof(buf), fp)) {
41 char *p = buf;
42
43 while (*p == ' ' || *p == '\t')
44 p++;
45
46 if (*p == '#' || *p == '\n' || *p == 0)
47 continue;
48
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) {
53 strcpy(namebuf, p);
54 return -1;
55 }
56 return 1;
57 }
58 return 0;
59}
60
9c47d877 61static void
46ac8a55 62rtnl_hash_initialize(const char *file, struct rtnl_hash_entry **hash, int size)
9c47d877
PM
63{
64 struct rtnl_hash_entry *entry;
9c47d877 65 FILE *fp;
f00073e8 66 int id;
67 char namebuf[NAME_MAX_LEN] = {0};
68 int ret;
9c47d877
PM
69
70 fp = fopen(file, "r");
71 if (!fp)
72 return;
9c47d877 73
f00073e8 74 while ((ret = fread_id_name(fp, &id, &namebuf[0]))) {
75 if (ret == -1) {
9c47d877 76 fprintf(stderr, "Database %s is corrupted at %s\n",
f00073e8 77 file, namebuf);
97c13582 78 fclose(fp);
9c47d877
PM
79 return;
80 }
81
68ef5072 82 if (id < 0)
9c47d877 83 continue;
f00073e8 84
9c47d877
PM
85 entry = malloc(sizeof(*entry));
86 entry->id = id;
87 entry->name = strdup(namebuf);
88 entry->next = hash[id & (size - 1)];
89 hash[id & (size - 1)] = entry;
90 }
91 fclose(fp);
92}
93
46ac8a55 94static void rtnl_tab_initialize(const char *file, char **tab, int size)
aba5acdf 95{
aba5acdf 96 FILE *fp;
f00073e8 97 int id;
98 char namebuf[NAME_MAX_LEN] = {0};
99 int ret;
aba5acdf
SH
100
101 fp = fopen(file, "r");
102 if (!fp)
103 return;
aba5acdf 104
f00073e8 105 while ((ret = fread_id_name(fp, &id, &namebuf[0]))) {
106 if (ret == -1) {
aba5acdf 107 fprintf(stderr, "Database %s is corrupted at %s\n",
f00073e8 108 file, namebuf);
97c13582 109 fclose(fp);
aba5acdf
SH
110 return;
111 }
68ef5072 112 if (id < 0 || id > size)
aba5acdf
SH
113 continue;
114
115 tab[id] = strdup(namebuf);
116 }
117 fclose(fp);
118}
119
68ef5072 120static char *rtnl_rtprot_tab[256] = {
1ca2e08b 121 [RTPROT_UNSPEC] = "unspec",
68ef5072
SH
122 [RTPROT_REDIRECT] = "redirect",
123 [RTPROT_KERNEL] = "kernel",
124 [RTPROT_BOOT] = "boot",
125 [RTPROT_STATIC] = "static",
126
127 [RTPROT_GATED] = "gated",
128 [RTPROT_RA] = "ra",
129 [RTPROT_MRT] = "mrt",
130 [RTPROT_ZEBRA] = "zebra",
131 [RTPROT_BIRD] = "bird",
132 [RTPROT_BABEL] = "babel",
b88fd9f4 133 [RTPROT_DNROUTED] = "dnrouted",
68ef5072
SH
134 [RTPROT_XORP] = "xorp",
135 [RTPROT_NTK] = "ntk",
136 [RTPROT_DHCP] = "dhcp",
a313455c
DS
137 [RTPROT_BGP] = "bgp",
138 [RTPROT_ISIS] = "isis",
139 [RTPROT_OSPF] = "ospf",
140 [RTPROT_RIP] = "rip",
141 [RTPROT_EIGRP] = "eigrp",
aba5acdf
SH
142};
143
144
aba5acdf
SH
145static int rtnl_rtprot_init;
146
147static void rtnl_rtprot_initialize(void)
148{
719e331f
DA
149 struct dirent *de;
150 DIR *d;
151
aba5acdf 152 rtnl_rtprot_init = 1;
fb72129b 153 rtnl_tab_initialize(CONFDIR "/rt_protos",
aba5acdf 154 rtnl_rtprot_tab, 256);
719e331f
DA
155
156 d = opendir(CONFDIR "/rt_protos.d");
157 if (!d)
158 return;
159
160 while ((de = readdir(d)) != NULL) {
161 char path[PATH_MAX];
162 size_t len;
163
164 if (*de->d_name == '.')
165 continue;
166
167 /* only consider filenames ending in '.conf' */
168 len = strlen(de->d_name);
169 if (len <= 5)
170 continue;
171 if (strcmp(de->d_name + len - 5, ".conf"))
172 continue;
173
174 snprintf(path, sizeof(path), CONFDIR "/rt_protos.d/%s",
175 de->d_name);
176 rtnl_tab_initialize(path, rtnl_rtprot_tab, 256);
177 }
178 closedir(d);
aba5acdf
SH
179}
180
68ef5072 181const char *rtnl_rtprot_n2a(int id, char *buf, int len)
aba5acdf 182{
68ef5072 183 if (id < 0 || id >= 256) {
46ac8a55 184 snprintf(buf, len, "%u", id);
aba5acdf
SH
185 return buf;
186 }
187 if (!rtnl_rtprot_tab[id]) {
188 if (!rtnl_rtprot_init)
189 rtnl_rtprot_initialize();
190 }
191 if (rtnl_rtprot_tab[id])
192 return rtnl_rtprot_tab[id];
46ac8a55 193 snprintf(buf, len, "%u", id);
aba5acdf
SH
194 return buf;
195}
196
46ac8a55 197int rtnl_rtprot_a2n(__u32 *id, const char *arg)
aba5acdf 198{
68ef5072 199 static char *cache;
aba5acdf
SH
200 static unsigned long res;
201 char *end;
202 int i;
203
204 if (cache && strcmp(cache, arg) == 0) {
205 *id = res;
206 return 0;
207 }
208
209 if (!rtnl_rtprot_init)
210 rtnl_rtprot_initialize();
211
68ef5072 212 for (i = 0; i < 256; i++) {
aba5acdf
SH
213 if (rtnl_rtprot_tab[i] &&
214 strcmp(rtnl_rtprot_tab[i], arg) == 0) {
215 cache = rtnl_rtprot_tab[i];
216 res = i;
217 *id = res;
218 return 0;
219 }
220 }
221
222 res = strtoul(arg, &end, 0);
223 if (!end || end == arg || *end || res > 255)
224 return -1;
225 *id = res;
226 return 0;
227}
228
68ef5072
SH
229
230static char *rtnl_rtscope_tab[256] = {
231 [RT_SCOPE_UNIVERSE] = "global",
232 [RT_SCOPE_NOWHERE] = "nowhere",
233 [RT_SCOPE_HOST] = "host",
234 [RT_SCOPE_LINK] = "link",
235 [RT_SCOPE_SITE] = "site",
aba5acdf
SH
236};
237
238static int rtnl_rtscope_init;
239
240static void rtnl_rtscope_initialize(void)
241{
242 rtnl_rtscope_init = 1;
fb72129b 243 rtnl_tab_initialize(CONFDIR "/rt_scopes",
aba5acdf
SH
244 rtnl_rtscope_tab, 256);
245}
246
46ac8a55 247const char *rtnl_rtscope_n2a(int id, char *buf, int len)
aba5acdf 248{
68ef5072 249 if (id < 0 || id >= 256) {
aba5acdf
SH
250 snprintf(buf, len, "%d", id);
251 return buf;
252 }
68ef5072 253
aba5acdf
SH
254 if (!rtnl_rtscope_tab[id]) {
255 if (!rtnl_rtscope_init)
256 rtnl_rtscope_initialize();
257 }
68ef5072 258
aba5acdf
SH
259 if (rtnl_rtscope_tab[id])
260 return rtnl_rtscope_tab[id];
68ef5072 261
aba5acdf
SH
262 snprintf(buf, len, "%d", id);
263 return buf;
264}
265
46ac8a55 266int rtnl_rtscope_a2n(__u32 *id, const char *arg)
aba5acdf 267{
68ef5072 268 static const char *cache;
aba5acdf
SH
269 static unsigned long res;
270 char *end;
271 int i;
272
273 if (cache && strcmp(cache, arg) == 0) {
274 *id = res;
275 return 0;
276 }
277
278 if (!rtnl_rtscope_init)
279 rtnl_rtscope_initialize();
280
68ef5072 281 for (i = 0; i < 256; i++) {
aba5acdf
SH
282 if (rtnl_rtscope_tab[i] &&
283 strcmp(rtnl_rtscope_tab[i], arg) == 0) {
284 cache = rtnl_rtscope_tab[i];
285 res = i;
286 *id = res;
287 return 0;
288 }
289 }
290
291 res = strtoul(arg, &end, 0);
292 if (!end || end == arg || *end || res > 255)
293 return -1;
294 *id = res;
295 return 0;
296}
297
298
68ef5072 299static char *rtnl_rtrealm_tab[256] = {
aba5acdf
SH
300 "unknown",
301};
302
303static int rtnl_rtrealm_init;
304
305static void rtnl_rtrealm_initialize(void)
306{
307 rtnl_rtrealm_init = 1;
fb72129b 308 rtnl_tab_initialize(CONFDIR "/rt_realms",
aba5acdf
SH
309 rtnl_rtrealm_tab, 256);
310}
311
46ac8a55 312const char *rtnl_rtrealm_n2a(int id, char *buf, int len)
aba5acdf 313{
68ef5072 314 if (id < 0 || id >= 256) {
aba5acdf
SH
315 snprintf(buf, len, "%d", id);
316 return buf;
317 }
318 if (!rtnl_rtrealm_tab[id]) {
319 if (!rtnl_rtrealm_init)
320 rtnl_rtrealm_initialize();
321 }
322 if (rtnl_rtrealm_tab[id])
323 return rtnl_rtrealm_tab[id];
324 snprintf(buf, len, "%d", id);
325 return buf;
326}
327
328
46ac8a55 329int rtnl_rtrealm_a2n(__u32 *id, const char *arg)
aba5acdf 330{
68ef5072 331 static char *cache;
aba5acdf
SH
332 static unsigned long res;
333 char *end;
334 int i;
335
336 if (cache && strcmp(cache, arg) == 0) {
337 *id = res;
338 return 0;
339 }
340
341 if (!rtnl_rtrealm_init)
342 rtnl_rtrealm_initialize();
343
68ef5072 344 for (i = 0; i < 256; i++) {
aba5acdf
SH
345 if (rtnl_rtrealm_tab[i] &&
346 strcmp(rtnl_rtrealm_tab[i], arg) == 0) {
347 cache = rtnl_rtrealm_tab[i];
348 res = i;
349 *id = res;
350 return 0;
351 }
352 }
353
354 res = strtoul(arg, &end, 0);
355 if (!end || end == arg || *end || res > 255)
356 return -1;
357 *id = res;
358 return 0;
359}
360
361
81ebcb2a
MY
362static struct rtnl_hash_entry dflt_table_entry = { .name = "default" };
363static struct rtnl_hash_entry main_table_entry = { .name = "main" };
364static struct rtnl_hash_entry local_table_entry = { .name = "local" };
aba5acdf 365
68ef5072 366static struct rtnl_hash_entry *rtnl_rttable_hash[256] = {
81ebcb2a
MY
367 [RT_TABLE_DEFAULT] = &dflt_table_entry,
368 [RT_TABLE_MAIN] = &main_table_entry,
369 [RT_TABLE_LOCAL] = &local_table_entry,
aba5acdf
SH
370};
371
372static int rtnl_rttable_init;
373
374static void rtnl_rttable_initialize(void)
375{
13ada95d
DA
376 struct dirent *de;
377 DIR *d;
81ebcb2a
MY
378 int i;
379
aba5acdf 380 rtnl_rttable_init = 1;
81ebcb2a
MY
381 for (i = 0; i < 256; i++) {
382 if (rtnl_rttable_hash[i])
383 rtnl_rttable_hash[i]->id = i;
384 }
fb72129b 385 rtnl_hash_initialize(CONFDIR "/rt_tables",
9c47d877 386 rtnl_rttable_hash, 256);
13ada95d
DA
387
388 d = opendir(CONFDIR "/rt_tables.d");
389 if (!d)
390 return;
391
392 while ((de = readdir(d)) != NULL) {
393 char path[PATH_MAX];
394 size_t len;
395
396 if (*de->d_name == '.')
397 continue;
398
399 /* only consider filenames ending in '.conf' */
400 len = strlen(de->d_name);
401 if (len <= 5)
402 continue;
403 if (strcmp(de->d_name + len - 5, ".conf"))
404 continue;
405
68ef5072
SH
406 snprintf(path, sizeof(path),
407 CONFDIR "/rt_tables.d/%s", de->d_name);
13ada95d
DA
408 rtnl_hash_initialize(path, rtnl_rttable_hash, 256);
409 }
410 closedir(d);
aba5acdf
SH
411}
412
68ef5072 413const char *rtnl_rttable_n2a(__u32 id, char *buf, int len)
aba5acdf 414{
9c47d877
PM
415 struct rtnl_hash_entry *entry;
416
9c47d877
PM
417 if (!rtnl_rttable_init)
418 rtnl_rttable_initialize();
419 entry = rtnl_rttable_hash[id & 255];
420 while (entry && entry->id != id)
421 entry = entry->next;
422 if (entry)
423 return entry->name;
424 snprintf(buf, len, "%u", id);
aba5acdf
SH
425 return buf;
426}
427
46ac8a55 428int rtnl_rttable_a2n(__u32 *id, const char *arg)
aba5acdf 429{
68ef5072 430 static const char *cache;
aba5acdf 431 static unsigned long res;
9c47d877 432 struct rtnl_hash_entry *entry;
aba5acdf 433 char *end;
5ffbf450 434 unsigned long i;
aba5acdf
SH
435
436 if (cache && strcmp(cache, arg) == 0) {
437 *id = res;
438 return 0;
439 }
440
441 if (!rtnl_rttable_init)
442 rtnl_rttable_initialize();
443
68ef5072 444 for (i = 0; i < 256; i++) {
9c47d877
PM
445 entry = rtnl_rttable_hash[i];
446 while (entry && strcmp(entry->name, arg))
447 entry = entry->next;
448 if (entry) {
449 cache = entry->name;
450 res = entry->id;
aba5acdf
SH
451 *id = res;
452 return 0;
453 }
454 }
455
456 i = strtoul(arg, &end, 0);
9c47d877 457 if (!end || end == arg || *end || i > RT_TABLE_MAX)
aba5acdf
SH
458 return -1;
459 *id = i;
460 return 0;
461}
462
463
68ef5072 464static char *rtnl_rtdsfield_tab[256] = {
aba5acdf
SH
465 "0",
466};
467
468static int rtnl_rtdsfield_init;
469
470static void rtnl_rtdsfield_initialize(void)
471{
472 rtnl_rtdsfield_init = 1;
fb72129b 473 rtnl_tab_initialize(CONFDIR "/rt_dsfield",
aba5acdf
SH
474 rtnl_rtdsfield_tab, 256);
475}
476
46ac8a55 477const char *rtnl_dsfield_n2a(int id, char *buf, int len)
aba5acdf 478{
68ef5072 479 if (id < 0 || id >= 256) {
aba5acdf
SH
480 snprintf(buf, len, "%d", id);
481 return buf;
482 }
483 if (!rtnl_rtdsfield_tab[id]) {
484 if (!rtnl_rtdsfield_init)
485 rtnl_rtdsfield_initialize();
486 }
487 if (rtnl_rtdsfield_tab[id])
488 return rtnl_rtdsfield_tab[id];
489 snprintf(buf, len, "0x%02x", id);
490 return buf;
491}
492
493
46ac8a55 494int rtnl_dsfield_a2n(__u32 *id, const char *arg)
aba5acdf 495{
68ef5072 496 static char *cache;
aba5acdf
SH
497 static unsigned long res;
498 char *end;
499 int i;
500
501 if (cache && strcmp(cache, arg) == 0) {
502 *id = res;
503 return 0;
504 }
505
506 if (!rtnl_rtdsfield_init)
507 rtnl_rtdsfield_initialize();
508
68ef5072 509 for (i = 0; i < 256; i++) {
aba5acdf
SH
510 if (rtnl_rtdsfield_tab[i] &&
511 strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
512 cache = rtnl_rtdsfield_tab[i];
513 res = i;
514 *id = res;
515 return 0;
516 }
517 }
518
519 res = strtoul(arg, &end, 16);
520 if (!end || end == arg || *end || res > 255)
521 return -1;
522 *id = res;
523 return 0;
524}
525
ac694c33 526
68ef5072
SH
527static struct rtnl_hash_entry dflt_group_entry = {
528 .id = 0, .name = "default"
529};
ac694c33 530
68ef5072 531static struct rtnl_hash_entry *rtnl_group_hash[256] = {
ac694c33
VD
532 [0] = &dflt_group_entry,
533};
534
535static int rtnl_group_init;
536
537static void rtnl_group_initialize(void)
538{
539 rtnl_group_init = 1;
4e5615b3 540 rtnl_hash_initialize(CONFDIR "/group",
ac694c33
VD
541 rtnl_group_hash, 256);
542}
543
46ac8a55 544int rtnl_group_a2n(int *id, const char *arg)
ac694c33 545{
68ef5072 546 static const char *cache;
ac694c33
VD
547 static unsigned long res;
548 struct rtnl_hash_entry *entry;
549 char *end;
550 int i;
551
552 if (cache && strcmp(cache, arg) == 0) {
553 *id = res;
554 return 0;
555 }
556
557 if (!rtnl_group_init)
558 rtnl_group_initialize();
559
68ef5072 560 for (i = 0; i < 256; i++) {
ac694c33
VD
561 entry = rtnl_group_hash[i];
562 while (entry && strcmp(entry->name, arg))
563 entry = entry->next;
564 if (entry) {
565 cache = entry->name;
566 res = entry->id;
567 *id = res;
568 return 0;
569 }
570 }
571
572 i = strtol(arg, &end, 0);
573 if (!end || end == arg || *end || i < 0)
574 return -1;
575 *id = i;
576 return 0;
577}
c4fdf75d
ST
578
579const char *rtnl_group_n2a(int id, char *buf, int len)
580{
581 struct rtnl_hash_entry *entry;
582 int i;
583
584 if (!rtnl_group_init)
585 rtnl_group_initialize();
586
68ef5072 587 for (i = 0; i < 256; i++) {
c4fdf75d 588 entry = rtnl_group_hash[i];
2d98dd48
ZS
589
590 while (entry) {
591 if (entry->id == id)
592 return entry->name;
593 entry = entry->next;
594 }
c4fdf75d
ST
595 }
596
597 snprintf(buf, len, "%d", id);
598 return buf;
599}
eef43b50 600
601static char *nl_proto_tab[256] = {
602 [NETLINK_ROUTE] = "rtnl",
603 [NETLINK_UNUSED] = "unused",
604 [NETLINK_USERSOCK] = "usersock",
605 [NETLINK_FIREWALL] = "fw",
606 [NETLINK_SOCK_DIAG] = "tcpdiag",
607 [NETLINK_NFLOG] = "nflog",
608 [NETLINK_XFRM] = "xfrm",
609 [NETLINK_SELINUX] = "selinux",
610 [NETLINK_ISCSI] = "iscsi",
611 [NETLINK_AUDIT] = "audit",
612 [NETLINK_FIB_LOOKUP] = "fiblookup",
613 [NETLINK_CONNECTOR] = "connector",
614 [NETLINK_NETFILTER] = "nft",
615 [NETLINK_IP6_FW] = "ip6fw",
616 [NETLINK_DNRTMSG] = "dec-rt",
617 [NETLINK_KOBJECT_UEVENT] = "uevent",
618 [NETLINK_GENERIC] = "genl",
619 [NETLINK_SCSITRANSPORT] = "scsi-trans",
620 [NETLINK_ECRYPTFS] = "ecryptfs",
621 [NETLINK_RDMA] = "rdma",
622 [NETLINK_CRYPTO] = "crypto",
623};
624
625static int nl_proto_init;
626
627static void nl_proto_initialize(void)
628{
629 nl_proto_init = 1;
630 rtnl_tab_initialize(CONFDIR "/nl_protos",
631 nl_proto_tab, 256);
632}
633
634const char *nl_proto_n2a(int id, char *buf, int len)
635{
636 if (id < 0 || id >= 256) {
637 snprintf(buf, len, "%u", id);
638 return buf;
639 }
640
641 if (!nl_proto_init)
642 nl_proto_initialize();
643
644 if (nl_proto_tab[id])
645 return nl_proto_tab[id];
646
647 snprintf(buf, len, "%u", id);
648 return buf;
649}
650
651int nl_proto_a2n(__u32 *id, const char *arg)
652{
68ef5072 653 static char *cache;
eef43b50 654 static unsigned long res;
655 char *end;
656 int i;
657
658 if (cache && strcmp(cache, arg) == 0) {
659 *id = res;
660 return 0;
661 }
662
663 if (!nl_proto_init)
664 nl_proto_initialize();
665
666 for (i = 0; i < 256; i++) {
667 if (nl_proto_tab[i] &&
668 strcmp(nl_proto_tab[i], arg) == 0) {
669 cache = nl_proto_tab[i];
670 res = i;
671 *id = res;
672 return 0;
673 }
674 }
675
676 res = strtoul(arg, &end, 0);
677 if (!end || end == arg || *end || res > 255)
678 return -1;
679 *id = res;
680 return 0;
681}