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 "libvalidate.h"
44 struct dt_fun *function;
53 struct dt_op stack[32];
59 bool (*call)(struct dt_state *s, int nargs);
63 dt_test_number(double number, const char *value)
68 n = strtod(value, &e);
70 return (e > value && *e == 0 && n == number);
74 dt_test_string(const char *s, const char *end, const char *value)
83 if (!esc && *s == '\\')
102 return (*s == *value || (s >= end && *value == 0));
106 dt_step(struct dt_state *s);
109 dt_call(struct dt_state *s);
112 dt_type_or(struct dt_state *s, int nargs)
122 dt_type_and(struct dt_state *s, int nargs)
132 dt_type_not(struct dt_state *s, int nargs)
141 dt_type_neg(struct dt_state *s, int nargs)
144 const char *value = s->value;
149 if (*s->value == '!')
150 while (isspace(*++s->value));
159 dt_type_list(struct dt_state *s, int nargs)
163 char *p, *str = strdup(s->value);
164 const char *value = s->value;
169 for (p = strtok(str, " \t"); p; p = strtok(NULL, " \t"))
189 dt_type_min(struct dt_state *s, int nargs)
194 if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
196 n = strtol(s->value, &e, 0);
198 return (e > s->value && *e == 0 &&
199 n >= s->stack[s->pos].value.number);
206 dt_type_max(struct dt_state *s, int nargs)
211 if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
213 n = strtol(s->value, &e, 0);
215 return (e > s->value && *e == 0 &&
216 n <= s->stack[s->pos].value.number);
223 dt_type_range(struct dt_state *s, int nargs)
229 s->stack[s->pos].type == OP_NUMBER &&
230 s->stack[s->pos + 1].type == OP_NUMBER)
232 n = strtol(s->value, &e, 0);
234 return (e > s->value && *e == 0 &&
235 n >= s->stack[s->pos].value.number &&
236 n <= s->stack[s->pos + 1].value.number);
243 dt_type_minlen(struct dt_state *s, int nargs)
245 if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
246 return (strlen(s->value) >= s->stack[s->pos].value.number);
252 dt_type_maxlen(struct dt_state *s, int nargs)
254 if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
255 return (strlen(s->value) <= s->stack[s->pos].value.number);
261 dt_type_rangelen(struct dt_state *s, int nargs)
264 s->stack[s->pos].type == OP_NUMBER &&
265 s->stack[s->pos + 1].type == OP_NUMBER)
266 return (strlen(s->value) >= s->stack[s->pos].value.number &&
267 strlen(s->value) <= s->stack[s->pos + 1].value.number);
273 dt_type_int(struct dt_state *s, int nargs)
277 strtol(s->value, &e, 0);
279 return (e > s->value && *e == 0);
283 dt_type_uint(struct dt_state *s, int nargs)
288 n = strtol(s->value, &e, 0);
290 return (e > s->value && *e == 0 && n >= 0);
294 dt_type_float(struct dt_state *s, int nargs)
298 strtod(s->value, &e);
300 return (e > s->value && *e == 0);
304 dt_type_ufloat(struct dt_state *s, int nargs)
309 n = strtod(s->value, &e);
311 return (e > s->value && *e == 0 && n >= 0.0);
315 dt_type_bool(struct dt_state *s, int nargs)
318 const char *values[] = {
319 "0", "off", "false", "no",
320 "1", "on", "true", "yes"
323 for (i = 0; i < sizeof(values) / sizeof(values[0]); i++)
324 if (!strcasecmp(values[i], s->value))
331 dt_type_string(struct dt_state *s, int nargs)
337 dt_type_ip4addr(struct dt_state *s, int nargs)
340 return inet_pton(AF_INET, s->value, &a);
344 dt_type_ip6addr(struct dt_state *s, int nargs)
347 return inet_pton(AF_INET6, s->value, &a);
351 dt_type_ipaddr(struct dt_state *s, int nargs)
353 return (dt_type_ip4addr(s, 0) || dt_type_ip6addr(s, 0));
357 dt_type_netmask4(struct dt_state *s, int nargs)
362 if (!inet_pton(AF_INET, s->value, &a))
368 a.s_addr = ntohl(a.s_addr);
370 for (i = 0; (i < 32) && !(a.s_addr & (1 << i)); i++);
372 return ((uint32_t)(~((1 << i) - 1)) == a.s_addr);
376 dt_type_netmask6(struct dt_state *s, int nargs)
381 if (!inet_pton(AF_INET6, s->value, &a))
384 for (i = 0; (i < 16) && (a.s6_addr[i] == 0xFF); i++);
389 if ((a.s6_addr[i] != 255) && (a.s6_addr[i] != 254) &&
390 (a.s6_addr[i] != 252) && (a.s6_addr[i] != 248) &&
391 (a.s6_addr[i] != 240) && (a.s6_addr[i] != 224) &&
392 (a.s6_addr[i] != 192) && (a.s6_addr[i] != 128) &&
396 for (; (i < 16) && (a.s6_addr[i] == 0); i++);
402 dt_type_cidr4(struct dt_state *s, int nargs)
406 char *p, buf[sizeof("255.255.255.255/32\0")];
408 if (strlen(s->value) >= sizeof(buf))
411 strcpy(buf, s->value);
412 p = strchr(buf, '/');
418 n = strtoul(p, &p, 10);
420 if ((*p != 0) || (n > 32))
424 return inet_pton(AF_INET, buf, &a);
428 dt_type_cidr6(struct dt_state *s, int nargs)
432 char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128\0")];
434 if (strlen(s->value) >= sizeof(buf))
437 strcpy(buf, s->value);
438 p = strchr(buf, '/');
444 n = strtoul(p, &p, 10);
446 if ((*p != 0) || (n > 128))
450 return inet_pton(AF_INET6, buf, &a);
454 dt_type_cidr(struct dt_state *s, int nargs)
456 return (dt_type_cidr4(s, 0) || dt_type_cidr6(s, 0));
460 dt_type_ipmask4(struct dt_state *s, int nargs)
465 char *p, buf[sizeof("255.255.255.255/255.255.255.255\0")];
467 if (strlen(s->value) >= sizeof(buf))
470 strcpy(buf, s->value);
471 p = strchr(buf, '/');
479 rv = dt_type_netmask4(s, 0);
486 return inet_pton(AF_INET, buf, &a);
490 dt_type_ipmask6(struct dt_state *s, int nargs)
495 char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/"
496 "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255\0")];
498 if (strlen(s->value) >= sizeof(buf))
501 strcpy(buf, s->value);
502 p = strchr(buf, '/');
510 rv = dt_type_netmask6(s, 0);
517 return inet_pton(AF_INET6, buf, &a);
521 dt_type_ipmask(struct dt_state *s, int nargs)
523 return (dt_type_ipmask4(s, 0) || dt_type_ipmask6(s, 0));
527 dt_type_port(struct dt_state *s, int nargs)
532 n = strtoul(s->value, &e, 10);
534 return (e > s->value && *e == 0 && n <= 65535);
538 dt_type_portrange(struct dt_state *s, int nargs)
543 n = strtoul(s->value, &e, 10);
545 if (e == s->value || *e != '-')
548 m = strtoul(e + 1, &e, 10);
550 return (*e == 0 && n <= 65535 && m <= 65535 && n <= m);
554 dt_type_macaddr(struct dt_state *s, int nargs)
556 return !!ether_aton(s->value);
560 dt_type_uciname(struct dt_state *s, int nargs)
565 *p && ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
566 (*p >= '0' && *p <= '9') || (*p == '_'));
573 dt_type_wpakey(struct dt_state *s, int nargs)
575 int len = strlen(s->value);
576 const char *p = s->value;
586 return (len >= 8 && len <= 63);
590 dt_type_wepkey(struct dt_state *s, int nargs)
592 int len = strlen(s->value);
593 const char *p = s->value;
595 if (!strncmp(p, "s:", 2))
601 if (len == 10 || len == 26)
609 return (len == 5 || len == 13);
613 dt_type_hostname(struct dt_state *s, int nargs)
615 const char *p, *last;
617 for (p = last = s->value; *p; p++)
621 if ((p - last) == 0 || (p - last) > 63)
627 else if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
628 (*p >= '0' && *p <= '9') || (*p == '_') || (*p == '-'))
636 return ((p - last) > 0 && (p - last) <= 255);
640 dt_type_host(struct dt_state *s, int nargs)
642 return (dt_type_hostname(s, 0) || dt_type_ipaddr(s, 0));
646 dt_type_network(struct dt_state *s, int nargs)
648 return (dt_type_uciname(s, 0) || dt_type_host(s, 0));
652 dt_type_phonedigit(struct dt_state *s, int nargs)
657 *p && ((*p >= '0' && *p <= '9') || (*p == '*') || (*p == '#') ||
658 (*p == '!') || (*p == '.'));
665 dt_type_directory(struct dt_state *s, int nargs)
668 return (!stat(s->value, &st) && S_ISDIR(st.st_mode));
673 dt_type_device(struct dt_state *s, int nargs)
676 return (!stat(s->value, &st) &&
677 (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)));
681 dt_type_file(struct dt_state *s, int nargs)
684 return (!stat(s->value, &st) && S_ISREG(st.st_mode));
688 static struct dt_fun dt_types[] = {
689 { "or", DT_INVALID, dt_type_or },
690 { "and", DT_INVALID, dt_type_and },
691 { "not", DT_INVALID, dt_type_not },
692 { "neg", DT_INVALID, dt_type_neg },
693 { "list", DT_INVALID, dt_type_list },
694 { "min", DT_NUMBER, dt_type_min },
695 { "max", DT_NUMBER, dt_type_max },
696 { "range", DT_NUMBER, dt_type_range },
697 { "minlength", DT_STRING, dt_type_minlen },
698 { "maxlength", DT_STRING, dt_type_maxlen },
699 { "rangelength", DT_STRING, dt_type_rangelen },
700 { "integer", DT_NUMBER, dt_type_int },
701 { "uinteger", DT_NUMBER, dt_type_uint },
702 { "float", DT_NUMBER, dt_type_float },
703 { "ufloat", DT_NUMBER, dt_type_ufloat },
704 { "bool", DT_BOOL, dt_type_bool },
705 { "string", DT_STRING, dt_type_string },
706 { "ip4addr", DT_STRING, dt_type_ip4addr },
707 { "ip6addr", DT_STRING, dt_type_ip6addr },
708 { "ipaddr", DT_STRING, dt_type_ipaddr },
709 { "cidr4", DT_STRING, dt_type_cidr4 },
710 { "cidr6", DT_STRING, dt_type_cidr6 },
711 { "cidr", DT_STRING, dt_type_cidr },
712 { "netmask4", DT_STRING, dt_type_netmask4 },
713 { "netmask6", DT_STRING, dt_type_netmask6 },
714 { "ipmask4", DT_STRING, dt_type_ipmask4 },
715 { "ipmask6", DT_STRING, dt_type_ipmask6 },
716 { "ipmask", DT_STRING, dt_type_ipmask },
717 { "port", DT_NUMBER, dt_type_port },
718 { "portrange", DT_STRING, dt_type_portrange },
719 { "macaddr", DT_STRING, dt_type_macaddr },
720 { "uciname", DT_STRING, dt_type_uciname },
721 { "wpakey", DT_STRING, dt_type_wpakey },
722 { "wepkey", DT_STRING, dt_type_wepkey },
723 { "hostname", DT_STRING, dt_type_hostname },
724 { "host", DT_STRING, dt_type_host },
725 { "network", DT_STRING, dt_type_network },
726 { "phonedigit", DT_STRING, dt_type_phonedigit },
727 { "directory", DT_STRING, dt_type_directory },
728 { "device", DT_STRING, dt_type_device },
729 { "file", DT_STRING, dt_type_file },
734 static struct dt_fun *
735 dt_lookup_function(const char *s, const char *e)
737 struct dt_fun *fun = dt_types;
741 if (!strncmp(fun->name, s, e - s) && *(fun->name + (e - s)) == '\0')
751 dt_parse_atom(struct dt_state *s, const char *label, const char *end)
758 struct dt_op *op = &s->stack[s->depth];
760 if ((s->depth + 1) >= (sizeof(s->stack) / sizeof(s->stack[0])))
762 printf("Syntax error, expression too long\n");
766 while (isspace(*label))
769 /* test whether label is a float */
770 dval = strtod(label, &e);
775 op->type = OP_NUMBER;
776 op->value.number = dval;
777 op->nextop = ++s->depth;
781 else if ((*label == '"') || (*label == '\''))
783 for (p = label + 1, q = *label, esc = false; p <= end; p++)
798 op->type = OP_STRING;
799 op->length = (p - label) - 1;
800 op->value.string = label + 1;
801 op->nextop = ++s->depth;
807 printf("Syntax error, unterminated string\n");
813 p <= end && ((*p >= 'A' && *p <= 'Z') ||
814 (*p >= 'a' && *p <= 'z') ||
815 (*p >= '0' && *p <= '9') ||
819 func = dt_lookup_function(label, p);
823 printf("Syntax error, unrecognized function\n");
828 op->type = OP_FUNCTION;
829 op->value.function = func;
830 op->nextop = ++s->depth;
835 printf("Syntax error, unexpected EOF\n");
840 dt_parse_list(struct dt_state *s, const char *code, const char *end);
843 dt_parse_expr(const char *code, const char *end, struct dt_state *s)
847 if (!dt_parse_atom(s, code, end))
850 tok = &s->stack[s->depth - 1];
852 while (isspace(*tok->next))
855 if (tok->type == OP_FUNCTION)
857 if (*tok->next == '(')
861 while (isspace(*end) && end > tok->next + 1)
864 return dt_parse_list(s, tok->next + 1, end);
866 else if (tok->next == end)
868 return dt_parse_list(s, tok->next, tok->next);
871 printf("Syntax error, expected '(' or EOF after function label\n");
874 else if (tok->next == end)
879 printf("Syntax error, expected ',' after literal\n");
884 dt_parse_list(struct dt_state *s, const char *code, const char *end)
889 const char *p, *last;
895 fptr = &s->stack[s->depth - 1];
897 for (nest = 0, p = last = code, esc = false, c = *p;
899 p++, c = (p < end) ? *p : '\0')
927 if (!dt_parse_expr(last, p, s))
940 fptr->nextop = s->depth;
945 dt_step(struct dt_state *s)
948 struct dt_op *op = &s->stack[s->pos];
953 rv = dt_test_number(op->value.number, s->value);
955 s->valtype = DT_NUMBER;
959 rv = dt_test_string(op->value.string, op->value.string + op->length, s->value);
961 s->valtype = DT_STRING;
978 dt_call(struct dt_state *s)
981 struct dt_op *fptr = &s->stack[s->pos];
982 struct dt_fun *func = fptr->value.function;
986 rv = func->call(s, fptr->length);
988 if (rv && func->valtype)
989 s->valtype = func->valtype;
991 s->pos = fptr->nextop;
997 dt_parse(const char *code, const char *value)
999 struct dt_state s = {
1003 .type = OP_FUNCTION,
1004 .value.function = &dt_types[0],
1010 if (!value || !*value)
1013 if (!dt_parse_list(&s, code, code + strlen(code)))