1/* vi: set sw=4 ts=4: */
2/*
3 * rt_names.c		rtnetlink names DB.
4 *
5 *		This program is free software; you can redistribute it and/or
6 *		modify it under the terms of the GNU General Public License
7 *		as published by the Free Software Foundation; either version
8 *		2 of the License, or (at your option) any later version.
9 *
10 * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
11 */
12
13#include "libbb.h"
14#include "rt_names.h"
15
16static void rtnl_tab_initialize(const char *file, const char **tab, int size)
17{
18	char buf[512];
19	FILE *fp;
20
21	fp = fopen(file, "r");
22	if (!fp)
23		return;
24	while (fgets(buf, sizeof(buf), fp)) {
25		char *p = buf;
26		int id;
27		char namebuf[512];
28
29		while (*p == ' ' || *p == '\t')
30			p++;
31		if (*p == '#' || *p == '\n' || *p == 0)
32			continue;
33		if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2
34		 && sscanf(p, "0x%x %s #", &id, namebuf) != 2
35		 && sscanf(p, "%d %s\n", &id, namebuf) != 2
36		 && sscanf(p, "%d %s #", &id, namebuf) != 2
37		) {
38			bb_error_msg("database %s is corrupted at %s",
39				file, p);
40			return;
41		}
42
43		if (id < 0 || id > size)
44			continue;
45
46		tab[id] = xstrdup(namebuf);
47	}
48	fclose(fp);
49}
50
51
52static const char **rtnl_rtprot_tab; /* [256] */
53
54static void rtnl_rtprot_initialize(void)
55{
56	static const char *const init_tab[] = {
57		"none",
58		"redirect",
59		"kernel",
60		"boot",
61		"static",
62		NULL,
63		NULL,
64		NULL,
65		"gated",
66		"ra",
67		"mrt",
68		"zebra",
69		"bird",
70	};
71	if (rtnl_rtprot_tab) return;
72	rtnl_rtprot_tab = xzalloc(256 * sizeof(rtnl_rtprot_tab[0]));
73	memcpy(rtnl_rtprot_tab, init_tab, sizeof(init_tab));
74	rtnl_tab_initialize("/etc/iproute2/rt_protos",
75			    rtnl_rtprot_tab, 256);
76}
77
78
79const char* rtnl_rtprot_n2a(int id, char *buf, int len)
80{
81	if (id < 0 || id >= 256) {
82		snprintf(buf, len, "%d", id);
83		return buf;
84	}
85
86	rtnl_rtprot_initialize();
87
88	if (rtnl_rtprot_tab[id])
89		return rtnl_rtprot_tab[id];
90	snprintf(buf, len, "%d", id);
91	return buf;
92}
93
94int rtnl_rtprot_a2n(uint32_t *id, char *arg)
95{
96	static const char *cache = NULL;
97	static unsigned long res;
98	int i;
99
100	if (cache && strcmp(cache, arg) == 0) {
101		*id = res;
102		return 0;
103	}
104
105	rtnl_rtprot_initialize();
106
107	for (i = 0; i < 256; i++) {
108		if (rtnl_rtprot_tab[i] &&
109		    strcmp(rtnl_rtprot_tab[i], arg) == 0) {
110			cache = rtnl_rtprot_tab[i];
111			res = i;
112			*id = res;
113			return 0;
114		}
115	}
116
117	res = bb_strtoul(arg, NULL, 0);
118	if (errno || res > 255)
119		return -1;
120	*id = res;
121	return 0;
122}
123
124
125static const char **rtnl_rtscope_tab; /* [256] */
126
127static void rtnl_rtscope_initialize(void)
128{
129	if (rtnl_rtscope_tab) return;
130	rtnl_rtscope_tab = xzalloc(256 * sizeof(rtnl_rtscope_tab[0]));
131	rtnl_rtscope_tab[0] = "global";
132	rtnl_rtscope_tab[255] = "nowhere";
133	rtnl_rtscope_tab[254] = "host";
134	rtnl_rtscope_tab[253] = "link";
135	rtnl_rtscope_tab[200] = "site";
136	rtnl_tab_initialize("/etc/iproute2/rt_scopes",
137			    rtnl_rtscope_tab, 256);
138}
139
140
141const char* rtnl_rtscope_n2a(int id, char *buf, int len)
142{
143	if (id < 0 || id >= 256) {
144		snprintf(buf, len, "%d", id);
145		return buf;
146	}
147
148	rtnl_rtscope_initialize();
149
150	if (rtnl_rtscope_tab[id])
151		return rtnl_rtscope_tab[id];
152	snprintf(buf, len, "%d", id);
153	return buf;
154}
155
156int rtnl_rtscope_a2n(uint32_t *id, char *arg)
157{
158	static const char *cache = NULL;
159	static unsigned long res;
160	int i;
161
162	if (cache && strcmp(cache, arg) == 0) {
163		*id = res;
164		return 0;
165	}
166
167	rtnl_rtscope_initialize();
168
169	for (i = 0; i < 256; i++) {
170		if (rtnl_rtscope_tab[i] &&
171		    strcmp(rtnl_rtscope_tab[i], arg) == 0) {
172			cache = rtnl_rtscope_tab[i];
173			res = i;
174			*id = res;
175			return 0;
176		}
177	}
178
179	res = bb_strtoul(arg, NULL, 0);
180	if (errno || res > 255)
181		return -1;
182	*id = res;
183	return 0;
184}
185
186
187static const char **rtnl_rtrealm_tab; /* [256] */
188
189static void rtnl_rtrealm_initialize(void)
190{
191	if (rtnl_rtrealm_tab) return;
192	rtnl_rtrealm_tab = xzalloc(256 * sizeof(rtnl_rtrealm_tab[0]));
193	rtnl_rtrealm_tab[0] = "unknown";
194	rtnl_tab_initialize("/etc/iproute2/rt_realms",
195			    rtnl_rtrealm_tab, 256);
196}
197
198
199int rtnl_rtrealm_a2n(uint32_t *id, char *arg)
200{
201	static const char *cache = NULL;
202	static unsigned long res;
203	int i;
204
205	if (cache && strcmp(cache, arg) == 0) {
206		*id = res;
207		return 0;
208	}
209
210	rtnl_rtrealm_initialize();
211
212	for (i = 0; i < 256; i++) {
213		if (rtnl_rtrealm_tab[i] &&
214		    strcmp(rtnl_rtrealm_tab[i], arg) == 0) {
215			cache = rtnl_rtrealm_tab[i];
216			res = i;
217			*id = res;
218			return 0;
219		}
220	}
221
222	res = bb_strtoul(arg, NULL, 0);
223	if (errno || res > 255)
224		return -1;
225	*id = res;
226	return 0;
227}
228
229#if ENABLE_FEATURE_IP_RULE
230const char* rtnl_rtrealm_n2a(int id, char *buf, int len)
231{
232	if (id < 0 || id >= 256) {
233		snprintf(buf, len, "%d", id);
234		return buf;
235	}
236
237	rtnl_rtrealm_initialize();
238
239	if (rtnl_rtrealm_tab[id])
240		return rtnl_rtrealm_tab[id];
241	snprintf(buf, len, "%d", id);
242	return buf;
243}
244#endif
245
246
247static const char **rtnl_rtdsfield_tab; /* [256] */
248
249static void rtnl_rtdsfield_initialize(void)
250{
251	if (rtnl_rtdsfield_tab) return;
252	rtnl_rtdsfield_tab = xzalloc(256 * sizeof(rtnl_rtdsfield_tab[0]));
253	rtnl_rtdsfield_tab[0] = "0";
254	rtnl_tab_initialize("/etc/iproute2/rt_dsfield",
255			    rtnl_rtdsfield_tab, 256);
256}
257
258
259const char * rtnl_dsfield_n2a(int id, char *buf, int len)
260{
261	if (id < 0 || id >= 256) {
262		snprintf(buf, len, "%d", id);
263		return buf;
264	}
265
266	rtnl_rtdsfield_initialize();
267
268	if (rtnl_rtdsfield_tab[id])
269		return rtnl_rtdsfield_tab[id];
270	snprintf(buf, len, "0x%02x", id);
271	return buf;
272}
273
274
275int rtnl_dsfield_a2n(uint32_t *id, char *arg)
276{
277	static const char *cache = NULL;
278	static unsigned long res;
279	int i;
280
281	if (cache && strcmp(cache, arg) == 0) {
282		*id = res;
283		return 0;
284	}
285
286	rtnl_rtdsfield_initialize();
287
288	for (i = 0; i < 256; i++) {
289		if (rtnl_rtdsfield_tab[i] &&
290		    strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
291			cache = rtnl_rtdsfield_tab[i];
292			res = i;
293			*id = res;
294			return 0;
295		}
296	}
297
298	res = bb_strtoul(arg, NULL, 16);
299	if (errno || res > 255)
300		return -1;
301	*id = res;
302	return 0;
303}
304
305
306#if ENABLE_FEATURE_IP_RULE
307static const char **rtnl_rttable_tab; /* [256] */
308
309static void rtnl_rttable_initialize(void)
310{
311	if (rtnl_rtdsfield_tab) return;
312	rtnl_rttable_tab = xzalloc(256 * sizeof(rtnl_rttable_tab[0]));
313	rtnl_rttable_tab[0] = "unspec";
314	rtnl_rttable_tab[255] = "local";
315	rtnl_rttable_tab[254] = "main";
316	rtnl_rttable_tab[253] = "default";
317	rtnl_tab_initialize("/etc/iproute2/rt_tables", rtnl_rttable_tab, 256);
318}
319
320
321const char *rtnl_rttable_n2a(int id, char *buf, int len)
322{
323	if (id < 0 || id >= 256) {
324		snprintf(buf, len, "%d", id);
325		return buf;
326	}
327
328	rtnl_rttable_initialize();
329
330	if (rtnl_rttable_tab[id])
331		return rtnl_rttable_tab[id];
332	snprintf(buf, len, "%d", id);
333	return buf;
334}
335
336int rtnl_rttable_a2n(uint32_t * id, char *arg)
337{
338	static char *cache = NULL;
339	static unsigned long res;
340	int i;
341
342	if (cache && strcmp(cache, arg) == 0) {
343		*id = res;
344		return 0;
345	}
346
347	rtnl_rttable_initialize();
348
349	for (i = 0; i < 256; i++) {
350		if (rtnl_rttable_tab[i] && strcmp(rtnl_rttable_tab[i], arg) == 0) {
351			cache = (char*)rtnl_rttable_tab[i];
352			res = i;
353			*id = res;
354			return 0;
355		}
356	}
357
358	i = bb_strtoul(arg, NULL, 0);
359	if (errno || i > 255)
360		return -1;
361	*id = i;
362	return 0;
363}
364
365#endif
366