]> git.proxmox.com Git - mirror_iproute2.git/blame - lib/rt_names.c
ip-link: remove warning message
[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"
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
SH
120static char *rtnl_rtprot_tab[256] = {
121 [RTPROT_UNSPEC] = "none",
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",
aba5acdf
SH
137};
138
139
aba5acdf
SH
140static int rtnl_rtprot_init;
141
142static void rtnl_rtprot_initialize(void)
143{
144 rtnl_rtprot_init = 1;
fb72129b 145 rtnl_tab_initialize(CONFDIR "/rt_protos",
aba5acdf
SH
146 rtnl_rtprot_tab, 256);
147}
148
68ef5072 149const char *rtnl_rtprot_n2a(int id, char *buf, int len)
aba5acdf 150{
68ef5072 151 if (id < 0 || id >= 256) {
46ac8a55 152 snprintf(buf, len, "%u", id);
aba5acdf
SH
153 return buf;
154 }
155 if (!rtnl_rtprot_tab[id]) {
156 if (!rtnl_rtprot_init)
157 rtnl_rtprot_initialize();
158 }
159 if (rtnl_rtprot_tab[id])
160 return rtnl_rtprot_tab[id];
46ac8a55 161 snprintf(buf, len, "%u", id);
aba5acdf
SH
162 return buf;
163}
164
46ac8a55 165int rtnl_rtprot_a2n(__u32 *id, const char *arg)
aba5acdf 166{
68ef5072 167 static char *cache;
aba5acdf
SH
168 static unsigned long res;
169 char *end;
170 int i;
171
172 if (cache && strcmp(cache, arg) == 0) {
173 *id = res;
174 return 0;
175 }
176
177 if (!rtnl_rtprot_init)
178 rtnl_rtprot_initialize();
179
68ef5072 180 for (i = 0; i < 256; i++) {
aba5acdf
SH
181 if (rtnl_rtprot_tab[i] &&
182 strcmp(rtnl_rtprot_tab[i], arg) == 0) {
183 cache = rtnl_rtprot_tab[i];
184 res = i;
185 *id = res;
186 return 0;
187 }
188 }
189
190 res = strtoul(arg, &end, 0);
191 if (!end || end == arg || *end || res > 255)
192 return -1;
193 *id = res;
194 return 0;
195}
196
68ef5072
SH
197
198static char *rtnl_rtscope_tab[256] = {
199 [RT_SCOPE_UNIVERSE] = "global",
200 [RT_SCOPE_NOWHERE] = "nowhere",
201 [RT_SCOPE_HOST] = "host",
202 [RT_SCOPE_LINK] = "link",
203 [RT_SCOPE_SITE] = "site",
aba5acdf
SH
204};
205
206static int rtnl_rtscope_init;
207
208static void rtnl_rtscope_initialize(void)
209{
210 rtnl_rtscope_init = 1;
fb72129b 211 rtnl_tab_initialize(CONFDIR "/rt_scopes",
aba5acdf
SH
212 rtnl_rtscope_tab, 256);
213}
214
46ac8a55 215const char *rtnl_rtscope_n2a(int id, char *buf, int len)
aba5acdf 216{
68ef5072 217 if (id < 0 || id >= 256) {
aba5acdf
SH
218 snprintf(buf, len, "%d", id);
219 return buf;
220 }
68ef5072 221
aba5acdf
SH
222 if (!rtnl_rtscope_tab[id]) {
223 if (!rtnl_rtscope_init)
224 rtnl_rtscope_initialize();
225 }
68ef5072 226
aba5acdf
SH
227 if (rtnl_rtscope_tab[id])
228 return rtnl_rtscope_tab[id];
68ef5072 229
aba5acdf
SH
230 snprintf(buf, len, "%d", id);
231 return buf;
232}
233
46ac8a55 234int rtnl_rtscope_a2n(__u32 *id, const char *arg)
aba5acdf 235{
68ef5072 236 static const char *cache;
aba5acdf
SH
237 static unsigned long res;
238 char *end;
239 int i;
240
241 if (cache && strcmp(cache, arg) == 0) {
242 *id = res;
243 return 0;
244 }
245
246 if (!rtnl_rtscope_init)
247 rtnl_rtscope_initialize();
248
68ef5072 249 for (i = 0; i < 256; i++) {
aba5acdf
SH
250 if (rtnl_rtscope_tab[i] &&
251 strcmp(rtnl_rtscope_tab[i], arg) == 0) {
252 cache = rtnl_rtscope_tab[i];
253 res = i;
254 *id = res;
255 return 0;
256 }
257 }
258
259 res = strtoul(arg, &end, 0);
260 if (!end || end == arg || *end || res > 255)
261 return -1;
262 *id = res;
263 return 0;
264}
265
266
68ef5072 267static char *rtnl_rtrealm_tab[256] = {
aba5acdf
SH
268 "unknown",
269};
270
271static int rtnl_rtrealm_init;
272
273static void rtnl_rtrealm_initialize(void)
274{
275 rtnl_rtrealm_init = 1;
fb72129b 276 rtnl_tab_initialize(CONFDIR "/rt_realms",
aba5acdf
SH
277 rtnl_rtrealm_tab, 256);
278}
279
46ac8a55 280const char *rtnl_rtrealm_n2a(int id, char *buf, int len)
aba5acdf 281{
68ef5072 282 if (id < 0 || id >= 256) {
aba5acdf
SH
283 snprintf(buf, len, "%d", id);
284 return buf;
285 }
286 if (!rtnl_rtrealm_tab[id]) {
287 if (!rtnl_rtrealm_init)
288 rtnl_rtrealm_initialize();
289 }
290 if (rtnl_rtrealm_tab[id])
291 return rtnl_rtrealm_tab[id];
292 snprintf(buf, len, "%d", id);
293 return buf;
294}
295
296
46ac8a55 297int rtnl_rtrealm_a2n(__u32 *id, const char *arg)
aba5acdf 298{
68ef5072 299 static char *cache;
aba5acdf
SH
300 static unsigned long res;
301 char *end;
302 int i;
303
304 if (cache && strcmp(cache, arg) == 0) {
305 *id = res;
306 return 0;
307 }
308
309 if (!rtnl_rtrealm_init)
310 rtnl_rtrealm_initialize();
311
68ef5072 312 for (i = 0; i < 256; i++) {
aba5acdf
SH
313 if (rtnl_rtrealm_tab[i] &&
314 strcmp(rtnl_rtrealm_tab[i], arg) == 0) {
315 cache = rtnl_rtrealm_tab[i];
316 res = i;
317 *id = res;
318 return 0;
319 }
320 }
321
322 res = strtoul(arg, &end, 0);
323 if (!end || end == arg || *end || res > 255)
324 return -1;
325 *id = res;
326 return 0;
327}
328
329
81ebcb2a
MY
330static struct rtnl_hash_entry dflt_table_entry = { .name = "default" };
331static struct rtnl_hash_entry main_table_entry = { .name = "main" };
332static struct rtnl_hash_entry local_table_entry = { .name = "local" };
aba5acdf 333
68ef5072 334static struct rtnl_hash_entry *rtnl_rttable_hash[256] = {
81ebcb2a
MY
335 [RT_TABLE_DEFAULT] = &dflt_table_entry,
336 [RT_TABLE_MAIN] = &main_table_entry,
337 [RT_TABLE_LOCAL] = &local_table_entry,
aba5acdf
SH
338};
339
340static int rtnl_rttable_init;
341
342static void rtnl_rttable_initialize(void)
343{
13ada95d
DA
344 struct dirent *de;
345 DIR *d;
81ebcb2a
MY
346 int i;
347
aba5acdf 348 rtnl_rttable_init = 1;
81ebcb2a
MY
349 for (i = 0; i < 256; i++) {
350 if (rtnl_rttable_hash[i])
351 rtnl_rttable_hash[i]->id = i;
352 }
fb72129b 353 rtnl_hash_initialize(CONFDIR "/rt_tables",
9c47d877 354 rtnl_rttable_hash, 256);
13ada95d
DA
355
356 d = opendir(CONFDIR "/rt_tables.d");
357 if (!d)
358 return;
359
360 while ((de = readdir(d)) != NULL) {
361 char path[PATH_MAX];
362 size_t len;
363
364 if (*de->d_name == '.')
365 continue;
366
367 /* only consider filenames ending in '.conf' */
368 len = strlen(de->d_name);
369 if (len <= 5)
370 continue;
371 if (strcmp(de->d_name + len - 5, ".conf"))
372 continue;
373
68ef5072
SH
374 snprintf(path, sizeof(path),
375 CONFDIR "/rt_tables.d/%s", de->d_name);
13ada95d
DA
376 rtnl_hash_initialize(path, rtnl_rttable_hash, 256);
377 }
378 closedir(d);
aba5acdf
SH
379}
380
68ef5072 381const char *rtnl_rttable_n2a(__u32 id, char *buf, int len)
aba5acdf 382{
9c47d877
PM
383 struct rtnl_hash_entry *entry;
384
887a5d00 385 if (id > RT_TABLE_MAX) {
9c47d877 386 snprintf(buf, len, "%u", id);
aba5acdf
SH
387 return buf;
388 }
9c47d877
PM
389 if (!rtnl_rttable_init)
390 rtnl_rttable_initialize();
391 entry = rtnl_rttable_hash[id & 255];
392 while (entry && entry->id != id)
393 entry = entry->next;
394 if (entry)
395 return entry->name;
396 snprintf(buf, len, "%u", id);
aba5acdf
SH
397 return buf;
398}
399
46ac8a55 400int rtnl_rttable_a2n(__u32 *id, const char *arg)
aba5acdf 401{
68ef5072 402 static const char *cache;
aba5acdf 403 static unsigned long res;
9c47d877 404 struct rtnl_hash_entry *entry;
aba5acdf 405 char *end;
34e95647 406 __u32 i;
aba5acdf
SH
407
408 if (cache && strcmp(cache, arg) == 0) {
409 *id = res;
410 return 0;
411 }
412
413 if (!rtnl_rttable_init)
414 rtnl_rttable_initialize();
415
68ef5072 416 for (i = 0; i < 256; i++) {
9c47d877
PM
417 entry = rtnl_rttable_hash[i];
418 while (entry && strcmp(entry->name, arg))
419 entry = entry->next;
420 if (entry) {
421 cache = entry->name;
422 res = entry->id;
aba5acdf
SH
423 *id = res;
424 return 0;
425 }
426 }
427
428 i = strtoul(arg, &end, 0);
9c47d877 429 if (!end || end == arg || *end || i > RT_TABLE_MAX)
aba5acdf
SH
430 return -1;
431 *id = i;
432 return 0;
433}
434
435
68ef5072 436static char *rtnl_rtdsfield_tab[256] = {
aba5acdf
SH
437 "0",
438};
439
440static int rtnl_rtdsfield_init;
441
442static void rtnl_rtdsfield_initialize(void)
443{
444 rtnl_rtdsfield_init = 1;
fb72129b 445 rtnl_tab_initialize(CONFDIR "/rt_dsfield",
aba5acdf
SH
446 rtnl_rtdsfield_tab, 256);
447}
448
46ac8a55 449const char *rtnl_dsfield_n2a(int id, char *buf, int len)
aba5acdf 450{
68ef5072 451 if (id < 0 || id >= 256) {
aba5acdf
SH
452 snprintf(buf, len, "%d", id);
453 return buf;
454 }
455 if (!rtnl_rtdsfield_tab[id]) {
456 if (!rtnl_rtdsfield_init)
457 rtnl_rtdsfield_initialize();
458 }
459 if (rtnl_rtdsfield_tab[id])
460 return rtnl_rtdsfield_tab[id];
461 snprintf(buf, len, "0x%02x", id);
462 return buf;
463}
464
465
46ac8a55 466int rtnl_dsfield_a2n(__u32 *id, const char *arg)
aba5acdf 467{
68ef5072 468 static char *cache;
aba5acdf
SH
469 static unsigned long res;
470 char *end;
471 int i;
472
473 if (cache && strcmp(cache, arg) == 0) {
474 *id = res;
475 return 0;
476 }
477
478 if (!rtnl_rtdsfield_init)
479 rtnl_rtdsfield_initialize();
480
68ef5072 481 for (i = 0; i < 256; i++) {
aba5acdf
SH
482 if (rtnl_rtdsfield_tab[i] &&
483 strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
484 cache = rtnl_rtdsfield_tab[i];
485 res = i;
486 *id = res;
487 return 0;
488 }
489 }
490
491 res = strtoul(arg, &end, 16);
492 if (!end || end == arg || *end || res > 255)
493 return -1;
494 *id = res;
495 return 0;
496}
497
ac694c33 498
68ef5072
SH
499static struct rtnl_hash_entry dflt_group_entry = {
500 .id = 0, .name = "default"
501};
ac694c33 502
68ef5072 503static struct rtnl_hash_entry *rtnl_group_hash[256] = {
ac694c33
VD
504 [0] = &dflt_group_entry,
505};
506
507static int rtnl_group_init;
508
509static void rtnl_group_initialize(void)
510{
511 rtnl_group_init = 1;
4e5615b3 512 rtnl_hash_initialize(CONFDIR "/group",
ac694c33
VD
513 rtnl_group_hash, 256);
514}
515
46ac8a55 516int rtnl_group_a2n(int *id, const char *arg)
ac694c33 517{
68ef5072 518 static const char *cache;
ac694c33
VD
519 static unsigned long res;
520 struct rtnl_hash_entry *entry;
521 char *end;
522 int i;
523
524 if (cache && strcmp(cache, arg) == 0) {
525 *id = res;
526 return 0;
527 }
528
529 if (!rtnl_group_init)
530 rtnl_group_initialize();
531
68ef5072 532 for (i = 0; i < 256; i++) {
ac694c33
VD
533 entry = rtnl_group_hash[i];
534 while (entry && strcmp(entry->name, arg))
535 entry = entry->next;
536 if (entry) {
537 cache = entry->name;
538 res = entry->id;
539 *id = res;
540 return 0;
541 }
542 }
543
544 i = strtol(arg, &end, 0);
545 if (!end || end == arg || *end || i < 0)
546 return -1;
547 *id = i;
548 return 0;
549}
c4fdf75d
ST
550
551const char *rtnl_group_n2a(int id, char *buf, int len)
552{
553 struct rtnl_hash_entry *entry;
554 int i;
555
556 if (!rtnl_group_init)
557 rtnl_group_initialize();
558
68ef5072 559 for (i = 0; i < 256; i++) {
c4fdf75d 560 entry = rtnl_group_hash[i];
68ef5072 561 if (entry && entry->id == id)
c4fdf75d 562 return entry->name;
c4fdf75d
ST
563 }
564
565 snprintf(buf, len, "%d", id);
566 return buf;
567}
eef43b50 568
569static char *nl_proto_tab[256] = {
570 [NETLINK_ROUTE] = "rtnl",
571 [NETLINK_UNUSED] = "unused",
572 [NETLINK_USERSOCK] = "usersock",
573 [NETLINK_FIREWALL] = "fw",
574 [NETLINK_SOCK_DIAG] = "tcpdiag",
575 [NETLINK_NFLOG] = "nflog",
576 [NETLINK_XFRM] = "xfrm",
577 [NETLINK_SELINUX] = "selinux",
578 [NETLINK_ISCSI] = "iscsi",
579 [NETLINK_AUDIT] = "audit",
580 [NETLINK_FIB_LOOKUP] = "fiblookup",
581 [NETLINK_CONNECTOR] = "connector",
582 [NETLINK_NETFILTER] = "nft",
583 [NETLINK_IP6_FW] = "ip6fw",
584 [NETLINK_DNRTMSG] = "dec-rt",
585 [NETLINK_KOBJECT_UEVENT] = "uevent",
586 [NETLINK_GENERIC] = "genl",
587 [NETLINK_SCSITRANSPORT] = "scsi-trans",
588 [NETLINK_ECRYPTFS] = "ecryptfs",
589 [NETLINK_RDMA] = "rdma",
590 [NETLINK_CRYPTO] = "crypto",
591};
592
593static int nl_proto_init;
594
595static void nl_proto_initialize(void)
596{
597 nl_proto_init = 1;
598 rtnl_tab_initialize(CONFDIR "/nl_protos",
599 nl_proto_tab, 256);
600}
601
602const char *nl_proto_n2a(int id, char *buf, int len)
603{
604 if (id < 0 || id >= 256) {
605 snprintf(buf, len, "%u", id);
606 return buf;
607 }
608
609 if (!nl_proto_init)
610 nl_proto_initialize();
611
612 if (nl_proto_tab[id])
613 return nl_proto_tab[id];
614
615 snprintf(buf, len, "%u", id);
616 return buf;
617}
618
619int nl_proto_a2n(__u32 *id, const char *arg)
620{
68ef5072 621 static char *cache;
eef43b50 622 static unsigned long res;
623 char *end;
624 int i;
625
626 if (cache && strcmp(cache, arg) == 0) {
627 *id = res;
628 return 0;
629 }
630
631 if (!nl_proto_init)
632 nl_proto_initialize();
633
634 for (i = 0; i < 256; i++) {
635 if (nl_proto_tab[i] &&
636 strcmp(nl_proto_tab[i], arg) == 0) {
637 cache = nl_proto_tab[i];
638 res = i;
639 *id = res;
640 return 0;
641 }
642 }
643
644 res = strtoul(arg, &end, 0);
645 if (!end || end == arg || *end || res > 255)
646 return -1;
647 *id = res;
648 return 0;
649}