2 * rt_names.c rtnetlink names DB.
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.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
19 #include <sys/socket.h>
23 #include <asm/types.h>
24 #include <linux/rtnetlink.h>
29 #define NAME_MAX_LEN 512
31 struct rtnl_hash_entry
{
32 struct rtnl_hash_entry
*next
;
37 static int fread_id_name(FILE *fp
, int *id
, char *namebuf
)
39 char buf
[NAME_MAX_LEN
];
41 while (fgets(buf
, sizeof(buf
), fp
)) {
44 while (*p
== ' ' || *p
== '\t')
47 if (*p
== '#' || *p
== '\n' || *p
== 0)
50 if (sscanf(p
, "0x%x %s\n", id
, namebuf
) != 2 &&
51 sscanf(p
, "0x%x %s #", id
, namebuf
) != 2 &&
52 sscanf(p
, "%d %s\n", id
, namebuf
) != 2 &&
53 sscanf(p
, "%d %s #", id
, namebuf
) != 2) {
63 rtnl_hash_initialize(const char *file
, struct rtnl_hash_entry
**hash
, int size
)
65 struct rtnl_hash_entry
*entry
;
68 char namebuf
[NAME_MAX_LEN
] = {0};
71 fp
= fopen(file
, "r");
75 while ((ret
= fread_id_name(fp
, &id
, &namebuf
[0]))) {
77 fprintf(stderr
, "Database %s is corrupted at %s\n",
86 entry
= malloc(sizeof(*entry
));
88 entry
->name
= strdup(namebuf
);
89 entry
->next
= hash
[id
& (size
- 1)];
90 hash
[id
& (size
- 1)] = entry
;
95 static void rtnl_tab_initialize(const char *file
, char **tab
, int size
)
99 char namebuf
[NAME_MAX_LEN
] = {0};
102 fp
= fopen(file
, "r");
106 while ((ret
= fread_id_name(fp
, &id
, &namebuf
[0]))) {
108 fprintf(stderr
, "Database %s is corrupted at %s\n",
113 if (id
< 0 || id
> size
)
116 tab
[id
] = strdup(namebuf
);
121 static char *rtnl_rtprot_tab
[256] = {
122 [RTPROT_UNSPEC
] = "none",
123 [RTPROT_REDIRECT
] = "redirect",
124 [RTPROT_KERNEL
] = "kernel",
125 [RTPROT_BOOT
] = "boot",
126 [RTPROT_STATIC
] = "static",
128 [RTPROT_GATED
] = "gated",
130 [RTPROT_MRT
] = "mrt",
131 [RTPROT_ZEBRA
] = "zebra",
132 [RTPROT_BIRD
] = "bird",
133 [RTPROT_BABEL
] = "babel",
134 [RTPROT_DNROUTED
] = "dnrouted",
135 [RTPROT_XORP
] = "xorp",
136 [RTPROT_NTK
] = "ntk",
137 [RTPROT_DHCP
] = "dhcp",
141 static int rtnl_rtprot_init
;
143 static void rtnl_rtprot_initialize(void)
148 rtnl_rtprot_init
= 1;
149 rtnl_tab_initialize(CONFDIR
"/rt_protos",
150 rtnl_rtprot_tab
, 256);
152 d
= opendir(CONFDIR
"/rt_protos.d");
156 while ((de
= readdir(d
)) != NULL
) {
160 if (*de
->d_name
== '.')
163 /* only consider filenames ending in '.conf' */
164 len
= strlen(de
->d_name
);
167 if (strcmp(de
->d_name
+ len
- 5, ".conf"))
170 snprintf(path
, sizeof(path
), CONFDIR
"/rt_protos.d/%s",
172 rtnl_tab_initialize(path
, rtnl_rtprot_tab
, 256);
177 const char *rtnl_rtprot_n2a(int id
, char *buf
, int len
)
179 if (id
< 0 || id
>= 256) {
180 snprintf(buf
, len
, "%u", id
);
183 if (!rtnl_rtprot_tab
[id
]) {
184 if (!rtnl_rtprot_init
)
185 rtnl_rtprot_initialize();
187 if (rtnl_rtprot_tab
[id
])
188 return rtnl_rtprot_tab
[id
];
189 snprintf(buf
, len
, "%u", id
);
193 int rtnl_rtprot_a2n(__u32
*id
, const char *arg
)
196 static unsigned long res
;
200 if (cache
&& strcmp(cache
, arg
) == 0) {
205 if (!rtnl_rtprot_init
)
206 rtnl_rtprot_initialize();
208 for (i
= 0; i
< 256; i
++) {
209 if (rtnl_rtprot_tab
[i
] &&
210 strcmp(rtnl_rtprot_tab
[i
], arg
) == 0) {
211 cache
= rtnl_rtprot_tab
[i
];
218 res
= strtoul(arg
, &end
, 0);
219 if (!end
|| end
== arg
|| *end
|| res
> 255)
226 static char *rtnl_rtscope_tab
[256] = {
227 [RT_SCOPE_UNIVERSE
] = "global",
228 [RT_SCOPE_NOWHERE
] = "nowhere",
229 [RT_SCOPE_HOST
] = "host",
230 [RT_SCOPE_LINK
] = "link",
231 [RT_SCOPE_SITE
] = "site",
234 static int rtnl_rtscope_init
;
236 static void rtnl_rtscope_initialize(void)
238 rtnl_rtscope_init
= 1;
239 rtnl_tab_initialize(CONFDIR
"/rt_scopes",
240 rtnl_rtscope_tab
, 256);
243 const char *rtnl_rtscope_n2a(int id
, char *buf
, int len
)
245 if (id
< 0 || id
>= 256) {
246 snprintf(buf
, len
, "%d", id
);
250 if (!rtnl_rtscope_tab
[id
]) {
251 if (!rtnl_rtscope_init
)
252 rtnl_rtscope_initialize();
255 if (rtnl_rtscope_tab
[id
])
256 return rtnl_rtscope_tab
[id
];
258 snprintf(buf
, len
, "%d", id
);
262 int rtnl_rtscope_a2n(__u32
*id
, const char *arg
)
264 static const char *cache
;
265 static unsigned long res
;
269 if (cache
&& strcmp(cache
, arg
) == 0) {
274 if (!rtnl_rtscope_init
)
275 rtnl_rtscope_initialize();
277 for (i
= 0; i
< 256; i
++) {
278 if (rtnl_rtscope_tab
[i
] &&
279 strcmp(rtnl_rtscope_tab
[i
], arg
) == 0) {
280 cache
= rtnl_rtscope_tab
[i
];
287 res
= strtoul(arg
, &end
, 0);
288 if (!end
|| end
== arg
|| *end
|| res
> 255)
295 static char *rtnl_rtrealm_tab
[256] = {
299 static int rtnl_rtrealm_init
;
301 static void rtnl_rtrealm_initialize(void)
303 rtnl_rtrealm_init
= 1;
304 rtnl_tab_initialize(CONFDIR
"/rt_realms",
305 rtnl_rtrealm_tab
, 256);
308 const char *rtnl_rtrealm_n2a(int id
, char *buf
, int len
)
310 if (id
< 0 || id
>= 256) {
311 snprintf(buf
, len
, "%d", id
);
314 if (!rtnl_rtrealm_tab
[id
]) {
315 if (!rtnl_rtrealm_init
)
316 rtnl_rtrealm_initialize();
318 if (rtnl_rtrealm_tab
[id
])
319 return rtnl_rtrealm_tab
[id
];
320 snprintf(buf
, len
, "%d", id
);
325 int rtnl_rtrealm_a2n(__u32
*id
, const char *arg
)
328 static unsigned long res
;
332 if (cache
&& strcmp(cache
, arg
) == 0) {
337 if (!rtnl_rtrealm_init
)
338 rtnl_rtrealm_initialize();
340 for (i
= 0; i
< 256; i
++) {
341 if (rtnl_rtrealm_tab
[i
] &&
342 strcmp(rtnl_rtrealm_tab
[i
], arg
) == 0) {
343 cache
= rtnl_rtrealm_tab
[i
];
350 res
= strtoul(arg
, &end
, 0);
351 if (!end
|| end
== arg
|| *end
|| res
> 255)
358 static struct rtnl_hash_entry dflt_table_entry
= { .name
= "default" };
359 static struct rtnl_hash_entry main_table_entry
= { .name
= "main" };
360 static struct rtnl_hash_entry local_table_entry
= { .name
= "local" };
362 static struct rtnl_hash_entry
*rtnl_rttable_hash
[256] = {
363 [RT_TABLE_DEFAULT
] = &dflt_table_entry
,
364 [RT_TABLE_MAIN
] = &main_table_entry
,
365 [RT_TABLE_LOCAL
] = &local_table_entry
,
368 static int rtnl_rttable_init
;
370 static void rtnl_rttable_initialize(void)
376 rtnl_rttable_init
= 1;
377 for (i
= 0; i
< 256; i
++) {
378 if (rtnl_rttable_hash
[i
])
379 rtnl_rttable_hash
[i
]->id
= i
;
381 rtnl_hash_initialize(CONFDIR
"/rt_tables",
382 rtnl_rttable_hash
, 256);
384 d
= opendir(CONFDIR
"/rt_tables.d");
388 while ((de
= readdir(d
)) != NULL
) {
392 if (*de
->d_name
== '.')
395 /* only consider filenames ending in '.conf' */
396 len
= strlen(de
->d_name
);
399 if (strcmp(de
->d_name
+ len
- 5, ".conf"))
402 snprintf(path
, sizeof(path
),
403 CONFDIR
"/rt_tables.d/%s", de
->d_name
);
404 rtnl_hash_initialize(path
, rtnl_rttable_hash
, 256);
409 const char *rtnl_rttable_n2a(__u32 id
, char *buf
, int len
)
411 struct rtnl_hash_entry
*entry
;
413 if (id
> RT_TABLE_MAX
) {
414 snprintf(buf
, len
, "%u", id
);
417 if (!rtnl_rttable_init
)
418 rtnl_rttable_initialize();
419 entry
= rtnl_rttable_hash
[id
& 255];
420 while (entry
&& entry
->id
!= id
)
424 snprintf(buf
, len
, "%u", id
);
428 int rtnl_rttable_a2n(__u32
*id
, const char *arg
)
430 static const char *cache
;
431 static unsigned long res
;
432 struct rtnl_hash_entry
*entry
;
436 if (cache
&& strcmp(cache
, arg
) == 0) {
441 if (!rtnl_rttable_init
)
442 rtnl_rttable_initialize();
444 for (i
= 0; i
< 256; i
++) {
445 entry
= rtnl_rttable_hash
[i
];
446 while (entry
&& strcmp(entry
->name
, arg
))
456 i
= strtoul(arg
, &end
, 0);
457 if (!end
|| end
== arg
|| *end
|| i
> RT_TABLE_MAX
)
464 static char *rtnl_rtdsfield_tab
[256] = {
468 static int rtnl_rtdsfield_init
;
470 static void rtnl_rtdsfield_initialize(void)
472 rtnl_rtdsfield_init
= 1;
473 rtnl_tab_initialize(CONFDIR
"/rt_dsfield",
474 rtnl_rtdsfield_tab
, 256);
477 const char *rtnl_dsfield_n2a(int id
, char *buf
, int len
)
479 if (id
< 0 || id
>= 256) {
480 snprintf(buf
, len
, "%d", id
);
483 if (!rtnl_rtdsfield_tab
[id
]) {
484 if (!rtnl_rtdsfield_init
)
485 rtnl_rtdsfield_initialize();
487 if (rtnl_rtdsfield_tab
[id
])
488 return rtnl_rtdsfield_tab
[id
];
489 snprintf(buf
, len
, "0x%02x", id
);
494 int rtnl_dsfield_a2n(__u32
*id
, const char *arg
)
497 static unsigned long res
;
501 if (cache
&& strcmp(cache
, arg
) == 0) {
506 if (!rtnl_rtdsfield_init
)
507 rtnl_rtdsfield_initialize();
509 for (i
= 0; i
< 256; i
++) {
510 if (rtnl_rtdsfield_tab
[i
] &&
511 strcmp(rtnl_rtdsfield_tab
[i
], arg
) == 0) {
512 cache
= rtnl_rtdsfield_tab
[i
];
519 res
= strtoul(arg
, &end
, 16);
520 if (!end
|| end
== arg
|| *end
|| res
> 255)
527 static struct rtnl_hash_entry dflt_group_entry
= {
528 .id
= 0, .name
= "default"
531 static struct rtnl_hash_entry
*rtnl_group_hash
[256] = {
532 [0] = &dflt_group_entry
,
535 static int rtnl_group_init
;
537 static void rtnl_group_initialize(void)
540 rtnl_hash_initialize(CONFDIR
"/group",
541 rtnl_group_hash
, 256);
544 int rtnl_group_a2n(int *id
, const char *arg
)
546 static const char *cache
;
547 static unsigned long res
;
548 struct rtnl_hash_entry
*entry
;
552 if (cache
&& strcmp(cache
, arg
) == 0) {
557 if (!rtnl_group_init
)
558 rtnl_group_initialize();
560 for (i
= 0; i
< 256; i
++) {
561 entry
= rtnl_group_hash
[i
];
562 while (entry
&& strcmp(entry
->name
, arg
))
572 i
= strtol(arg
, &end
, 0);
573 if (!end
|| end
== arg
|| *end
|| i
< 0)
579 const char *rtnl_group_n2a(int id
, char *buf
, int len
)
581 struct rtnl_hash_entry
*entry
;
584 if (!rtnl_group_init
)
585 rtnl_group_initialize();
587 for (i
= 0; i
< 256; i
++) {
588 entry
= rtnl_group_hash
[i
];
597 snprintf(buf
, len
, "%d", id
);
601 static 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",
625 static int nl_proto_init
;
627 static void nl_proto_initialize(void)
630 rtnl_tab_initialize(CONFDIR
"/nl_protos",
634 const char *nl_proto_n2a(int id
, char *buf
, int len
)
636 if (id
< 0 || id
>= 256) {
637 snprintf(buf
, len
, "%u", id
);
642 nl_proto_initialize();
644 if (nl_proto_tab
[id
])
645 return nl_proto_tab
[id
];
647 snprintf(buf
, len
, "%u", id
);
651 int nl_proto_a2n(__u32
*id
, const char *arg
)
654 static unsigned long res
;
658 if (cache
&& strcmp(cache
, arg
) == 0) {
664 nl_proto_initialize();
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
];
676 res
= strtoul(arg
, &end
, 0);
677 if (!end
|| end
== arg
|| *end
|| res
> 255)