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>
18 #include <sys/socket.h>
22 #include <asm/types.h>
23 #include <linux/rtnetlink.h>
28 #define NAME_MAX_LEN 512
30 struct rtnl_hash_entry
{
31 struct rtnl_hash_entry
*next
;
36 static int fread_id_name(FILE *fp
, int *id
, char *namebuf
)
38 char buf
[NAME_MAX_LEN
];
40 while (fgets(buf
, sizeof(buf
), fp
)) {
43 while (*p
== ' ' || *p
== '\t')
46 if (*p
== '#' || *p
== '\n' || *p
== 0)
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) {
62 rtnl_hash_initialize(const char *file
, struct rtnl_hash_entry
**hash
, int size
)
64 struct rtnl_hash_entry
*entry
;
67 char namebuf
[NAME_MAX_LEN
] = {0};
70 fp
= fopen(file
, "r");
74 while ((ret
= fread_id_name(fp
, &id
, &namebuf
[0]))) {
76 fprintf(stderr
, "Database %s is corrupted at %s\n",
85 entry
= malloc(sizeof(*entry
));
87 entry
->name
= strdup(namebuf
);
88 entry
->next
= hash
[id
& (size
- 1)];
89 hash
[id
& (size
- 1)] = entry
;
94 static void rtnl_tab_initialize(const char *file
, char **tab
, int size
)
98 char namebuf
[NAME_MAX_LEN
] = {0};
101 fp
= fopen(file
, "r");
105 while ((ret
= fread_id_name(fp
, &id
, &namebuf
[0]))) {
107 fprintf(stderr
, "Database %s is corrupted at %s\n",
112 if (id
< 0 || id
> size
)
115 tab
[id
] = strdup(namebuf
);
120 static char *rtnl_rtprot_tab
[256] = {
121 [RTPROT_UNSPEC
] = "unspec",
122 [RTPROT_REDIRECT
] = "redirect",
123 [RTPROT_KERNEL
] = "kernel",
124 [RTPROT_BOOT
] = "boot",
125 [RTPROT_STATIC
] = "static",
127 [RTPROT_GATED
] = "gated",
129 [RTPROT_MRT
] = "mrt",
130 [RTPROT_ZEBRA
] = "zebra",
131 [RTPROT_BIRD
] = "bird",
132 [RTPROT_BABEL
] = "babel",
133 [RTPROT_DNROUTED
] = "dnrouted",
134 [RTPROT_XORP
] = "xorp",
135 [RTPROT_NTK
] = "ntk",
136 [RTPROT_DHCP
] = "dhcp",
137 [RTPROT_BGP
] = "bgp",
138 [RTPROT_ISIS
] = "isis",
139 [RTPROT_OSPF
] = "ospf",
140 [RTPROT_RIP
] = "rip",
141 [RTPROT_EIGRP
] = "eigrp",
145 static int rtnl_rtprot_init
;
147 static void rtnl_rtprot_initialize(void)
152 rtnl_rtprot_init
= 1;
153 rtnl_tab_initialize(CONFDIR
"/rt_protos",
154 rtnl_rtprot_tab
, 256);
156 d
= opendir(CONFDIR
"/rt_protos.d");
160 while ((de
= readdir(d
)) != NULL
) {
164 if (*de
->d_name
== '.')
167 /* only consider filenames ending in '.conf' */
168 len
= strlen(de
->d_name
);
171 if (strcmp(de
->d_name
+ len
- 5, ".conf"))
174 snprintf(path
, sizeof(path
), CONFDIR
"/rt_protos.d/%s",
176 rtnl_tab_initialize(path
, rtnl_rtprot_tab
, 256);
181 const char *rtnl_rtprot_n2a(int id
, char *buf
, int len
)
183 if (id
< 0 || id
>= 256) {
184 snprintf(buf
, len
, "%u", id
);
187 if (!rtnl_rtprot_tab
[id
]) {
188 if (!rtnl_rtprot_init
)
189 rtnl_rtprot_initialize();
191 if (rtnl_rtprot_tab
[id
])
192 return rtnl_rtprot_tab
[id
];
193 snprintf(buf
, len
, "%u", id
);
197 int rtnl_rtprot_a2n(__u32
*id
, const char *arg
)
200 static unsigned long res
;
204 if (cache
&& strcmp(cache
, arg
) == 0) {
209 if (!rtnl_rtprot_init
)
210 rtnl_rtprot_initialize();
212 for (i
= 0; i
< 256; i
++) {
213 if (rtnl_rtprot_tab
[i
] &&
214 strcmp(rtnl_rtprot_tab
[i
], arg
) == 0) {
215 cache
= rtnl_rtprot_tab
[i
];
222 res
= strtoul(arg
, &end
, 0);
223 if (!end
|| end
== arg
|| *end
|| res
> 255)
230 static char *rtnl_rtscope_tab
[256] = {
231 [RT_SCOPE_UNIVERSE
] = "global",
232 [RT_SCOPE_NOWHERE
] = "nowhere",
233 [RT_SCOPE_HOST
] = "host",
234 [RT_SCOPE_LINK
] = "link",
235 [RT_SCOPE_SITE
] = "site",
238 static int rtnl_rtscope_init
;
240 static void rtnl_rtscope_initialize(void)
242 rtnl_rtscope_init
= 1;
243 rtnl_tab_initialize(CONFDIR
"/rt_scopes",
244 rtnl_rtscope_tab
, 256);
247 const char *rtnl_rtscope_n2a(int id
, char *buf
, int len
)
249 if (id
< 0 || id
>= 256) {
250 snprintf(buf
, len
, "%d", id
);
254 if (!rtnl_rtscope_tab
[id
]) {
255 if (!rtnl_rtscope_init
)
256 rtnl_rtscope_initialize();
259 if (rtnl_rtscope_tab
[id
])
260 return rtnl_rtscope_tab
[id
];
262 snprintf(buf
, len
, "%d", id
);
266 int rtnl_rtscope_a2n(__u32
*id
, const char *arg
)
268 static const char *cache
;
269 static unsigned long res
;
273 if (cache
&& strcmp(cache
, arg
) == 0) {
278 if (!rtnl_rtscope_init
)
279 rtnl_rtscope_initialize();
281 for (i
= 0; i
< 256; i
++) {
282 if (rtnl_rtscope_tab
[i
] &&
283 strcmp(rtnl_rtscope_tab
[i
], arg
) == 0) {
284 cache
= rtnl_rtscope_tab
[i
];
291 res
= strtoul(arg
, &end
, 0);
292 if (!end
|| end
== arg
|| *end
|| res
> 255)
299 static char *rtnl_rtrealm_tab
[256] = {
303 static int rtnl_rtrealm_init
;
305 static void rtnl_rtrealm_initialize(void)
307 rtnl_rtrealm_init
= 1;
308 rtnl_tab_initialize(CONFDIR
"/rt_realms",
309 rtnl_rtrealm_tab
, 256);
312 const char *rtnl_rtrealm_n2a(int id
, char *buf
, int len
)
314 if (id
< 0 || id
>= 256) {
315 snprintf(buf
, len
, "%d", id
);
318 if (!rtnl_rtrealm_tab
[id
]) {
319 if (!rtnl_rtrealm_init
)
320 rtnl_rtrealm_initialize();
322 if (rtnl_rtrealm_tab
[id
])
323 return rtnl_rtrealm_tab
[id
];
324 snprintf(buf
, len
, "%d", id
);
329 int rtnl_rtrealm_a2n(__u32
*id
, const char *arg
)
332 static unsigned long res
;
336 if (cache
&& strcmp(cache
, arg
) == 0) {
341 if (!rtnl_rtrealm_init
)
342 rtnl_rtrealm_initialize();
344 for (i
= 0; i
< 256; i
++) {
345 if (rtnl_rtrealm_tab
[i
] &&
346 strcmp(rtnl_rtrealm_tab
[i
], arg
) == 0) {
347 cache
= rtnl_rtrealm_tab
[i
];
354 res
= strtoul(arg
, &end
, 0);
355 if (!end
|| end
== arg
|| *end
|| res
> 255)
362 static struct rtnl_hash_entry dflt_table_entry
= { .name
= "default" };
363 static struct rtnl_hash_entry main_table_entry
= { .name
= "main" };
364 static struct rtnl_hash_entry local_table_entry
= { .name
= "local" };
366 static struct rtnl_hash_entry
*rtnl_rttable_hash
[256] = {
367 [RT_TABLE_DEFAULT
] = &dflt_table_entry
,
368 [RT_TABLE_MAIN
] = &main_table_entry
,
369 [RT_TABLE_LOCAL
] = &local_table_entry
,
372 static int rtnl_rttable_init
;
374 static void rtnl_rttable_initialize(void)
380 rtnl_rttable_init
= 1;
381 for (i
= 0; i
< 256; i
++) {
382 if (rtnl_rttable_hash
[i
])
383 rtnl_rttable_hash
[i
]->id
= i
;
385 rtnl_hash_initialize(CONFDIR
"/rt_tables",
386 rtnl_rttable_hash
, 256);
388 d
= opendir(CONFDIR
"/rt_tables.d");
392 while ((de
= readdir(d
)) != NULL
) {
396 if (*de
->d_name
== '.')
399 /* only consider filenames ending in '.conf' */
400 len
= strlen(de
->d_name
);
403 if (strcmp(de
->d_name
+ len
- 5, ".conf"))
406 snprintf(path
, sizeof(path
),
407 CONFDIR
"/rt_tables.d/%s", de
->d_name
);
408 rtnl_hash_initialize(path
, rtnl_rttable_hash
, 256);
413 const char *rtnl_rttable_n2a(__u32 id
, char *buf
, int len
)
415 struct rtnl_hash_entry
*entry
;
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)