BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file parse.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * @section DESCRIPTION
30 *
31 * Synopsis:
32 * parse_number(string str)
33 * parse_hex_number(string str)
34 * parse_value(string str)
35 * parse_ipv4_addr(string str)
36 * parse_ipv6_addr(string str)
37 *
38 * Variables:
39 * succeeded - "true" or "false", reflecting success of the parsing
40 * (empty) - normalized parsed value (only if succeeded)
41 *
42 * Synopsis:
43 * parse_ipv4_cidr_addr(string str)
44 * parse_ipv6_cidr_addr(string str)
45 *
46 * Variables:
47 * succeeded - "true" or "false", reflecting success of the parsing
48 * (empty) - normalized CIDR notation address (only if succeeded)
49 * addr - normalized address without prefix (only if succeeded)
50 * prefix - normalized prefix without address (only if succeeded)
51 */
52  
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <inttypes.h>
56  
57 #include <misc/parse_number.h>
58 #include <misc/ipaddr.h>
59 #include <misc/ipaddr6.h>
60 #include <ncd/NCDValParser.h>
61  
62 #include <ncd/module_common.h>
63  
64 #include <generated/blog_channel_ncd_parse.h>
65  
66 struct instance {
67 NCDModuleInst *i;
68 NCDValMem mem;
69 NCDValRef value;
70 int succeeded;
71 };
72  
73 struct ipv4_cidr_instance {
74 NCDModuleInst *i;
75 int succeeded;
76 struct ipv4_ifaddr ifaddr;
77 };
78  
79 struct ipv6_cidr_instance {
80 NCDModuleInst *i;
81 int succeeded;
82 struct ipv6_ifaddr ifaddr;
83 };
84  
85 enum {STRING_ADDR, STRING_PREFIX};
86  
87 static const char *strings[] = {
88 "addr", "prefix", NULL
89 };
90  
91 typedef int (*parse_func) (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out);
92  
93 static int parse_number (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
94 {
95 uintmax_t n;
96 if (!parse_unsigned_integer(str, &n)) {
97 ModuleLog(i, BLOG_ERROR, "failed to parse number");
98 return 0;
99 }
100  
101 *out = ncd_make_uintmax(mem, n);
102 if (NCDVal_IsInvalid(*out)) {
103 return 0;
104 }
105  
106 return 1;
107 }
108  
109 static int parse_hex_number (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
110 {
111 uintmax_t n;
112 if (!parse_unsigned_hex_integer(str, &n)) {
113 ModuleLog(i, BLOG_ERROR, "failed to parse hex number");
114 return 0;
115 }
116  
117 *out = ncd_make_uintmax(mem, n);
118 if (NCDVal_IsInvalid(*out)) {
119 return 0;
120 }
121  
122 return 1;
123 }
124  
125 static int parse_value (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
126 {
127 if (!NCDValParser_Parse(str, mem, out)) {
128 ModuleLog(i, BLOG_ERROR, "failed to parse value");
129 return 0;
130 }
131  
132 return 1;
133 }
134  
135 static int parse_ipv4_addr (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
136 {
137 uint32_t addr;
138 if (!ipaddr_parse_ipv4_addr(str, &addr)) {
139 ModuleLog(i, BLOG_ERROR, "failed to parse ipv4 addresss");
140 return 0;
141 }
142  
143 char buf[IPADDR_PRINT_MAX];
144 ipaddr_print_addr(addr, buf);
145  
146 *out = NCDVal_NewString(mem, buf);
147 if (NCDVal_IsInvalid(*out)) {
148 return 0;
149 }
150  
151 return 1;
152 }
153  
154 static int parse_ipv6_addr (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
155 {
156 struct ipv6_addr addr;
157 if (!ipaddr6_parse_ipv6_addr(str, &addr)) {
158 ModuleLog(i, BLOG_ERROR, "failed to parse ipv6 addresss");
159 return 0;
160 }
161  
162 char buf[IPADDR6_PRINT_MAX];
163 ipaddr6_print_addr(addr, buf);
164  
165 *out = NCDVal_NewString(mem, buf);
166 if (NCDVal_IsInvalid(*out)) {
167 return 0;
168 }
169  
170 return 1;
171 }
172  
173 static void new_templ (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params, parse_func pfunc)
174 {
175 struct instance *o = vo;
176 o->i = i;
177  
178 // read arguments
179 NCDValRef str_arg;
180 if (!NCDVal_ListRead(params->args, 1, &str_arg)) {
181 ModuleLog(i, BLOG_ERROR, "wrong arity");
182 goto fail0;
183 }
184 if (!NCDVal_IsString(str_arg)) {
185 ModuleLog(o->i, BLOG_ERROR, "wrong type");
186 goto fail0;
187 }
188  
189 // init mem
190 NCDValMem_Init(&o->mem, i->params->iparams->string_index);
191  
192 // parse
193 o->succeeded = pfunc(i, NCDVal_StringMemRef(str_arg), &o->mem, &o->value);
194  
195 // signal up
196 NCDModuleInst_Backend_Up(i);
197 return;
198  
199 fail0:
200 NCDModuleInst_Backend_DeadError(i);
201 }
202  
203 static void func_die (void *vo)
204 {
205 struct instance *o = vo;
206  
207 // free mem
208 NCDValMem_Free(&o->mem);
209  
210 NCDModuleInst_Backend_Dead(o->i);
211 }
212  
213 static int func_getvar2 (void *vo, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
214 {
215 struct instance *o = vo;
216  
217 if (name == NCD_STRING_SUCCEEDED) {
218 *out = ncd_make_boolean(mem, o->succeeded);
219 return 1;
220 }
221  
222 if (o->succeeded && name == NCD_STRING_EMPTY) {
223 *out = NCDVal_NewCopy(mem, o->value);
224 return 1;
225 }
226  
227 return 0;
228 }
229  
230 static void func_new_parse_number (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
231 {
232 new_templ(vo, i, params, parse_number);
233 }
234  
235 static void func_new_parse_hex_number (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
236 {
237 new_templ(vo, i, params, parse_hex_number);
238 }
239  
240 static void func_new_parse_value (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
241 {
242 new_templ(vo, i, params, parse_value);
243 }
244  
245 static void func_new_parse_ipv4_addr (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
246 {
247 new_templ(vo, i, params, parse_ipv4_addr);
248 }
249  
250 static void func_new_parse_ipv6_addr (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
251 {
252 new_templ(vo, i, params, parse_ipv6_addr);
253 }
254  
255 static void ipv4_cidr_addr_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
256 {
257 struct ipv4_cidr_instance *o = vo;
258 o->i = i;
259  
260 NCDValRef str_arg;
261 if (!NCDVal_ListRead(params->args, 1, &str_arg)) {
262 ModuleLog(i, BLOG_ERROR, "wrong arity");
263 goto fail0;
264 }
265 if (!NCDVal_IsString(str_arg)) {
266 ModuleLog(o->i, BLOG_ERROR, "wrong type");
267 goto fail0;
268 }
269  
270 o->succeeded = ipaddr_parse_ipv4_ifaddr(NCDVal_StringMemRef(str_arg), &o->ifaddr);
271  
272 NCDModuleInst_Backend_Up(i);
273 return;
274  
275 fail0:
276 NCDModuleInst_Backend_DeadError(i);
277 }
278  
279 static int ipv4_cidr_addr_func_getvar2 (void *vo, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
280 {
281 struct ipv4_cidr_instance *o = vo;
282  
283 if (name == NCD_STRING_SUCCEEDED) {
284 *out = ncd_make_boolean(mem, o->succeeded);
285 return 1;
286 }
287  
288 if (!o->succeeded) {
289 return 0;
290 }
291  
292 char str[IPADDR_PRINT_MAX];
293  
294 if (name == NCD_STRING_EMPTY) {
295 ipaddr_print_ifaddr(o->ifaddr, str);
296 }
297 else if (name == ModuleString(o->i, STRING_ADDR)) {
298 ipaddr_print_addr(o->ifaddr.addr, str);
299 }
300 else if (name == ModuleString(o->i, STRING_PREFIX)) {
301 sprintf(str, "%d", o->ifaddr.prefix);
302 }
303 else {
304 return 0;
305 }
306  
307 *out = NCDVal_NewString(mem, str);
308 return 1;
309 }
310  
311 static void ipv6_cidr_addr_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
312 {
313 struct ipv6_cidr_instance *o = vo;
314 o->i = i;
315  
316 NCDValRef str_arg;
317 if (!NCDVal_ListRead(params->args, 1, &str_arg)) {
318 ModuleLog(i, BLOG_ERROR, "wrong arity");
319 goto fail0;
320 }
321 if (!NCDVal_IsString(str_arg)) {
322 ModuleLog(o->i, BLOG_ERROR, "wrong type");
323 goto fail0;
324 }
325  
326 o->succeeded = ipaddr6_parse_ipv6_ifaddr(NCDVal_StringMemRef(str_arg), &o->ifaddr);
327  
328 NCDModuleInst_Backend_Up(i);
329 return;
330  
331 fail0:
332 NCDModuleInst_Backend_DeadError(i);
333 }
334  
335 static int ipv6_cidr_addr_func_getvar2 (void *vo, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
336 {
337 struct ipv6_cidr_instance *o = vo;
338  
339 if (name == NCD_STRING_SUCCEEDED) {
340 *out = ncd_make_boolean(mem, o->succeeded);
341 return 1;
342 }
343  
344 if (!o->succeeded) {
345 return 0;
346 }
347  
348 char str[IPADDR6_PRINT_MAX];
349  
350 if (name == NCD_STRING_EMPTY) {
351 ipaddr6_print_ifaddr(o->ifaddr, str);
352 }
353 else if (name == ModuleString(o->i, STRING_ADDR)) {
354 ipaddr6_print_addr(o->ifaddr.addr, str);
355 }
356 else if (name == ModuleString(o->i, STRING_PREFIX)) {
357 sprintf(str, "%d", o->ifaddr.prefix);
358 }
359 else {
360 return 0;
361 }
362  
363 *out = NCDVal_NewString(mem, str);
364 return 1;
365 }
366  
367 static struct NCDModule modules[] = {
368 {
369 .type = "parse_number",
370 .func_new2 = func_new_parse_number,
371 .func_die = func_die,
372 .func_getvar2 = func_getvar2,
373 .alloc_size = sizeof(struct instance)
374 }, {
375 .type = "parse_hex_number",
376 .func_new2 = func_new_parse_hex_number,
377 .func_die = func_die,
378 .func_getvar2 = func_getvar2,
379 .alloc_size = sizeof(struct instance)
380 }, {
381 .type = "parse_value",
382 .func_new2 = func_new_parse_value,
383 .func_die = func_die,
384 .func_getvar2 = func_getvar2,
385 .alloc_size = sizeof(struct instance)
386 }, {
387 .type = "parse_ipv4_addr",
388 .func_new2 = func_new_parse_ipv4_addr,
389 .func_die = func_die,
390 .func_getvar2 = func_getvar2,
391 .alloc_size = sizeof(struct instance)
392 }, {
393 .type = "parse_ipv6_addr",
394 .func_new2 = func_new_parse_ipv6_addr,
395 .func_die = func_die,
396 .func_getvar2 = func_getvar2,
397 .alloc_size = sizeof(struct instance)
398 }, {
399 .type = "parse_ipv4_cidr_addr",
400 .func_new2 = ipv4_cidr_addr_func_new,
401 .func_getvar2 = ipv4_cidr_addr_func_getvar2,
402 .alloc_size = sizeof(struct ipv4_cidr_instance)
403 }, {
404 .type = "parse_ipv6_cidr_addr",
405 .func_new2 = ipv6_cidr_addr_func_new,
406 .func_getvar2 = ipv6_cidr_addr_func_getvar2,
407 .alloc_size = sizeof(struct ipv6_cidr_instance)
408 }, {
409 .type = NULL
410 }
411 };
412  
413 const struct NCDModuleGroup ncdmodule_parse = {
414 .modules = modules,
415 .strings = strings
416 };