f550e760bf5695eaec73dee0b24b8bc51bcdaeea
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
);