libiproute: handle table ids larger than 255
[oweals/busybox.git] / networking / libiproute / rt_names.c
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
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
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
78 static void rtnl_rtprot_initialize(void)
79 {
80         static const char *const init_tab[] = {
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
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
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
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
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
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
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
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
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
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
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
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
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
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