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