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
] = "unspec",
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 (!rtnl_rttable_init
)
414 rtnl_rttable_initialize();
415 entry
= rtnl_rttable_hash
[id
& 255];
416 while (entry
&& entry
->id
!= id
)
420 snprintf(buf
, len
, "%u", id
);
424 int rtnl_rttable_a2n(__u32
*id
, const char *arg
)
426 static const char *cache
;
427 static unsigned long res
;
428 struct rtnl_hash_entry
*entry
;
432 if (cache
&& strcmp(cache
, arg
) == 0) {
437 if (!rtnl_rttable_init
)
438 rtnl_rttable_initialize();
440 for (i
= 0; i
< 256; i
++) {
441 entry
= rtnl_rttable_hash
[i
];
442 while (entry
&& strcmp(entry
->name
, arg
))
452 i
= strtoul(arg
, &end
, 0);
453 if (!end
|| end
== arg
|| *end
|| i
> RT_TABLE_MAX
)
460 static char *rtnl_rtdsfield_tab
[256] = {
464 static int rtnl_rtdsfield_init
;
466 static void rtnl_rtdsfield_initialize(void)
468 rtnl_rtdsfield_init
= 1;
469 rtnl_tab_initialize(CONFDIR
"/rt_dsfield",
470 rtnl_rtdsfield_tab
, 256);
473 const char *rtnl_dsfield_n2a(int id
, char *buf
, int len
)
475 if (id
< 0 || id
>= 256) {
476 snprintf(buf
, len
, "%d", id
);
479 if (!rtnl_rtdsfield_tab
[id
]) {
480 if (!rtnl_rtdsfield_init
)
481 rtnl_rtdsfield_initialize();
483 if (rtnl_rtdsfield_tab
[id
])
484 return rtnl_rtdsfield_tab
[id
];
485 snprintf(buf
, len
, "0x%02x", id
);
490 int rtnl_dsfield_a2n(__u32
*id
, const char *arg
)
493 static unsigned long res
;
497 if (cache
&& strcmp(cache
, arg
) == 0) {
502 if (!rtnl_rtdsfield_init
)
503 rtnl_rtdsfield_initialize();
505 for (i
= 0; i
< 256; i
++) {
506 if (rtnl_rtdsfield_tab
[i
] &&
507 strcmp(rtnl_rtdsfield_tab
[i
], arg
) == 0) {
508 cache
= rtnl_rtdsfield_tab
[i
];
515 res
= strtoul(arg
, &end
, 16);
516 if (!end
|| end
== arg
|| *end
|| res
> 255)
523 static struct rtnl_hash_entry dflt_group_entry
= {
524 .id
= 0, .name
= "default"
527 static struct rtnl_hash_entry
*rtnl_group_hash
[256] = {
528 [0] = &dflt_group_entry
,
531 static int rtnl_group_init
;
533 static void rtnl_group_initialize(void)
536 rtnl_hash_initialize(CONFDIR
"/group",
537 rtnl_group_hash
, 256);
540 int rtnl_group_a2n(int *id
, const char *arg
)
542 static const char *cache
;
543 static unsigned long res
;
544 struct rtnl_hash_entry
*entry
;
548 if (cache
&& strcmp(cache
, arg
) == 0) {
553 if (!rtnl_group_init
)
554 rtnl_group_initialize();
556 for (i
= 0; i
< 256; i
++) {
557 entry
= rtnl_group_hash
[i
];
558 while (entry
&& strcmp(entry
->name
, arg
))
568 i
= strtol(arg
, &end
, 0);
569 if (!end
|| end
== arg
|| *end
|| i
< 0)
575 const char *rtnl_group_n2a(int id
, char *buf
, int len
)
577 struct rtnl_hash_entry
*entry
;
580 if (!rtnl_group_init
)
581 rtnl_group_initialize();
583 for (i
= 0; i
< 256; i
++) {
584 entry
= rtnl_group_hash
[i
];
593 snprintf(buf
, len
, "%d", id
);
597 static char *nl_proto_tab
[256] = {
598 [NETLINK_ROUTE
] = "rtnl",
599 [NETLINK_UNUSED
] = "unused",
600 [NETLINK_USERSOCK
] = "usersock",
601 [NETLINK_FIREWALL
] = "fw",
602 [NETLINK_SOCK_DIAG
] = "tcpdiag",
603 [NETLINK_NFLOG
] = "nflog",
604 [NETLINK_XFRM
] = "xfrm",
605 [NETLINK_SELINUX
] = "selinux",
606 [NETLINK_ISCSI
] = "iscsi",
607 [NETLINK_AUDIT
] = "audit",
608 [NETLINK_FIB_LOOKUP
] = "fiblookup",
609 [NETLINK_CONNECTOR
] = "connector",
610 [NETLINK_NETFILTER
] = "nft",
611 [NETLINK_IP6_FW
] = "ip6fw",
612 [NETLINK_DNRTMSG
] = "dec-rt",
613 [NETLINK_KOBJECT_UEVENT
] = "uevent",
614 [NETLINK_GENERIC
] = "genl",
615 [NETLINK_SCSITRANSPORT
] = "scsi-trans",
616 [NETLINK_ECRYPTFS
] = "ecryptfs",
617 [NETLINK_RDMA
] = "rdma",
618 [NETLINK_CRYPTO
] = "crypto",
621 static int nl_proto_init
;
623 static void nl_proto_initialize(void)
626 rtnl_tab_initialize(CONFDIR
"/nl_protos",
630 const char *nl_proto_n2a(int id
, char *buf
, int len
)
632 if (id
< 0 || id
>= 256) {
633 snprintf(buf
, len
, "%u", id
);
638 nl_proto_initialize();
640 if (nl_proto_tab
[id
])
641 return nl_proto_tab
[id
];
643 snprintf(buf
, len
, "%u", id
);
647 int nl_proto_a2n(__u32
*id
, const char *arg
)
650 static unsigned long res
;
654 if (cache
&& strcmp(cache
, arg
) == 0) {
660 nl_proto_initialize();
662 for (i
= 0; i
< 256; i
++) {
663 if (nl_proto_tab
[i
] &&
664 strcmp(nl_proto_tab
[i
], arg
) == 0) {
665 cache
= nl_proto_tab
[i
];
672 res
= strtoul(arg
, &end
, 0);
673 if (!end
|| end
== arg
|| *end
|| res
> 255)