]>
Commit | Line | Data |
---|---|---|
aba5acdf SH |
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> | |
aba5acdf SH |
15 | #include <fcntl.h> |
16 | #include <string.h> | |
17 | #include <sys/time.h> | |
b88fd9f4 | 18 | #include <sys/socket.h> |
13ada95d | 19 | #include <dirent.h> |
4a36b4c2 | 20 | #include <limits.h> |
b88fd9f4 SH |
21 | |
22 | #include <asm/types.h> | |
23 | #include <linux/rtnetlink.h> | |
24 | ||
25 | #include "rt_names.h" | |
f6793eec | 26 | #include "utils.h" |
fb72129b | 27 | |
f00073e8 | 28 | #define NAME_MAX_LEN 512 |
29 | ||
ca697cee HL |
30 | int numeric; |
31 | ||
9c47d877 | 32 | struct rtnl_hash_entry { |
68ef5072 SH |
33 | struct rtnl_hash_entry *next; |
34 | const char *name; | |
9c47d877 PM |
35 | unsigned int id; |
36 | }; | |
37 | ||
f00073e8 | 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 | ||
9c47d877 | 63 | static void |
46ac8a55 | 64 | rtnl_hash_initialize(const char *file, struct rtnl_hash_entry **hash, int size) |
9c47d877 PM |
65 | { |
66 | struct rtnl_hash_entry *entry; | |
9c47d877 | 67 | FILE *fp; |
f00073e8 | 68 | int id; |
69 | char namebuf[NAME_MAX_LEN] = {0}; | |
70 | int ret; | |
9c47d877 PM |
71 | |
72 | fp = fopen(file, "r"); | |
73 | if (!fp) | |
74 | return; | |
9c47d877 | 75 | |
f00073e8 | 76 | while ((ret = fread_id_name(fp, &id, &namebuf[0]))) { |
77 | if (ret == -1) { | |
9c47d877 | 78 | fprintf(stderr, "Database %s is corrupted at %s\n", |
f00073e8 | 79 | file, namebuf); |
97c13582 | 80 | fclose(fp); |
9c47d877 PM |
81 | return; |
82 | } | |
83 | ||
68ef5072 | 84 | if (id < 0) |
9c47d877 | 85 | continue; |
f00073e8 | 86 | |
9c47d877 PM |
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 | ||
46ac8a55 | 96 | static void rtnl_tab_initialize(const char *file, char **tab, int size) |
aba5acdf | 97 | { |
aba5acdf | 98 | FILE *fp; |
f00073e8 | 99 | int id; |
100 | char namebuf[NAME_MAX_LEN] = {0}; | |
101 | int ret; | |
aba5acdf SH |
102 | |
103 | fp = fopen(file, "r"); | |
104 | if (!fp) | |
105 | return; | |
aba5acdf | 106 | |
f00073e8 | 107 | while ((ret = fread_id_name(fp, &id, &namebuf[0]))) { |
108 | if (ret == -1) { | |
aba5acdf | 109 | fprintf(stderr, "Database %s is corrupted at %s\n", |
f00073e8 | 110 | file, namebuf); |
97c13582 | 111 | fclose(fp); |
aba5acdf SH |
112 | return; |
113 | } | |
68ef5072 | 114 | if (id < 0 || id > size) |
aba5acdf SH |
115 | continue; |
116 | ||
117 | tab[id] = strdup(namebuf); | |
118 | } | |
119 | fclose(fp); | |
120 | } | |
121 | ||
68ef5072 | 122 | static char *rtnl_rtprot_tab[256] = { |
30f3beea AC |
123 | [RTPROT_UNSPEC] = "unspec", |
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 | [RTPROT_KEEPALIVED] = "keepalived", | |
140 | [RTPROT_BGP] = "bgp", | |
141 | [RTPROT_ISIS] = "isis", | |
142 | [RTPROT_OSPF] = "ospf", | |
143 | [RTPROT_RIP] = "rip", | |
144 | [RTPROT_EIGRP] = "eigrp", | |
aba5acdf SH |
145 | }; |
146 | ||
147 | ||
aba5acdf SH |
148 | static int rtnl_rtprot_init; |
149 | ||
150 | static void rtnl_rtprot_initialize(void) | |
151 | { | |
719e331f DA |
152 | struct dirent *de; |
153 | DIR *d; | |
154 | ||
aba5acdf | 155 | rtnl_rtprot_init = 1; |
fb72129b | 156 | rtnl_tab_initialize(CONFDIR "/rt_protos", |
aba5acdf | 157 | rtnl_rtprot_tab, 256); |
719e331f DA |
158 | |
159 | d = opendir(CONFDIR "/rt_protos.d"); | |
160 | if (!d) | |
161 | return; | |
162 | ||
163 | while ((de = readdir(d)) != NULL) { | |
164 | char path[PATH_MAX]; | |
165 | size_t len; | |
166 | ||
167 | if (*de->d_name == '.') | |
168 | continue; | |
169 | ||
170 | /* only consider filenames ending in '.conf' */ | |
171 | len = strlen(de->d_name); | |
172 | if (len <= 5) | |
173 | continue; | |
174 | if (strcmp(de->d_name + len - 5, ".conf")) | |
175 | continue; | |
176 | ||
177 | snprintf(path, sizeof(path), CONFDIR "/rt_protos.d/%s", | |
178 | de->d_name); | |
179 | rtnl_tab_initialize(path, rtnl_rtprot_tab, 256); | |
180 | } | |
181 | closedir(d); | |
aba5acdf SH |
182 | } |
183 | ||
68ef5072 | 184 | const char *rtnl_rtprot_n2a(int id, char *buf, int len) |
aba5acdf | 185 | { |
ca697cee | 186 | if (id < 0 || id >= 256 || numeric) { |
46ac8a55 | 187 | snprintf(buf, len, "%u", id); |
aba5acdf SH |
188 | return buf; |
189 | } | |
190 | if (!rtnl_rtprot_tab[id]) { | |
191 | if (!rtnl_rtprot_init) | |
192 | rtnl_rtprot_initialize(); | |
193 | } | |
194 | if (rtnl_rtprot_tab[id]) | |
195 | return rtnl_rtprot_tab[id]; | |
46ac8a55 | 196 | snprintf(buf, len, "%u", id); |
aba5acdf SH |
197 | return buf; |
198 | } | |
199 | ||
46ac8a55 | 200 | int rtnl_rtprot_a2n(__u32 *id, const char *arg) |
aba5acdf | 201 | { |
68ef5072 | 202 | static char *cache; |
aba5acdf SH |
203 | static unsigned long res; |
204 | char *end; | |
205 | int i; | |
206 | ||
207 | if (cache && strcmp(cache, arg) == 0) { | |
208 | *id = res; | |
209 | return 0; | |
210 | } | |
211 | ||
212 | if (!rtnl_rtprot_init) | |
213 | rtnl_rtprot_initialize(); | |
214 | ||
68ef5072 | 215 | for (i = 0; i < 256; i++) { |
aba5acdf SH |
216 | if (rtnl_rtprot_tab[i] && |
217 | strcmp(rtnl_rtprot_tab[i], arg) == 0) { | |
218 | cache = rtnl_rtprot_tab[i]; | |
219 | res = i; | |
220 | *id = res; | |
221 | return 0; | |
222 | } | |
223 | } | |
224 | ||
225 | res = strtoul(arg, &end, 0); | |
226 | if (!end || end == arg || *end || res > 255) | |
227 | return -1; | |
228 | *id = res; | |
229 | return 0; | |
230 | } | |
231 | ||
68ef5072 SH |
232 | |
233 | static char *rtnl_rtscope_tab[256] = { | |
234 | [RT_SCOPE_UNIVERSE] = "global", | |
235 | [RT_SCOPE_NOWHERE] = "nowhere", | |
236 | [RT_SCOPE_HOST] = "host", | |
237 | [RT_SCOPE_LINK] = "link", | |
238 | [RT_SCOPE_SITE] = "site", | |
aba5acdf SH |
239 | }; |
240 | ||
241 | static int rtnl_rtscope_init; | |
242 | ||
243 | static void rtnl_rtscope_initialize(void) | |
244 | { | |
245 | rtnl_rtscope_init = 1; | |
fb72129b | 246 | rtnl_tab_initialize(CONFDIR "/rt_scopes", |
aba5acdf SH |
247 | rtnl_rtscope_tab, 256); |
248 | } | |
249 | ||
46ac8a55 | 250 | const char *rtnl_rtscope_n2a(int id, char *buf, int len) |
aba5acdf | 251 | { |
ca697cee | 252 | if (id < 0 || id >= 256 || numeric) { |
aba5acdf SH |
253 | snprintf(buf, len, "%d", id); |
254 | return buf; | |
255 | } | |
68ef5072 | 256 | |
aba5acdf SH |
257 | if (!rtnl_rtscope_tab[id]) { |
258 | if (!rtnl_rtscope_init) | |
259 | rtnl_rtscope_initialize(); | |
260 | } | |
68ef5072 | 261 | |
aba5acdf SH |
262 | if (rtnl_rtscope_tab[id]) |
263 | return rtnl_rtscope_tab[id]; | |
68ef5072 | 264 | |
aba5acdf SH |
265 | snprintf(buf, len, "%d", id); |
266 | return buf; | |
267 | } | |
268 | ||
46ac8a55 | 269 | int rtnl_rtscope_a2n(__u32 *id, const char *arg) |
aba5acdf | 270 | { |
68ef5072 | 271 | static const char *cache; |
aba5acdf SH |
272 | static unsigned long res; |
273 | char *end; | |
274 | int i; | |
275 | ||
276 | if (cache && strcmp(cache, arg) == 0) { | |
277 | *id = res; | |
278 | return 0; | |
279 | } | |
280 | ||
281 | if (!rtnl_rtscope_init) | |
282 | rtnl_rtscope_initialize(); | |
283 | ||
68ef5072 | 284 | for (i = 0; i < 256; i++) { |
aba5acdf SH |
285 | if (rtnl_rtscope_tab[i] && |
286 | strcmp(rtnl_rtscope_tab[i], arg) == 0) { | |
287 | cache = rtnl_rtscope_tab[i]; | |
288 | res = i; | |
289 | *id = res; | |
290 | return 0; | |
291 | } | |
292 | } | |
293 | ||
294 | res = strtoul(arg, &end, 0); | |
295 | if (!end || end == arg || *end || res > 255) | |
296 | return -1; | |
297 | *id = res; | |
298 | return 0; | |
299 | } | |
300 | ||
301 | ||
68ef5072 | 302 | static char *rtnl_rtrealm_tab[256] = { |
aba5acdf SH |
303 | "unknown", |
304 | }; | |
305 | ||
306 | static int rtnl_rtrealm_init; | |
307 | ||
308 | static void rtnl_rtrealm_initialize(void) | |
309 | { | |
310 | rtnl_rtrealm_init = 1; | |
fb72129b | 311 | rtnl_tab_initialize(CONFDIR "/rt_realms", |
aba5acdf SH |
312 | rtnl_rtrealm_tab, 256); |
313 | } | |
314 | ||
46ac8a55 | 315 | const char *rtnl_rtrealm_n2a(int id, char *buf, int len) |
aba5acdf | 316 | { |
ca697cee | 317 | if (id < 0 || id >= 256 || numeric) { |
aba5acdf SH |
318 | snprintf(buf, len, "%d", id); |
319 | return buf; | |
320 | } | |
321 | if (!rtnl_rtrealm_tab[id]) { | |
322 | if (!rtnl_rtrealm_init) | |
323 | rtnl_rtrealm_initialize(); | |
324 | } | |
325 | if (rtnl_rtrealm_tab[id]) | |
326 | return rtnl_rtrealm_tab[id]; | |
327 | snprintf(buf, len, "%d", id); | |
328 | return buf; | |
329 | } | |
330 | ||
331 | ||
46ac8a55 | 332 | int rtnl_rtrealm_a2n(__u32 *id, const char *arg) |
aba5acdf | 333 | { |
68ef5072 | 334 | static char *cache; |
aba5acdf SH |
335 | static unsigned long res; |
336 | char *end; | |
337 | int i; | |
338 | ||
339 | if (cache && strcmp(cache, arg) == 0) { | |
340 | *id = res; | |
341 | return 0; | |
342 | } | |
343 | ||
344 | if (!rtnl_rtrealm_init) | |
345 | rtnl_rtrealm_initialize(); | |
346 | ||
68ef5072 | 347 | for (i = 0; i < 256; i++) { |
aba5acdf SH |
348 | if (rtnl_rtrealm_tab[i] && |
349 | strcmp(rtnl_rtrealm_tab[i], arg) == 0) { | |
350 | cache = rtnl_rtrealm_tab[i]; | |
351 | res = i; | |
352 | *id = res; | |
353 | return 0; | |
354 | } | |
355 | } | |
356 | ||
357 | res = strtoul(arg, &end, 0); | |
358 | if (!end || end == arg || *end || res > 255) | |
359 | return -1; | |
360 | *id = res; | |
361 | return 0; | |
362 | } | |
363 | ||
364 | ||
81ebcb2a MY |
365 | static struct rtnl_hash_entry dflt_table_entry = { .name = "default" }; |
366 | static struct rtnl_hash_entry main_table_entry = { .name = "main" }; | |
367 | static struct rtnl_hash_entry local_table_entry = { .name = "local" }; | |
aba5acdf | 368 | |
68ef5072 | 369 | static struct rtnl_hash_entry *rtnl_rttable_hash[256] = { |
81ebcb2a MY |
370 | [RT_TABLE_DEFAULT] = &dflt_table_entry, |
371 | [RT_TABLE_MAIN] = &main_table_entry, | |
372 | [RT_TABLE_LOCAL] = &local_table_entry, | |
aba5acdf SH |
373 | }; |
374 | ||
375 | static int rtnl_rttable_init; | |
376 | ||
377 | static void rtnl_rttable_initialize(void) | |
378 | { | |
13ada95d DA |
379 | struct dirent *de; |
380 | DIR *d; | |
81ebcb2a MY |
381 | int i; |
382 | ||
aba5acdf | 383 | rtnl_rttable_init = 1; |
81ebcb2a MY |
384 | for (i = 0; i < 256; i++) { |
385 | if (rtnl_rttable_hash[i]) | |
386 | rtnl_rttable_hash[i]->id = i; | |
387 | } | |
fb72129b | 388 | rtnl_hash_initialize(CONFDIR "/rt_tables", |
9c47d877 | 389 | rtnl_rttable_hash, 256); |
13ada95d DA |
390 | |
391 | d = opendir(CONFDIR "/rt_tables.d"); | |
392 | if (!d) | |
393 | return; | |
394 | ||
395 | while ((de = readdir(d)) != NULL) { | |
396 | char path[PATH_MAX]; | |
397 | size_t len; | |
398 | ||
399 | if (*de->d_name == '.') | |
400 | continue; | |
401 | ||
402 | /* only consider filenames ending in '.conf' */ | |
403 | len = strlen(de->d_name); | |
404 | if (len <= 5) | |
405 | continue; | |
406 | if (strcmp(de->d_name + len - 5, ".conf")) | |
407 | continue; | |
408 | ||
68ef5072 SH |
409 | snprintf(path, sizeof(path), |
410 | CONFDIR "/rt_tables.d/%s", de->d_name); | |
13ada95d DA |
411 | rtnl_hash_initialize(path, rtnl_rttable_hash, 256); |
412 | } | |
413 | closedir(d); | |
aba5acdf SH |
414 | } |
415 | ||
68ef5072 | 416 | const char *rtnl_rttable_n2a(__u32 id, char *buf, int len) |
aba5acdf | 417 | { |
9c47d877 PM |
418 | struct rtnl_hash_entry *entry; |
419 | ||
9c47d877 PM |
420 | if (!rtnl_rttable_init) |
421 | rtnl_rttable_initialize(); | |
422 | entry = rtnl_rttable_hash[id & 255]; | |
423 | while (entry && entry->id != id) | |
424 | entry = entry->next; | |
ca697cee | 425 | if (!numeric && entry) |
9c47d877 PM |
426 | return entry->name; |
427 | snprintf(buf, len, "%u", id); | |
aba5acdf SH |
428 | return buf; |
429 | } | |
430 | ||
46ac8a55 | 431 | int rtnl_rttable_a2n(__u32 *id, const char *arg) |
aba5acdf | 432 | { |
68ef5072 | 433 | static const char *cache; |
aba5acdf | 434 | static unsigned long res; |
9c47d877 | 435 | struct rtnl_hash_entry *entry; |
aba5acdf | 436 | char *end; |
5ffbf450 | 437 | unsigned long i; |
aba5acdf SH |
438 | |
439 | if (cache && strcmp(cache, arg) == 0) { | |
440 | *id = res; | |
441 | return 0; | |
442 | } | |
443 | ||
444 | if (!rtnl_rttable_init) | |
445 | rtnl_rttable_initialize(); | |
446 | ||
68ef5072 | 447 | for (i = 0; i < 256; i++) { |
9c47d877 PM |
448 | entry = rtnl_rttable_hash[i]; |
449 | while (entry && strcmp(entry->name, arg)) | |
450 | entry = entry->next; | |
451 | if (entry) { | |
452 | cache = entry->name; | |
453 | res = entry->id; | |
aba5acdf SH |
454 | *id = res; |
455 | return 0; | |
456 | } | |
457 | } | |
458 | ||
459 | i = strtoul(arg, &end, 0); | |
9c47d877 | 460 | if (!end || end == arg || *end || i > RT_TABLE_MAX) |
aba5acdf SH |
461 | return -1; |
462 | *id = i; | |
463 | return 0; | |
464 | } | |
465 | ||
466 | ||
68ef5072 | 467 | static char *rtnl_rtdsfield_tab[256] = { |
aba5acdf SH |
468 | "0", |
469 | }; | |
470 | ||
471 | static int rtnl_rtdsfield_init; | |
472 | ||
473 | static void rtnl_rtdsfield_initialize(void) | |
474 | { | |
475 | rtnl_rtdsfield_init = 1; | |
fb72129b | 476 | rtnl_tab_initialize(CONFDIR "/rt_dsfield", |
aba5acdf SH |
477 | rtnl_rtdsfield_tab, 256); |
478 | } | |
479 | ||
46ac8a55 | 480 | const char *rtnl_dsfield_n2a(int id, char *buf, int len) |
aba5acdf | 481 | { |
bf244ee6 PM |
482 | const char *name; |
483 | ||
68ef5072 | 484 | if (id < 0 || id >= 256) { |
aba5acdf SH |
485 | snprintf(buf, len, "%d", id); |
486 | return buf; | |
487 | } | |
bf244ee6 PM |
488 | if (!numeric) { |
489 | name = rtnl_dsfield_get_name(id); | |
490 | if (name != NULL) | |
491 | return name; | |
492 | } | |
493 | snprintf(buf, len, "0x%02x", id); | |
494 | return buf; | |
495 | } | |
496 | ||
497 | const char *rtnl_dsfield_get_name(int id) | |
498 | { | |
499 | if (id < 0 || id >= 256) | |
500 | return NULL; | |
aba5acdf SH |
501 | if (!rtnl_rtdsfield_tab[id]) { |
502 | if (!rtnl_rtdsfield_init) | |
503 | rtnl_rtdsfield_initialize(); | |
504 | } | |
bf244ee6 | 505 | return rtnl_rtdsfield_tab[id]; |
aba5acdf SH |
506 | } |
507 | ||
508 | ||
46ac8a55 | 509 | int rtnl_dsfield_a2n(__u32 *id, const char *arg) |
aba5acdf | 510 | { |
68ef5072 | 511 | static char *cache; |
aba5acdf SH |
512 | static unsigned long res; |
513 | char *end; | |
514 | int i; | |
515 | ||
516 | if (cache && strcmp(cache, arg) == 0) { | |
517 | *id = res; | |
518 | return 0; | |
519 | } | |
520 | ||
521 | if (!rtnl_rtdsfield_init) | |
522 | rtnl_rtdsfield_initialize(); | |
523 | ||
68ef5072 | 524 | for (i = 0; i < 256; i++) { |
aba5acdf SH |
525 | if (rtnl_rtdsfield_tab[i] && |
526 | strcmp(rtnl_rtdsfield_tab[i], arg) == 0) { | |
527 | cache = rtnl_rtdsfield_tab[i]; | |
528 | res = i; | |
529 | *id = res; | |
530 | return 0; | |
531 | } | |
532 | } | |
533 | ||
534 | res = strtoul(arg, &end, 16); | |
535 | if (!end || end == arg || *end || res > 255) | |
536 | return -1; | |
537 | *id = res; | |
538 | return 0; | |
539 | } | |
540 | ||
ac694c33 | 541 | |
68ef5072 SH |
542 | static struct rtnl_hash_entry dflt_group_entry = { |
543 | .id = 0, .name = "default" | |
544 | }; | |
ac694c33 | 545 | |
68ef5072 | 546 | static struct rtnl_hash_entry *rtnl_group_hash[256] = { |
ac694c33 VD |
547 | [0] = &dflt_group_entry, |
548 | }; | |
549 | ||
550 | static int rtnl_group_init; | |
551 | ||
552 | static void rtnl_group_initialize(void) | |
553 | { | |
554 | rtnl_group_init = 1; | |
4e5615b3 | 555 | rtnl_hash_initialize(CONFDIR "/group", |
ac694c33 VD |
556 | rtnl_group_hash, 256); |
557 | } | |
558 | ||
46ac8a55 | 559 | int rtnl_group_a2n(int *id, const char *arg) |
ac694c33 | 560 | { |
68ef5072 | 561 | static const char *cache; |
ac694c33 VD |
562 | static unsigned long res; |
563 | struct rtnl_hash_entry *entry; | |
564 | char *end; | |
565 | int i; | |
566 | ||
567 | if (cache && strcmp(cache, arg) == 0) { | |
568 | *id = res; | |
569 | return 0; | |
570 | } | |
571 | ||
572 | if (!rtnl_group_init) | |
573 | rtnl_group_initialize(); | |
574 | ||
68ef5072 | 575 | for (i = 0; i < 256; i++) { |
ac694c33 VD |
576 | entry = rtnl_group_hash[i]; |
577 | while (entry && strcmp(entry->name, arg)) | |
578 | entry = entry->next; | |
579 | if (entry) { | |
580 | cache = entry->name; | |
581 | res = entry->id; | |
582 | *id = res; | |
583 | return 0; | |
584 | } | |
585 | } | |
586 | ||
587 | i = strtol(arg, &end, 0); | |
588 | if (!end || end == arg || *end || i < 0) | |
589 | return -1; | |
590 | *id = i; | |
591 | return 0; | |
592 | } | |
c4fdf75d ST |
593 | |
594 | const char *rtnl_group_n2a(int id, char *buf, int len) | |
595 | { | |
596 | struct rtnl_hash_entry *entry; | |
597 | int i; | |
598 | ||
599 | if (!rtnl_group_init) | |
600 | rtnl_group_initialize(); | |
601 | ||
ca697cee | 602 | for (i = 0; !numeric && i < 256; i++) { |
c4fdf75d | 603 | entry = rtnl_group_hash[i]; |
2d98dd48 ZS |
604 | |
605 | while (entry) { | |
606 | if (entry->id == id) | |
607 | return entry->name; | |
608 | entry = entry->next; | |
609 | } | |
c4fdf75d ST |
610 | } |
611 | ||
612 | snprintf(buf, len, "%d", id); | |
613 | return buf; | |
614 | } | |
eef43b50 | 615 | |
616 | static char *nl_proto_tab[256] = { | |
617 | [NETLINK_ROUTE] = "rtnl", | |
618 | [NETLINK_UNUSED] = "unused", | |
619 | [NETLINK_USERSOCK] = "usersock", | |
620 | [NETLINK_FIREWALL] = "fw", | |
621 | [NETLINK_SOCK_DIAG] = "tcpdiag", | |
622 | [NETLINK_NFLOG] = "nflog", | |
623 | [NETLINK_XFRM] = "xfrm", | |
624 | [NETLINK_SELINUX] = "selinux", | |
625 | [NETLINK_ISCSI] = "iscsi", | |
626 | [NETLINK_AUDIT] = "audit", | |
627 | [NETLINK_FIB_LOOKUP] = "fiblookup", | |
628 | [NETLINK_CONNECTOR] = "connector", | |
629 | [NETLINK_NETFILTER] = "nft", | |
630 | [NETLINK_IP6_FW] = "ip6fw", | |
631 | [NETLINK_DNRTMSG] = "dec-rt", | |
632 | [NETLINK_KOBJECT_UEVENT] = "uevent", | |
633 | [NETLINK_GENERIC] = "genl", | |
634 | [NETLINK_SCSITRANSPORT] = "scsi-trans", | |
635 | [NETLINK_ECRYPTFS] = "ecryptfs", | |
636 | [NETLINK_RDMA] = "rdma", | |
637 | [NETLINK_CRYPTO] = "crypto", | |
638 | }; | |
639 | ||
640 | static int nl_proto_init; | |
641 | ||
642 | static void nl_proto_initialize(void) | |
643 | { | |
644 | nl_proto_init = 1; | |
645 | rtnl_tab_initialize(CONFDIR "/nl_protos", | |
646 | nl_proto_tab, 256); | |
647 | } | |
648 | ||
649 | const char *nl_proto_n2a(int id, char *buf, int len) | |
650 | { | |
ca697cee HL |
651 | if (id < 0 || id >= 256 || numeric) { |
652 | snprintf(buf, len, "%d", id); | |
eef43b50 | 653 | return buf; |
654 | } | |
655 | ||
656 | if (!nl_proto_init) | |
657 | nl_proto_initialize(); | |
658 | ||
659 | if (nl_proto_tab[id]) | |
660 | return nl_proto_tab[id]; | |
661 | ||
662 | snprintf(buf, len, "%u", id); | |
663 | return buf; | |
664 | } | |
665 | ||
666 | int nl_proto_a2n(__u32 *id, const char *arg) | |
667 | { | |
68ef5072 | 668 | static char *cache; |
eef43b50 | 669 | static unsigned long res; |
670 | char *end; | |
671 | int i; | |
672 | ||
673 | if (cache && strcmp(cache, arg) == 0) { | |
674 | *id = res; | |
675 | return 0; | |
676 | } | |
677 | ||
678 | if (!nl_proto_init) | |
679 | nl_proto_initialize(); | |
680 | ||
681 | for (i = 0; i < 256; i++) { | |
682 | if (nl_proto_tab[i] && | |
683 | strcmp(nl_proto_tab[i], arg) == 0) { | |
684 | cache = nl_proto_tab[i]; | |
685 | res = i; | |
686 | *id = res; | |
687 | return 0; | |
688 | } | |
689 | } | |
690 | ||
691 | res = strtoul(arg, &end, 0); | |
692 | if (!end || end == arg || *end || res > 255) | |
693 | return -1; | |
694 | *id = res; | |
695 | return 0; | |
696 | } | |
6fd53b2a RP |
697 | |
698 | #define PROTODOWN_REASON_NUM_BITS 32 | |
699 | static char *protodown_reason_tab[PROTODOWN_REASON_NUM_BITS] = { | |
700 | }; | |
701 | ||
702 | static int protodown_reason_init; | |
703 | ||
704 | static void protodown_reason_initialize(void) | |
705 | { | |
706 | struct dirent *de; | |
707 | DIR *d; | |
708 | ||
709 | protodown_reason_init = 1; | |
710 | ||
711 | d = opendir(CONFDIR "/protodown_reasons.d"); | |
712 | if (!d) | |
713 | return; | |
714 | ||
715 | while ((de = readdir(d)) != NULL) { | |
716 | char path[PATH_MAX]; | |
717 | size_t len; | |
718 | ||
719 | if (*de->d_name == '.') | |
720 | continue; | |
721 | ||
722 | /* only consider filenames ending in '.conf' */ | |
723 | len = strlen(de->d_name); | |
724 | if (len <= 5) | |
725 | continue; | |
726 | if (strcmp(de->d_name + len - 5, ".conf")) | |
727 | continue; | |
728 | ||
729 | snprintf(path, sizeof(path), CONFDIR "/protodown_reasons.d/%s", | |
730 | de->d_name); | |
731 | rtnl_tab_initialize(path, protodown_reason_tab, | |
732 | PROTODOWN_REASON_NUM_BITS); | |
733 | } | |
734 | closedir(d); | |
735 | } | |
736 | ||
737 | int protodown_reason_n2a(int id, char *buf, int len) | |
738 | { | |
739 | if (id < 0 || id >= PROTODOWN_REASON_NUM_BITS) | |
740 | return -1; | |
741 | ||
742 | if (numeric) { | |
743 | snprintf(buf, len, "%d", id); | |
744 | return 0; | |
745 | } | |
746 | ||
747 | if (!protodown_reason_init) | |
748 | protodown_reason_initialize(); | |
749 | ||
750 | if (protodown_reason_tab[id]) | |
751 | snprintf(buf, len, "%s", protodown_reason_tab[id]); | |
752 | else | |
753 | snprintf(buf, len, "%d", id); | |
754 | ||
755 | return 0; | |
756 | } | |
757 | ||
758 | int protodown_reason_a2n(__u32 *id, const char *arg) | |
759 | { | |
760 | static char *cache; | |
761 | static unsigned long res; | |
762 | char *end; | |
763 | int i; | |
764 | ||
765 | if (cache && strcmp(cache, arg) == 0) { | |
766 | *id = res; | |
767 | return 0; | |
768 | } | |
769 | ||
770 | if (!protodown_reason_init) | |
771 | protodown_reason_initialize(); | |
772 | ||
773 | for (i = 0; i < PROTODOWN_REASON_NUM_BITS; i++) { | |
774 | if (protodown_reason_tab[i] && | |
775 | strcmp(protodown_reason_tab[i], arg) == 0) { | |
776 | cache = protodown_reason_tab[i]; | |
777 | res = i; | |
778 | *id = res; | |
779 | return 0; | |
780 | } | |
781 | } | |
782 | ||
783 | res = strtoul(arg, &end, 0); | |
784 | if (!end || end == arg || *end || res >= PROTODOWN_REASON_NUM_BITS) | |
785 | return -1; | |
786 | *id = res; | |
787 | return 0; | |
788 | } |