1 /* vi: set sw=4 ts=4: */
2 /*
3  * This program is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU General Public License
5  * as published by the Free Software Foundation; either version
6  * 2 of the License, or (at your option) any later version.
7  *
8  * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
9  */
10 #include "libbb.h"
11 #include "rt_names.h"
12 
13 #define CONFDIR          CONFIG_FEATURE_IP_ROUTE_DIR
14 
15 typedef struct rtnl_tab_t {
16 	const char *cached_str;
17 	unsigned cached_result;
18 	/* upstream version switched to a hash table and removed
19 	 * id < 256 limit. For now bbox bumps this array size from 256
20 	 * to 1024. If you plan to change this to a hash table,
21 	 * consider merging several hash tables we have (for example,
22 	 * awk has resizable one!
23 	 */
24 #define RT_TABLE_MAX 1023
25 	const char *tab[RT_TABLE_MAX+1];
26 } rtnl_tab_t;
27 
rtnl_tab_initialize(const char * file,const char ** tab)28 static void rtnl_tab_initialize(const char *file, const char **tab)
29 {
30 	char *token[2];
31 	char fullname[sizeof(CONFDIR"/rt_dsfield") + 8];
32 	parser_t *parser;
33 
34 	sprintf(fullname, CONFDIR"/rt_%s", file);
35 	parser = config_open2(fullname, fopen_for_read);
36 	while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
37 		unsigned id = bb_strtou(token[0], NULL, 0);
38 		if (id > RT_TABLE_MAX) {
39 			bb_error_msg("database %s is corrupted at line %d",
40 				file, parser->lineno);
41 			break;
42 		}
43 		tab[id] = xstrdup(token[1]);
44 	}
45 	config_close(parser);
46 }
47 
rtnl_a2n(rtnl_tab_t * tab,uint32_t * id,const char * arg,int base)48 static int rtnl_a2n(rtnl_tab_t *tab, uint32_t *id, const char *arg, int base)
49 {
50 	unsigned i;
51 
52 	if (tab->cached_str && strcmp(tab->cached_str, arg) == 0) {
53 		*id = tab->cached_result;
54 		return 0;
55 	}
56 
57 	for (i = 0; i <= RT_TABLE_MAX; i++) {
58 		if (tab->tab[i]
59 		 && strcmp(tab->tab[i], arg) == 0
60 		) {
61 			tab->cached_str = tab->tab[i];
62 			tab->cached_result = i;
63 			*id = i;
64 			return 0;
65 		}
66 	}
67 
68 	i = bb_strtou(arg, NULL, base);
69 	if (i > RT_TABLE_MAX)
70 		return -1;
71 	*id = i;
72 	return 0;
73 }
74 
75 
76 static rtnl_tab_t *rtnl_rtprot_tab;
77 
rtnl_rtprot_initialize(void)78 static void rtnl_rtprot_initialize(void)
79 {
80 	static const char *const init_tab[] ALIGN_PTR = {
81 		"none",
82 		"redirect",
83 		"kernel",
84 		"boot",
85 		"static",
86 		NULL,
87 		NULL,
88 		NULL,
89 		"gated",
90 		"ra",
91 		"mrt",
92 		"zebra",
93 		"bird",
94 	};
95 
96 	if (rtnl_rtprot_tab)
97 		return;
98 	rtnl_rtprot_tab = xzalloc(sizeof(*rtnl_rtprot_tab));
99 	memcpy(rtnl_rtprot_tab->tab, init_tab, sizeof(init_tab));
100 	rtnl_tab_initialize("protos", rtnl_rtprot_tab->tab);
101 }
102 
103 #if 0 /* UNUSED */
104 const char* FAST_FUNC rtnl_rtprot_n2a(int id)
105 {
106 	if (id < 0 || id > RT_TABLE_MAX) {
107 		return itoa(id);
108 	}
109 
110 	rtnl_rtprot_initialize();
111 
112 	if (rtnl_rtprot_tab->tab[id])
113 		return rtnl_rtprot_tab->tab[id];
114 	return itoa(id);
115 }
116 #endif
117 
rtnl_rtprot_a2n(uint32_t * id,char * arg)118 int FAST_FUNC rtnl_rtprot_a2n(uint32_t *id, char *arg)
119 {
120 	rtnl_rtprot_initialize();
121 	return rtnl_a2n(rtnl_rtprot_tab, id, arg, 0);
122 }
123 
124 
125 static rtnl_tab_t *rtnl_rtscope_tab;
126 
rtnl_rtscope_initialize(void)127 static void rtnl_rtscope_initialize(void)
128 {
129 	if (rtnl_rtscope_tab)
130 		return;
131 	rtnl_rtscope_tab = xzalloc(sizeof(*rtnl_rtscope_tab));
132 	rtnl_rtscope_tab->tab[0] = "global";
133 	rtnl_rtscope_tab->tab[255] = "nowhere";
134 	rtnl_rtscope_tab->tab[254] = "host";
135 	rtnl_rtscope_tab->tab[253] = "link";
136 	rtnl_rtscope_tab->tab[200] = "site";
137 	rtnl_tab_initialize("scopes", rtnl_rtscope_tab->tab);
138 }
139 
rtnl_rtscope_n2a(int id)140 const char* FAST_FUNC rtnl_rtscope_n2a(int id)
141 {
142 	if (id < 0 || id > RT_TABLE_MAX) {
143 		return itoa(id);
144 	}
145 
146 	rtnl_rtscope_initialize();
147 
148 	if (rtnl_rtscope_tab->tab[id])
149 		return rtnl_rtscope_tab->tab[id];
150 	return itoa(id);
151 }
152 
rtnl_rtscope_a2n(uint32_t * id,char * arg)153 int FAST_FUNC rtnl_rtscope_a2n(uint32_t *id, char *arg)
154 {
155 	rtnl_rtscope_initialize();
156 	return rtnl_a2n(rtnl_rtscope_tab, id, arg, 0);
157 }
158 
159 
160 static rtnl_tab_t *rtnl_rtrealm_tab;
161 
rtnl_rtrealm_initialize(void)162 static void rtnl_rtrealm_initialize(void)
163 {
164 	if (rtnl_rtrealm_tab) return;
165 	rtnl_rtrealm_tab = xzalloc(sizeof(*rtnl_rtrealm_tab));
166 	rtnl_rtrealm_tab->tab[0] = "unknown";
167 	rtnl_tab_initialize("realms", rtnl_rtrealm_tab->tab);
168 }
169 
rtnl_rtrealm_a2n(uint32_t * id,char * arg)170 int FAST_FUNC rtnl_rtrealm_a2n(uint32_t *id, char *arg)
171 {
172 	rtnl_rtrealm_initialize();
173 	return rtnl_a2n(rtnl_rtrealm_tab, id, arg, 0);
174 }
175 
176 #if ENABLE_FEATURE_IP_RULE
rtnl_rtrealm_n2a(int id)177 const char* FAST_FUNC rtnl_rtrealm_n2a(int id)
178 {
179 	if (id < 0 || id > RT_TABLE_MAX) {
180 		return itoa(id);
181 	}
182 
183 	rtnl_rtrealm_initialize();
184 
185 	if (rtnl_rtrealm_tab->tab[id])
186 		return rtnl_rtrealm_tab->tab[id];
187 	return itoa(id);
188 }
189 #endif
190 
191 
192 static rtnl_tab_t *rtnl_rtdsfield_tab;
193 
rtnl_rtdsfield_initialize(void)194 static void rtnl_rtdsfield_initialize(void)
195 {
196 	if (rtnl_rtdsfield_tab) return;
197 	rtnl_rtdsfield_tab = xzalloc(sizeof(*rtnl_rtdsfield_tab));
198 	rtnl_rtdsfield_tab->tab[0] = "0";
199 	rtnl_tab_initialize("dsfield", rtnl_rtdsfield_tab->tab);
200 }
201 
rtnl_dsfield_n2a(int id)202 const char* FAST_FUNC rtnl_dsfield_n2a(int id)
203 {
204 	if (id < 0 || id > RT_TABLE_MAX) {
205 		return itoa(id);
206 	}
207 
208 	rtnl_rtdsfield_initialize();
209 
210 	if (rtnl_rtdsfield_tab->tab[id])
211 		return rtnl_rtdsfield_tab->tab[id];
212 	return itoa(id);
213 }
214 
rtnl_dsfield_a2n(uint32_t * id,char * arg)215 int FAST_FUNC rtnl_dsfield_a2n(uint32_t *id, char *arg)
216 {
217 	rtnl_rtdsfield_initialize();
218 	return rtnl_a2n(rtnl_rtdsfield_tab, id, arg, 16);
219 }
220 
221 
222 #if ENABLE_FEATURE_IP_RULE
223 static rtnl_tab_t *rtnl_rttable_tab;
224 
rtnl_rttable_initialize(void)225 static void rtnl_rttable_initialize(void)
226 {
227 	if (rtnl_rttable_tab)
228 		return;
229 
230 	rtnl_rttable_tab = xzalloc(sizeof(*rtnl_rttable_tab));
231 	rtnl_rttable_tab->tab[0] = "unspec";
232 	rtnl_rttable_tab->tab[255] = "local";
233 	rtnl_rttable_tab->tab[254] = "main";
234 	rtnl_rttable_tab->tab[253] = "default";
235 	rtnl_tab_initialize("tables", rtnl_rttable_tab->tab);
236 }
237 
rtnl_rttable_n2a(int id)238 const char* FAST_FUNC rtnl_rttable_n2a(int id)
239 {
240 	if (id < 0 || id > RT_TABLE_MAX) {
241 		return itoa(id);
242 	}
243 
244 	rtnl_rttable_initialize();
245 
246 	if (rtnl_rttable_tab->tab[id])
247 		return rtnl_rttable_tab->tab[id];
248 	return itoa(id);
249 }
250 
rtnl_rttable_a2n(uint32_t * id,char * arg)251 int FAST_FUNC rtnl_rttable_a2n(uint32_t *id, char *arg)
252 {
253 	rtnl_rttable_initialize();
254 	return rtnl_a2n(rtnl_rttable_tab, id, arg, 0);
255 }
256 
257 #endif
258