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