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
) - 2;
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
);
957 rv
= dt_test_string(op
->value
.string
, op
->value
.string
+ op
->length
, s
->value
);
974 dt_call(struct dt_state
*s
)
977 struct dt_op
*fptr
= &s
->stack
[s
->pos
];
978 struct dt_fun
*func
= fptr
->value
.function
;
982 rv
= func
->call(s
, fptr
->length
);
984 if (rv
&& func
->valtype
)
985 s
->valtype
= func
->valtype
;
987 s
->pos
= fptr
->nextop
;
993 dt_parse(const char *code
, const char *value
)
995 struct dt_state s
= {
1000 .value
.function
= &dt_types
[0],
1006 if (!value
|| !*value
)
1009 if (!dt_parse_list(&s
, code
, code
+ strlen(code
)))