parse.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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_value(string str)
  34. * parse_ipv4_addr(string str)
  35. * parse_ipv6_addr(string str)
  36. *
  37. * Variables:
  38. * succeeded - "true" or "false", reflecting success of the parsing
  39. * (empty) - normalized parsed value (only if succeeded)
  40. *
  41. * Synopsis:
  42. * parse_ipv4_cidr_addr(string str)
  43. * parse_ipv6_cidr_addr(string str)
  44. *
  45. * Variables:
  46. * succeeded - "true" or "false", reflecting success of the parsing
  47. * (empty) - normalized CIDR notation address (only if succeeded)
  48. * addr - normalized address without prefix (only if succeeded)
  49. * prefix - normalized prefix without address (only if succeeded)
  50. */
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <inttypes.h>
  54. #include <misc/parse_number.h>
  55. #include <misc/ipaddr.h>
  56. #include <misc/ipaddr6.h>
  57. #include <ncd/NCDValParser.h>
  58. #include <ncd/module_common.h>
  59. #include <generated/blog_channel_ncd_parse.h>
  60. struct instance {
  61. NCDModuleInst *i;
  62. NCDValMem mem;
  63. NCDValRef value;
  64. int succeeded;
  65. };
  66. struct ipv4_cidr_instance {
  67. NCDModuleInst *i;
  68. int succeeded;
  69. struct ipv4_ifaddr ifaddr;
  70. };
  71. struct ipv6_cidr_instance {
  72. NCDModuleInst *i;
  73. int succeeded;
  74. struct ipv6_ifaddr ifaddr;
  75. };
  76. enum {STRING_ADDR, STRING_PREFIX};
  77. static const char *strings[] = {
  78. "addr", "prefix", NULL
  79. };
  80. typedef int (*parse_func) (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out);
  81. static int parse_number (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
  82. {
  83. uintmax_t n;
  84. if (!parse_unsigned_integer(str, &n)) {
  85. ModuleLog(i, BLOG_ERROR, "failed to parse number");
  86. return 0;
  87. }
  88. *out = ncd_make_uintmax(mem, n);
  89. if (NCDVal_IsInvalid(*out)) {
  90. return 0;
  91. }
  92. return 1;
  93. }
  94. static int parse_value (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
  95. {
  96. if (!NCDValParser_Parse(str.ptr, str.len, mem, out)) {
  97. ModuleLog(i, BLOG_ERROR, "failed to parse value");
  98. return 0;
  99. }
  100. return 1;
  101. }
  102. static int parse_ipv4_addr (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
  103. {
  104. uint32_t addr;
  105. if (!ipaddr_parse_ipv4_addr(str, &addr)) {
  106. ModuleLog(i, BLOG_ERROR, "failed to parse ipv4 addresss");
  107. return 0;
  108. }
  109. char buf[IPADDR_PRINT_MAX];
  110. ipaddr_print_addr(addr, buf);
  111. *out = NCDVal_NewString(mem, buf);
  112. if (NCDVal_IsInvalid(*out)) {
  113. return 0;
  114. }
  115. return 1;
  116. }
  117. static int parse_ipv6_addr (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
  118. {
  119. struct ipv6_addr addr;
  120. if (!ipaddr6_parse_ipv6_addr(str, &addr)) {
  121. ModuleLog(i, BLOG_ERROR, "failed to parse ipv6 addresss");
  122. return 0;
  123. }
  124. char buf[IPADDR6_PRINT_MAX];
  125. ipaddr6_print_addr(addr, buf);
  126. *out = NCDVal_NewString(mem, buf);
  127. if (NCDVal_IsInvalid(*out)) {
  128. return 0;
  129. }
  130. return 1;
  131. }
  132. static void new_templ (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params, parse_func pfunc)
  133. {
  134. struct instance *o = vo;
  135. o->i = i;
  136. // read arguments
  137. NCDValRef str_arg;
  138. if (!NCDVal_ListRead(params->args, 1, &str_arg)) {
  139. ModuleLog(i, BLOG_ERROR, "wrong arity");
  140. goto fail0;
  141. }
  142. if (!NCDVal_IsString(str_arg)) {
  143. ModuleLog(o->i, BLOG_ERROR, "wrong type");
  144. goto fail0;
  145. }
  146. // init mem
  147. NCDValMem_Init(&o->mem);
  148. // parse
  149. o->succeeded = pfunc(i, NCDVal_StringMemRef(str_arg), &o->mem, &o->value);
  150. // signal up
  151. NCDModuleInst_Backend_Up(i);
  152. return;
  153. fail0:
  154. NCDModuleInst_Backend_DeadError(i);
  155. }
  156. static void func_die (void *vo)
  157. {
  158. struct instance *o = vo;
  159. // free mem
  160. NCDValMem_Free(&o->mem);
  161. NCDModuleInst_Backend_Dead(o->i);
  162. }
  163. static int func_getvar2 (void *vo, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
  164. {
  165. struct instance *o = vo;
  166. if (name == NCD_STRING_SUCCEEDED) {
  167. *out = ncd_make_boolean(mem, o->succeeded, o->i->params->iparams->string_index);
  168. return 1;
  169. }
  170. if (o->succeeded && name == NCD_STRING_EMPTY) {
  171. *out = NCDVal_NewCopy(mem, o->value);
  172. return 1;
  173. }
  174. return 0;
  175. }
  176. static void func_new_parse_number (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
  177. {
  178. new_templ(vo, i, params, parse_number);
  179. }
  180. static void func_new_parse_value (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
  181. {
  182. new_templ(vo, i, params, parse_value);
  183. }
  184. static void func_new_parse_ipv4_addr (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
  185. {
  186. new_templ(vo, i, params, parse_ipv4_addr);
  187. }
  188. static void func_new_parse_ipv6_addr (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
  189. {
  190. new_templ(vo, i, params, parse_ipv6_addr);
  191. }
  192. static void ipv4_cidr_addr_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
  193. {
  194. struct ipv4_cidr_instance *o = vo;
  195. o->i = i;
  196. NCDValRef str_arg;
  197. if (!NCDVal_ListRead(params->args, 1, &str_arg)) {
  198. ModuleLog(i, BLOG_ERROR, "wrong arity");
  199. goto fail0;
  200. }
  201. if (!NCDVal_IsString(str_arg)) {
  202. ModuleLog(o->i, BLOG_ERROR, "wrong type");
  203. goto fail0;
  204. }
  205. o->succeeded = ipaddr_parse_ipv4_ifaddr(NCDVal_StringMemRef(str_arg), &o->ifaddr);
  206. NCDModuleInst_Backend_Up(i);
  207. return;
  208. fail0:
  209. NCDModuleInst_Backend_DeadError(i);
  210. }
  211. static int ipv4_cidr_addr_func_getvar2 (void *vo, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
  212. {
  213. struct ipv4_cidr_instance *o = vo;
  214. if (name == NCD_STRING_SUCCEEDED) {
  215. *out = ncd_make_boolean(mem, o->succeeded, o->i->params->iparams->string_index);
  216. return 1;
  217. }
  218. if (!o->succeeded) {
  219. return 0;
  220. }
  221. char str[IPADDR_PRINT_MAX];
  222. if (name == NCD_STRING_EMPTY) {
  223. ipaddr_print_ifaddr(o->ifaddr, str);
  224. }
  225. else if (name == ModuleString(o->i, STRING_ADDR)) {
  226. ipaddr_print_addr(o->ifaddr.addr, str);
  227. }
  228. else if (name == ModuleString(o->i, STRING_PREFIX)) {
  229. sprintf(str, "%d", o->ifaddr.prefix);
  230. }
  231. else {
  232. return 0;
  233. }
  234. *out = NCDVal_NewString(mem, str);
  235. return 1;
  236. }
  237. static void ipv6_cidr_addr_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
  238. {
  239. struct ipv6_cidr_instance *o = vo;
  240. o->i = i;
  241. NCDValRef str_arg;
  242. if (!NCDVal_ListRead(params->args, 1, &str_arg)) {
  243. ModuleLog(i, BLOG_ERROR, "wrong arity");
  244. goto fail0;
  245. }
  246. if (!NCDVal_IsString(str_arg)) {
  247. ModuleLog(o->i, BLOG_ERROR, "wrong type");
  248. goto fail0;
  249. }
  250. o->succeeded = ipaddr6_parse_ipv6_ifaddr(NCDVal_StringMemRef(str_arg), &o->ifaddr);
  251. NCDModuleInst_Backend_Up(i);
  252. return;
  253. fail0:
  254. NCDModuleInst_Backend_DeadError(i);
  255. }
  256. static int ipv6_cidr_addr_func_getvar2 (void *vo, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
  257. {
  258. struct ipv6_cidr_instance *o = vo;
  259. if (name == NCD_STRING_SUCCEEDED) {
  260. *out = ncd_make_boolean(mem, o->succeeded, o->i->params->iparams->string_index);
  261. return 1;
  262. }
  263. if (!o->succeeded) {
  264. return 0;
  265. }
  266. char str[IPADDR6_PRINT_MAX];
  267. if (name == NCD_STRING_EMPTY) {
  268. ipaddr6_print_ifaddr(o->ifaddr, str);
  269. }
  270. else if (name == ModuleString(o->i, STRING_ADDR)) {
  271. ipaddr6_print_addr(o->ifaddr.addr, str);
  272. }
  273. else if (name == ModuleString(o->i, STRING_PREFIX)) {
  274. sprintf(str, "%d", o->ifaddr.prefix);
  275. }
  276. else {
  277. return 0;
  278. }
  279. *out = NCDVal_NewString(mem, str);
  280. return 1;
  281. }
  282. static struct NCDModule modules[] = {
  283. {
  284. .type = "parse_number",
  285. .func_new2 = func_new_parse_number,
  286. .func_die = func_die,
  287. .func_getvar2 = func_getvar2,
  288. .alloc_size = sizeof(struct instance)
  289. }, {
  290. .type = "parse_value",
  291. .func_new2 = func_new_parse_value,
  292. .func_die = func_die,
  293. .func_getvar2 = func_getvar2,
  294. .alloc_size = sizeof(struct instance)
  295. }, {
  296. .type = "parse_ipv4_addr",
  297. .func_new2 = func_new_parse_ipv4_addr,
  298. .func_die = func_die,
  299. .func_getvar2 = func_getvar2,
  300. .alloc_size = sizeof(struct instance)
  301. }, {
  302. .type = "parse_ipv6_addr",
  303. .func_new2 = func_new_parse_ipv6_addr,
  304. .func_die = func_die,
  305. .func_getvar2 = func_getvar2,
  306. .alloc_size = sizeof(struct instance)
  307. }, {
  308. .type = "parse_ipv4_cidr_addr",
  309. .func_new2 = ipv4_cidr_addr_func_new,
  310. .func_getvar2 = ipv4_cidr_addr_func_getvar2,
  311. .alloc_size = sizeof(struct ipv4_cidr_instance)
  312. }, {
  313. .type = "parse_ipv6_cidr_addr",
  314. .func_new2 = ipv6_cidr_addr_func_new,
  315. .func_getvar2 = ipv6_cidr_addr_func_getvar2,
  316. .alloc_size = sizeof(struct ipv6_cidr_instance)
  317. }, {
  318. .type = NULL
  319. }
  320. };
  321. const struct NCDModuleGroup ncdmodule_parse = {
  322. .modules = modules,
  323. .strings = strings
  324. };