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