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