• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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