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 struct rtnl_hash_entry {
27 struct rtnl_hash_entry *next;
28 char * name;
29 unsigned int id;
30 };
31
32 static void
rtnl_hash_initialize(char * file,struct rtnl_hash_entry ** hash,int size)33 rtnl_hash_initialize(char *file, struct rtnl_hash_entry **hash, int size)
34 {
35 struct rtnl_hash_entry *entry;
36 char buf[512];
37 FILE *fp;
38
39 fp = fopen(file, "r");
40 if (!fp)
41 return;
42 while (fgets(buf, sizeof(buf), fp)) {
43 char *p = buf;
44 int id;
45 char namebuf[512];
46
47 while (*p == ' ' || *p == '\t')
48 p++;
49 if (*p == '#' || *p == '\n' || *p == 0)
50 continue;
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 fprintf(stderr, "Database %s is corrupted at %s\n",
56 file, p);
57 return;
58 }
59
60 if (id<0)
61 continue;
62 entry = malloc(sizeof(*entry));
63 entry->id = id;
64 entry->name = strdup(namebuf);
65 entry->next = hash[id & (size - 1)];
66 hash[id & (size - 1)] = entry;
67 }
68 fclose(fp);
69 }
70
rtnl_tab_initialize(char * file,char ** tab,int size)71 static void rtnl_tab_initialize(char *file, char **tab, int size)
72 {
73 char buf[512];
74 FILE *fp;
75
76 fp = fopen(file, "r");
77 if (!fp)
78 return;
79 while (fgets(buf, sizeof(buf), fp)) {
80 char *p = buf;
81 int id;
82 char namebuf[512];
83
84 while (*p == ' ' || *p == '\t')
85 p++;
86 if (*p == '#' || *p == '\n' || *p == 0)
87 continue;
88 if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2 &&
89 sscanf(p, "0x%x %s #", &id, namebuf) != 2 &&
90 sscanf(p, "%d %s\n", &id, namebuf) != 2 &&
91 sscanf(p, "%d %s #", &id, namebuf) != 2) {
92 fprintf(stderr, "Database %s is corrupted at %s\n",
93 file, p);
94 return;
95 }
96
97 if (id<0 || id>size)
98 continue;
99
100 tab[id] = strdup(namebuf);
101 }
102 fclose(fp);
103 }
104
105 static char * rtnl_rtprot_tab[256] = {
106 [RTPROT_UNSPEC] = "none",
107 [RTPROT_REDIRECT] ="redirect",
108 [RTPROT_KERNEL] = "kernel",
109 [RTPROT_BOOT] = "boot",
110 [RTPROT_STATIC] = "static",
111
112 [RTPROT_GATED] = "gated",
113 [RTPROT_RA] = "ra",
114 [RTPROT_MRT] = "mrt",
115 [RTPROT_ZEBRA] ="zebra",
116 [RTPROT_BIRD] = "bird",
117 [RTPROT_DNROUTED] = "dnrouted",
118 [RTPROT_XORP] = "xorp",
119 [RTPROT_NTK] = "ntk",
120 [RTPROT_DHCP] = "dhcp",
121 };
122
123
124
125 static int rtnl_rtprot_init;
126
rtnl_rtprot_initialize(void)127 static void rtnl_rtprot_initialize(void)
128 {
129 rtnl_rtprot_init = 1;
130 rtnl_tab_initialize("/etc/iproute2/rt_protos",
131 rtnl_rtprot_tab, 256);
132 }
133
rtnl_rtprot_n2a(int id,char * buf,int len)134 char * rtnl_rtprot_n2a(int id, char *buf, int len)
135 {
136 if (id<0 || id>=256) {
137 snprintf(buf, len, "%d", id);
138 return buf;
139 }
140 if (!rtnl_rtprot_tab[id]) {
141 if (!rtnl_rtprot_init)
142 rtnl_rtprot_initialize();
143 }
144 if (rtnl_rtprot_tab[id])
145 return rtnl_rtprot_tab[id];
146 snprintf(buf, len, "%d", id);
147 return buf;
148 }
149
rtnl_rtprot_a2n(__u32 * id,char * arg)150 int rtnl_rtprot_a2n(__u32 *id, char *arg)
151 {
152 static char *cache = NULL;
153 static unsigned long res;
154 char *end;
155 int i;
156
157 if (cache && strcmp(cache, arg) == 0) {
158 *id = res;
159 return 0;
160 }
161
162 if (!rtnl_rtprot_init)
163 rtnl_rtprot_initialize();
164
165 for (i=0; i<256; i++) {
166 if (rtnl_rtprot_tab[i] &&
167 strcmp(rtnl_rtprot_tab[i], arg) == 0) {
168 cache = rtnl_rtprot_tab[i];
169 res = i;
170 *id = res;
171 return 0;
172 }
173 }
174
175 res = strtoul(arg, &end, 0);
176 if (!end || end == arg || *end || res > 255)
177 return -1;
178 *id = res;
179 return 0;
180 }
181
182
183
184 static char * rtnl_rtscope_tab[256] = {
185 "global",
186 };
187
188 static int rtnl_rtscope_init;
189
rtnl_rtscope_initialize(void)190 static void rtnl_rtscope_initialize(void)
191 {
192 rtnl_rtscope_init = 1;
193 rtnl_rtscope_tab[255] = "nowhere";
194 rtnl_rtscope_tab[254] = "host";
195 rtnl_rtscope_tab[253] = "link";
196 rtnl_rtscope_tab[200] = "site";
197 rtnl_tab_initialize("/etc/iproute2/rt_scopes",
198 rtnl_rtscope_tab, 256);
199 }
200
rtnl_rtscope_n2a(int id,char * buf,int len)201 char * rtnl_rtscope_n2a(int id, char *buf, int len)
202 {
203 if (id<0 || id>=256) {
204 snprintf(buf, len, "%d", id);
205 return buf;
206 }
207 if (!rtnl_rtscope_tab[id]) {
208 if (!rtnl_rtscope_init)
209 rtnl_rtscope_initialize();
210 }
211 if (rtnl_rtscope_tab[id])
212 return rtnl_rtscope_tab[id];
213 snprintf(buf, len, "%d", id);
214 return buf;
215 }
216
rtnl_rtscope_a2n(__u32 * id,char * arg)217 int rtnl_rtscope_a2n(__u32 *id, char *arg)
218 {
219 static char *cache = NULL;
220 static unsigned long res;
221 char *end;
222 int i;
223
224 if (cache && strcmp(cache, arg) == 0) {
225 *id = res;
226 return 0;
227 }
228
229 if (!rtnl_rtscope_init)
230 rtnl_rtscope_initialize();
231
232 for (i=0; i<256; i++) {
233 if (rtnl_rtscope_tab[i] &&
234 strcmp(rtnl_rtscope_tab[i], arg) == 0) {
235 cache = rtnl_rtscope_tab[i];
236 res = i;
237 *id = res;
238 return 0;
239 }
240 }
241
242 res = strtoul(arg, &end, 0);
243 if (!end || end == arg || *end || res > 255)
244 return -1;
245 *id = res;
246 return 0;
247 }
248
249
250
251 static char * rtnl_rtrealm_tab[256] = {
252 "unknown",
253 };
254
255 static int rtnl_rtrealm_init;
256
rtnl_rtrealm_initialize(void)257 static void rtnl_rtrealm_initialize(void)
258 {
259 rtnl_rtrealm_init = 1;
260 rtnl_tab_initialize("/etc/iproute2/rt_realms",
261 rtnl_rtrealm_tab, 256);
262 }
263
rtnl_rtrealm_n2a(int id,char * buf,int len)264 char * rtnl_rtrealm_n2a(int id, char *buf, int len)
265 {
266 if (id<0 || id>=256) {
267 snprintf(buf, len, "%d", id);
268 return buf;
269 }
270 if (!rtnl_rtrealm_tab[id]) {
271 if (!rtnl_rtrealm_init)
272 rtnl_rtrealm_initialize();
273 }
274 if (rtnl_rtrealm_tab[id])
275 return rtnl_rtrealm_tab[id];
276 snprintf(buf, len, "%d", id);
277 return buf;
278 }
279
280
rtnl_rtrealm_a2n(__u32 * id,char * arg)281 int rtnl_rtrealm_a2n(__u32 *id, char *arg)
282 {
283 static char *cache = NULL;
284 static unsigned long res;
285 char *end;
286 int i;
287
288 if (cache && strcmp(cache, arg) == 0) {
289 *id = res;
290 return 0;
291 }
292
293 if (!rtnl_rtrealm_init)
294 rtnl_rtrealm_initialize();
295
296 for (i=0; i<256; i++) {
297 if (rtnl_rtrealm_tab[i] &&
298 strcmp(rtnl_rtrealm_tab[i], arg) == 0) {
299 cache = rtnl_rtrealm_tab[i];
300 res = i;
301 *id = res;
302 return 0;
303 }
304 }
305
306 res = strtoul(arg, &end, 0);
307 if (!end || end == arg || *end || res > 255)
308 return -1;
309 *id = res;
310 return 0;
311 }
312
313
314 static struct rtnl_hash_entry dflt_table_entry = { .id = 253, .name = "default" };
315 static struct rtnl_hash_entry main_table_entry = { .id = 254, .name = "main" };
316 static struct rtnl_hash_entry local_table_entry = { .id = 255, .name = "local" };
317
318 static struct rtnl_hash_entry * rtnl_rttable_hash[256] = {
319 [253] = &dflt_table_entry,
320 [254] = &main_table_entry,
321 [255] = &local_table_entry,
322 };
323
324 static int rtnl_rttable_init;
325
rtnl_rttable_initialize(void)326 static void rtnl_rttable_initialize(void)
327 {
328 rtnl_rttable_init = 1;
329 rtnl_hash_initialize("/etc/iproute2/rt_tables",
330 rtnl_rttable_hash, 256);
331 }
332
rtnl_rttable_n2a(__u32 id,char * buf,int len)333 char * rtnl_rttable_n2a(__u32 id, char *buf, int len)
334 {
335 struct rtnl_hash_entry *entry;
336
337 if (id > RT_TABLE_MAX) {
338 snprintf(buf, len, "%u", id);
339 return buf;
340 }
341 if (!rtnl_rttable_init)
342 rtnl_rttable_initialize();
343 entry = rtnl_rttable_hash[id & 255];
344 while (entry && entry->id != id)
345 entry = entry->next;
346 if (entry)
347 return entry->name;
348 snprintf(buf, len, "%u", id);
349 return buf;
350 }
351
rtnl_rttable_a2n(__u32 * id,char * arg)352 int rtnl_rttable_a2n(__u32 *id, char *arg)
353 {
354 static char *cache = NULL;
355 static unsigned long res;
356 struct rtnl_hash_entry *entry;
357 char *end;
358 __u32 i;
359
360 if (cache && strcmp(cache, arg) == 0) {
361 *id = res;
362 return 0;
363 }
364
365 if (!rtnl_rttable_init)
366 rtnl_rttable_initialize();
367
368 for (i=0; i<256; i++) {
369 entry = rtnl_rttable_hash[i];
370 while (entry && strcmp(entry->name, arg))
371 entry = entry->next;
372 if (entry) {
373 cache = entry->name;
374 res = entry->id;
375 *id = res;
376 return 0;
377 }
378 }
379
380 i = strtoul(arg, &end, 0);
381 if (!end || end == arg || *end || i > RT_TABLE_MAX)
382 return -1;
383 *id = i;
384 return 0;
385 }
386
387
388 static char * rtnl_rtdsfield_tab[256] = {
389 "0",
390 };
391
392 static int rtnl_rtdsfield_init;
393
rtnl_rtdsfield_initialize(void)394 static void rtnl_rtdsfield_initialize(void)
395 {
396 rtnl_rtdsfield_init = 1;
397 rtnl_tab_initialize("/etc/iproute2/rt_dsfield",
398 rtnl_rtdsfield_tab, 256);
399 }
400
rtnl_dsfield_n2a(int id,char * buf,int len)401 char * rtnl_dsfield_n2a(int id, char *buf, int len)
402 {
403 if (id<0 || id>=256) {
404 snprintf(buf, len, "%d", id);
405 return buf;
406 }
407 if (!rtnl_rtdsfield_tab[id]) {
408 if (!rtnl_rtdsfield_init)
409 rtnl_rtdsfield_initialize();
410 }
411 if (rtnl_rtdsfield_tab[id])
412 return rtnl_rtdsfield_tab[id];
413 snprintf(buf, len, "0x%02x", id);
414 return buf;
415 }
416
417
rtnl_dsfield_a2n(__u32 * id,char * arg)418 int rtnl_dsfield_a2n(__u32 *id, char *arg)
419 {
420 static char *cache = NULL;
421 static unsigned long res;
422 char *end;
423 int i;
424
425 if (cache && strcmp(cache, arg) == 0) {
426 *id = res;
427 return 0;
428 }
429
430 if (!rtnl_rtdsfield_init)
431 rtnl_rtdsfield_initialize();
432
433 for (i=0; i<256; i++) {
434 if (rtnl_rtdsfield_tab[i] &&
435 strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
436 cache = rtnl_rtdsfield_tab[i];
437 res = i;
438 *id = res;
439 return 0;
440 }
441 }
442
443 res = strtoul(arg, &end, 16);
444 if (!end || end == arg || *end || res > 255)
445 return -1;
446 *id = res;
447 return 0;
448 }
449
450