2 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
20 #include <arpa/inet.h>
21 #include <netinet/ether.h>
24 #include <sys/types.h>
29 #include "libvalidate.h"
49 struct dt_fun *function;
56 struct uci_context *ctx;
59 struct dt_op stack[32];
65 bool (*call)(struct dt_state *s, int nargs);
69 dt_test_number(double number, const char *value)
74 n = strtod(value, &e);
76 return (e > value && *e == 0 && n == number);
80 dt_test_string(const char *s, const char *end, const char *value)
89 if (!esc && *s == '\\')
108 return (*s == *value || (s >= end && *value == 0));
112 dt_step(struct dt_state *s);
115 dt_call(struct dt_state *s);
117 #define dt_getint(n, v) \
118 ((n < nargs && s->stack[s->pos + n].type == OP_NUMBER) \
119 ? (v = s->stack[s->pos + n].value.number, 1) : 0)
122 dt_type_or(struct dt_state *s, int nargs)
132 dt_type_and(struct dt_state *s, int nargs)
142 dt_type_not(struct dt_state *s, int nargs)
151 dt_type_neg(struct dt_state *s, int nargs)
154 const char *value = s->value;
159 if (*s->value == '!')
160 while (isspace(*++s->value));
169 dt_type_list(struct dt_state *s, int nargs)
173 char *p, *str = strdup(s->value);
174 const char *value = s->value;
179 for (p = strtok(str, " \t"); p; p = strtok(NULL, " \t"))
199 dt_type_min(struct dt_state *s, int nargs)
204 if (dt_getint(0, min))
206 n = strtol(s->value, &e, 0);
207 return (e > s->value && *e == 0 && n >= min);
214 dt_type_max(struct dt_state *s, int nargs)
219 if (dt_getint(0, max))
221 n = strtol(s->value, &e, 0);
222 return (e > s->value && *e == 0 && n <= max);
229 dt_type_range(struct dt_state *s, int nargs)
234 if (dt_getint(0, min) && dt_getint(1, max))
236 n = strtol(s->value, &e, 0);
237 return (e > s->value && *e == 0 && n >= min && n <= max);
244 dt_type_minlen(struct dt_state *s, int nargs)
248 if (dt_getint(0, min))
249 return (strlen(s->value) >= min);
255 dt_type_maxlen(struct dt_state *s, int nargs)
259 if (dt_getint(0, max))
260 return (strlen(s->value) <= max);
266 dt_type_rangelen(struct dt_state *s, int nargs)
269 int len = strlen(s->value);
271 if (dt_getint(0, min) && dt_getint(1, max))
272 return (len >= min && len <= max);
278 dt_type_int(struct dt_state *s, int nargs)
283 if (!isxdigit(*s->value) && *s->value != '-')
287 strtol(s->value, &e, base);
289 return (e > s->value && *e == 0);
293 dt_type_uint(struct dt_state *s, int nargs)
298 if (!isxdigit(*s->value))
302 strtoul(s->value, &e, base);
304 return (e > s->value && *e == 0);
308 dt_type_float(struct dt_state *s, int nargs)
312 strtod(s->value, &e);
314 return (e > s->value && *e == 0);
318 dt_type_ufloat(struct dt_state *s, int nargs)
323 n = strtod(s->value, &e);
325 return (e > s->value && *e == 0 && n >= 0.0);
329 dt_type_bool(struct dt_state *s, int nargs)
332 const char *values[] = {
333 "0", "off", "false", "no",
334 "1", "on", "true", "yes"
337 for (i = 0; i < sizeof(values) / sizeof(values[0]); i++)
338 if (!strcasecmp(values[i], s->value))
345 dt_type_string(struct dt_state *s, int nargs)
348 int len = strlen(s->value);
350 if (dt_getint(0, min) && (len < min))
353 if (dt_getint(1, max) && (len > max))
360 dt_type_hexstring(struct dt_state *s, int nargs)
363 int len = strlen(s->value);
369 if (dt_getint(0, min) && (len < min))
372 if (dt_getint(1, max) && (len > max))
375 for (p = s->value; *p; p++)
383 dt_type_ip4addr(struct dt_state *s, int nargs)
386 return inet_pton(AF_INET, s->value, &a);
390 dt_type_ip6addr(struct dt_state *s, int nargs)
393 return inet_pton(AF_INET6, s->value, &a);
397 dt_type_ipaddr(struct dt_state *s, int nargs)
399 return (dt_type_ip4addr(s, 0) || dt_type_ip6addr(s, 0));
403 dt_type_netmask4(struct dt_state *s, int nargs)
408 if (!inet_pton(AF_INET, s->value, &a))
414 a.s_addr = ntohl(a.s_addr);
416 for (i = 0; (i < 32) && !(a.s_addr & (1 << i)); i++);
418 return ((uint32_t)(~((1 << i) - 1)) == a.s_addr);
422 dt_type_netmask6(struct dt_state *s, int nargs)
427 if (!inet_pton(AF_INET6, s->value, &a))
430 for (i = 0; (i < 16) && (a.s6_addr[i] == 0xFF); i++);
435 if ((a.s6_addr[i] != 255) && (a.s6_addr[i] != 254) &&
436 (a.s6_addr[i] != 252) && (a.s6_addr[i] != 248) &&
437 (a.s6_addr[i] != 240) && (a.s6_addr[i] != 224) &&
438 (a.s6_addr[i] != 192) && (a.s6_addr[i] != 128) &&
442 for (; (i < 16) && (a.s6_addr[i] == 0); i++);
448 dt_type_cidr4(struct dt_state *s, int nargs)
452 char *p, buf[sizeof("255.255.255.255/32\0")];
454 if (strlen(s->value) >= sizeof(buf))
457 strcpy(buf, s->value);
458 p = strchr(buf, '/');
464 n = strtoul(p, &p, 10);
466 if ((*p != 0) || (n > 32))
470 return inet_pton(AF_INET, buf, &a);
474 dt_type_cidr6(struct dt_state *s, int nargs)
478 char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128\0")];
480 if (strlen(s->value) >= sizeof(buf))
483 strcpy(buf, s->value);
484 p = strchr(buf, '/');
490 n = strtoul(p, &p, 10);
492 if ((*p != 0) || (n > 128))
496 return inet_pton(AF_INET6, buf, &a);
500 dt_type_cidr(struct dt_state *s, int nargs)
502 return (dt_type_cidr4(s, 0) || dt_type_cidr6(s, 0));
506 dt_type_ipmask4(struct dt_state *s, int nargs)
511 char *p, buf[sizeof("255.255.255.255/255.255.255.255\0")];
513 if (strlen(s->value) >= sizeof(buf))
516 strcpy(buf, s->value);
517 p = strchr(buf, '/');
525 rv = dt_type_netmask4(s, 0);
532 return inet_pton(AF_INET, buf, &a);
536 dt_type_ipmask6(struct dt_state *s, int nargs)
541 char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/"
542 "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255\0")];
544 if (strlen(s->value) >= sizeof(buf))
547 strcpy(buf, s->value);
548 p = strchr(buf, '/');
556 rv = dt_type_netmask6(s, 0);
563 return inet_pton(AF_INET6, buf, &a);
567 dt_type_ipmask(struct dt_state *s, int nargs)
569 return (dt_type_ipmask4(s, 0) || dt_type_ipmask6(s, 0));
573 dt_type_port(struct dt_state *s, int nargs)
578 n = strtoul(s->value, &e, 10);
580 return (e > s->value && *e == 0 && n <= 65535);
584 dt_type_portrange(struct dt_state *s, int nargs)
589 n = strtoul(s->value, &e, 10);
591 if (e == s->value || *e != '-')
594 m = strtoul(e + 1, &e, 10);
596 return (*e == 0 && n <= 65535 && m <= 65535 && n <= m);
600 dt_type_macaddr(struct dt_state *s, int nargs)
602 return !!ether_aton(s->value);
606 dt_type_uciname(struct dt_state *s, int nargs)
611 *p && ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
612 (*p >= '0' && *p <= '9') || (*p == '_'));
619 dt_type_wpakey(struct dt_state *s, int nargs)
621 int len = strlen(s->value);
622 const char *p = s->value;
632 return (len >= 8 && len <= 63);
636 dt_type_wepkey(struct dt_state *s, int nargs)
638 int len = strlen(s->value);
639 const char *p = s->value;
641 if (!strncmp(p, "s:", 2))
647 if (len == 10 || len == 26)
655 return (len == 5 || len == 13);
659 dt_type_hostname(struct dt_state *s, int nargs)
661 const char *p, *last;
663 for (p = last = s->value; *p; p++)
667 if ((p - last) == 0 || (p - last) > 63)
673 else if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
674 (*p >= '0' && *p <= '9') || (*p == '_') || (*p == '-'))
682 return ((p - last) > 0 && (p - last) <= 255);
686 dt_type_host(struct dt_state *s, int nargs)
688 return (dt_type_hostname(s, 0) || dt_type_ipaddr(s, 0));
692 dt_type_network(struct dt_state *s, int nargs)
694 return (dt_type_uciname(s, 0) || dt_type_host(s, 0));
698 dt_type_phonedigit(struct dt_state *s, int nargs)
703 *p && ((*p >= '0' && *p <= '9') || (*p == '*') || (*p == '#') ||
704 (*p == '!') || (*p == '.'));
711 dt_type_directory(struct dt_state *s, int nargs)
714 return (!stat(s->value, &st) && S_ISDIR(st.st_mode));
719 dt_type_device(struct dt_state *s, int nargs)
722 return (!stat(s->value, &st) &&
723 (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)));
727 dt_type_file(struct dt_state *s, int nargs)
730 return (!stat(s->value, &st) && S_ISREG(st.st_mode));
734 dt_type_regex(struct dt_state *s, int nargs)
741 if (nargs < 1 || s->stack[s->pos].type != OP_STRING)
744 relen = s->stack[s->pos].length;
745 re = alloca(relen + 3);
750 memset(re, 0, relen + 3);
751 memcpy(re + 1, s->stack[s->pos].value.string, relen);
756 if (regcomp(&pattern, re, REG_EXTENDED | REG_NOSUB))
759 rv = !regexec(&pattern, s->value, 0, NULL, 0);
767 dt_uci_lookup(struct dt_state *s, const char *pkg,
768 const char *sct, const char *opt, enum uci_type type)
770 struct uci_ptr ptr = {
776 if (!s->ctx || uci_lookup_ptr(s->ctx, &ptr, NULL, false) ||
777 !(ptr.flags & UCI_LOOKUP_COMPLETE))
780 if (ptr.last->type != type)
785 case UCI_TYPE_PACKAGE:
786 return uci_to_package(ptr.last);
788 case UCI_TYPE_SECTION:
789 return uci_to_section(ptr.last);
791 case UCI_TYPE_OPTION:
792 return uci_to_option(ptr.last);
800 dt_uci_cmp(struct dt_state *s,
801 const char *pkg, const char *sct, const char *opt)
803 struct uci_element *e;
804 struct uci_option *o = dt_uci_lookup(s, pkg, sct, opt, UCI_TYPE_OPTION);
811 case UCI_TYPE_STRING:
812 if (!strcmp(s->value, o->v.string))
817 uci_foreach_element(&o->v.list, e)
818 if (!strcmp(s->value, e->name))
827 dt_type_uci(struct dt_state *s, int nargs)
830 struct uci_element *e;
831 struct uci_package *p;
837 for (i = 0; i < nargs && i < 3; i++)
839 if (s->stack[s->pos + i].type != OP_STRING)
842 len = s->stack[s->pos + i].length;
843 cso[i] = alloca(len + 1);
848 memset(cso[i], 0, len + 1);
849 memcpy(cso[i], s->stack[s->pos + i].value.string, len);
852 if (!cso[0] || !cso[1] || (*cso[1] != '@' && !cso[2]))
856 return dt_uci_cmp(s, cso[0], cso[1], cso[2]);
858 p = dt_uci_lookup(s, cso[0], NULL, NULL, UCI_TYPE_PACKAGE);
863 uci_foreach_element(&p->sections, e)
865 if (strcmp(uci_to_section(e)->type, cso[1] + 1))
870 if (!strcmp(s->value, e->name))
875 if (dt_uci_cmp(s, cso[0], e->name, cso[2]))
884 static struct dt_fun dt_types[] = {
885 { "or", DT_INVALID, dt_type_or },
886 { "and", DT_INVALID, dt_type_and },
887 { "not", DT_INVALID, dt_type_not },
888 { "neg", DT_INVALID, dt_type_neg },
889 { "list", DT_INVALID, dt_type_list },
890 { "min", DT_NUMBER, dt_type_min },
891 { "max", DT_NUMBER, dt_type_max },
892 { "range", DT_NUMBER, dt_type_range },
893 { "minlength", DT_STRING, dt_type_minlen },
894 { "maxlength", DT_STRING, dt_type_maxlen },
895 { "rangelength", DT_STRING, dt_type_rangelen },
896 { "integer", DT_NUMBER, dt_type_int },
897 { "uinteger", DT_NUMBER, dt_type_uint },
898 { "float", DT_NUMBER, dt_type_float },
899 { "ufloat", DT_NUMBER, dt_type_ufloat },
900 { "bool", DT_BOOL, dt_type_bool },
901 { "string", DT_STRING, dt_type_string },
902 { "hexstring", DT_STRING, dt_type_hexstring },
903 { "ip4addr", DT_STRING, dt_type_ip4addr },
904 { "ip6addr", DT_STRING, dt_type_ip6addr },
905 { "ipaddr", DT_STRING, dt_type_ipaddr },
906 { "cidr4", DT_STRING, dt_type_cidr4 },
907 { "cidr6", DT_STRING, dt_type_cidr6 },
908 { "cidr", DT_STRING, dt_type_cidr },
909 { "netmask4", DT_STRING, dt_type_netmask4 },
910 { "netmask6", DT_STRING, dt_type_netmask6 },
911 { "ipmask4", DT_STRING, dt_type_ipmask4 },
912 { "ipmask6", DT_STRING, dt_type_ipmask6 },
913 { "ipmask", DT_STRING, dt_type_ipmask },
914 { "port", DT_NUMBER, dt_type_port },
915 { "portrange", DT_STRING, dt_type_portrange },
916 { "macaddr", DT_STRING, dt_type_macaddr },
917 { "uciname", DT_STRING, dt_type_uciname },
918 { "wpakey", DT_STRING, dt_type_wpakey },
919 { "wepkey", DT_STRING, dt_type_wepkey },
920 { "hostname", DT_STRING, dt_type_hostname },
921 { "host", DT_STRING, dt_type_host },
922 { "network", DT_STRING, dt_type_network },
923 { "phonedigit", DT_STRING, dt_type_phonedigit },
924 { "directory", DT_STRING, dt_type_directory },
925 { "device", DT_STRING, dt_type_device },
926 { "file", DT_STRING, dt_type_file },
927 { "regex", DT_STRING, dt_type_regex },
928 { "uci", DT_STRING, dt_type_uci },
933 static struct dt_fun *
934 dt_lookup_function(const char *s, const char *e)
936 struct dt_fun *fun = dt_types;
940 if (!strncmp(fun->name, s, e - s) && *(fun->name + (e - s)) == '\0')
950 dt_parse_atom(struct dt_state *s, const char *label, const char *end)
957 struct dt_op *op = &s->stack[s->depth];
959 if ((s->depth + 1) >= (sizeof(s->stack) / sizeof(s->stack[0])))
961 printf("Syntax error, expression too long\n");
965 while (isspace(*label))
968 /* test whether label is a float */
969 dval = strtod(label, &e);
974 op->type = OP_NUMBER;
975 op->value.number = dval;
976 op->nextop = ++s->depth;
980 else if ((*label == '"') || (*label == '\''))
982 for (p = label + 1, q = *label, esc = false; p <= end; p++)
997 op->type = OP_STRING;
998 op->length = (p - label) - 1;
999 op->value.string = label + 1;
1000 op->nextop = ++s->depth;
1006 printf("Syntax error, unterminated string\n");
1012 p <= end && ((*p >= 'A' && *p <= 'Z') ||
1013 (*p >= 'a' && *p <= 'z') ||
1014 (*p >= '0' && *p <= '9') ||
1018 func = dt_lookup_function(label, p);
1022 printf("Syntax error, unrecognized function\n");
1027 op->type = OP_FUNCTION;
1028 op->value.function = func;
1029 op->nextop = ++s->depth;
1034 printf("Syntax error, unexpected EOF\n");
1039 dt_parse_list(struct dt_state *s, const char *code, const char *end);
1042 dt_parse_expr(const char *code, const char *end, struct dt_state *s)
1046 if (!dt_parse_atom(s, code, end))
1049 tok = &s->stack[s->depth - 1];
1051 while (isspace(*tok->next))
1054 if (tok->type == OP_FUNCTION)
1056 if (*tok->next == '(')
1060 while (isspace(*end) && end > tok->next + 1)
1063 return dt_parse_list(s, tok->next + 1, end);
1065 else if (tok->next == end)
1067 return dt_parse_list(s, tok->next, tok->next);
1070 printf("Syntax error, expected '(' or EOF after function label\n");
1073 else if (tok->next == end)
1078 printf("Syntax error, expected ',' after literal\n");
1083 dt_parse_list(struct dt_state *s, const char *code, const char *end)
1088 const char *p, *last;
1094 fptr = &s->stack[s->depth - 1];
1096 for (nest = 0, p = last = code, esc = false, c = *p;
1098 p++, c = (p < end) ? *p : '\0')
1126 if (!dt_parse_expr(last, p, s))
1139 fptr->nextop = s->depth;
1144 dt_step(struct dt_state *s)
1147 struct dt_op *op = &s->stack[s->pos];
1152 rv = dt_test_number(op->value.number, s->value);
1154 s->valtype = DT_NUMBER;
1158 rv = dt_test_string(op->value.string, op->value.string + op->length, s->value);
1160 s->valtype = DT_STRING;
1172 s->pos = op->nextop;
1177 dt_call(struct dt_state *s)
1180 struct dt_op *fptr = &s->stack[s->pos];
1181 struct dt_fun *func = fptr->value.function;
1185 rv = func->call(s, fptr->length);
1187 if (rv && func->valtype)
1188 s->valtype = func->valtype;
1190 s->pos = fptr->nextop;
1196 dt_parse(const char *code, const char *value)
1198 enum dt_type rv = DT_INVALID;
1200 struct dt_state s = {
1204 .type = OP_FUNCTION,
1205 .value.function = &dt_types[0],
1211 if (!value || !*value)
1214 if (!dt_parse_list(&s, code, code + strlen(code)))
1217 s.ctx = uci_alloc_context();
1224 uci_free_context(s.ctx);