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