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"
45 struct dt_fun
*function
;
53 struct dt_op stack
[32];
58 bool (*call
)(struct dt_state
*s
, int nargs
);
62 dt_test_number(double number
, const char *value
)
67 n
= strtod(value
, &e
);
69 return (e
> value
&& *e
== 0 && n
== number
);
73 dt_test_string(const char *s
, const char *end
, const char *value
)
82 if (!esc
&& *s
== '\\')
101 return (*s
== *value
|| (s
> end
&& *value
== 0));
105 dt_step(struct dt_state
*s
);
108 dt_call(struct dt_state
*s
);
111 dt_type_or(struct dt_state
*s
, int nargs
)
121 dt_type_and(struct dt_state
*s
, int nargs
)
131 dt_type_not(struct dt_state
*s
, int nargs
)
140 dt_type_neg(struct dt_state
*s
, int nargs
)
143 const char *value
= s
->value
;
148 if (*s
->value
== '!')
149 while (isspace(*++s
->value
));
158 dt_type_list(struct dt_state
*s
, int nargs
)
162 char *p
, *str
= strdup(s
->value
);
163 const char *value
= s
->value
;
168 for (p
= strtok(str
, " \t"); p
; p
= strtok(NULL
, " \t"))
188 dt_type_min(struct dt_state
*s
, int nargs
)
193 if (nargs
>= 1 && s
->stack
[s
->pos
].type
== OP_NUMBER
)
195 n
= strtol(s
->value
, &e
, 0);
197 return (e
> s
->value
&& *e
== 0 &&
198 n
>= s
->stack
[s
->pos
].value
.number
);
205 dt_type_max(struct dt_state
*s
, int nargs
)
210 if (nargs
>= 1 && s
->stack
[s
->pos
].type
== OP_NUMBER
)
212 n
= strtol(s
->value
, &e
, 0);
214 return (e
> s
->value
&& *e
== 0 &&
215 n
<= s
->stack
[s
->pos
].value
.number
);
222 dt_type_range(struct dt_state
*s
, int nargs
)
228 s
->stack
[s
->pos
].type
== OP_NUMBER
&&
229 s
->stack
[s
->pos
+ 1].type
== OP_NUMBER
)
231 n
= strtol(s
->value
, &e
, 0);
233 return (e
> s
->value
&& *e
== 0 &&
234 n
>= s
->stack
[s
->pos
].value
.number
&&
235 n
<= s
->stack
[s
->pos
+ 1].value
.number
);
242 dt_type_minlen(struct dt_state
*s
, int nargs
)
244 if (nargs
>= 1 && s
->stack
[s
->pos
].type
== OP_NUMBER
)
245 return (strlen(s
->value
) >= s
->stack
[s
->pos
].value
.number
);
251 dt_type_maxlen(struct dt_state
*s
, int nargs
)
253 if (nargs
>= 1 && s
->stack
[s
->pos
].type
== OP_NUMBER
)
254 return (strlen(s
->value
) <= s
->stack
[s
->pos
].value
.number
);
260 dt_type_rangelen(struct dt_state
*s
, int nargs
)
263 s
->stack
[s
->pos
].type
== OP_NUMBER
&&
264 s
->stack
[s
->pos
+ 1].type
== OP_NUMBER
)
265 return (strlen(s
->value
) >= s
->stack
[s
->pos
].value
.number
&&
266 strlen(s
->value
) <= s
->stack
[s
->pos
+ 1].value
.number
);
272 dt_type_int(struct dt_state
*s
, int nargs
)
276 strtol(s
->value
, &e
, 0);
278 return (e
> s
->value
&& *e
== 0);
282 dt_type_uint(struct dt_state
*s
, int nargs
)
287 n
= strtol(s
->value
, &e
, 0);
289 return (e
> s
->value
&& *e
== 0 && n
>= 0);
293 dt_type_float(struct dt_state
*s
, int nargs
)
297 strtod(s
->value
, &e
);
299 return (e
> s
->value
&& *e
== 0);
303 dt_type_ufloat(struct dt_state
*s
, int nargs
)
308 n
= strtod(s
->value
, &e
);
310 return (e
> s
->value
&& *e
== 0 && n
>= 0.0);
314 dt_type_bool(struct dt_state
*s
, int nargs
)
317 const char *values
[] = {
318 "0", "off", "false", "no",
319 "1", "on", "true", "yes"
322 for (i
= 0; i
< sizeof(values
) / sizeof(values
[0]); i
++)
323 if (!strcasecmp(values
[i
], s
->value
))
330 dt_type_string(struct dt_state
*s
, int nargs
)
336 dt_type_ip4addr(struct dt_state
*s
, int nargs
)
339 return inet_pton(AF_INET
, s
->value
, &a
);
343 dt_type_ip6addr(struct dt_state
*s
, int nargs
)
346 return inet_pton(AF_INET6
, s
->value
, &a
);
350 dt_type_ipaddr(struct dt_state
*s
, int nargs
)
352 return (dt_type_ip4addr(s
, 0) || dt_type_ip6addr(s
, 0));
356 dt_type_netmask4(struct dt_state
*s
, int nargs
)
361 if (!inet_pton(AF_INET
, s
->value
, &a
))
367 a
.s_addr
= ntohl(a
.s_addr
);
369 for (i
= 0; (i
< 32) && !(a
.s_addr
& (1 << i
)); i
++);
371 return ((uint32_t)(~((1 << i
) - 1)) == a
.s_addr
);
375 dt_type_netmask6(struct dt_state
*s
, int nargs
)
380 if (!inet_pton(AF_INET6
, s
->value
, &a
))
383 for (i
= 0; (i
< 16) && (a
.s6_addr
[i
] == 0xFF); i
++);
388 if ((a
.s6_addr
[i
] != 255) && (a
.s6_addr
[i
] != 254) &&
389 (a
.s6_addr
[i
] != 252) && (a
.s6_addr
[i
] != 248) &&
390 (a
.s6_addr
[i
] != 240) && (a
.s6_addr
[i
] != 224) &&
391 (a
.s6_addr
[i
] != 192) && (a
.s6_addr
[i
] != 128) &&
395 for (; (i
< 16) && (a
.s6_addr
[i
] == 0); i
++);
401 dt_type_cidr4(struct dt_state
*s
, int nargs
)
405 char *p
, buf
[sizeof("255.255.255.255/32\0")];
407 if (strlen(s
->value
) >= sizeof(buf
))
410 strcpy(buf
, s
->value
);
411 p
= strchr(buf
, '/');
417 n
= strtoul(p
, &p
, 10);
419 if ((*p
!= 0) || (n
> 32))
423 return inet_pton(AF_INET
, buf
, &a
);
427 dt_type_cidr6(struct dt_state
*s
, int nargs
)
431 char *p
, buf
[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128\0")];
433 if (strlen(s
->value
) >= sizeof(buf
))
436 strcpy(buf
, s
->value
);
437 p
= strchr(buf
, '/');
443 n
= strtoul(p
, &p
, 10);
445 if ((*p
!= 0) || (n
> 128))
449 return inet_pton(AF_INET6
, buf
, &a
);
453 dt_type_cidr(struct dt_state
*s
, int nargs
)
455 return (dt_type_cidr4(s
, 0) || dt_type_cidr6(s
, 0));
459 dt_type_ipmask4(struct dt_state
*s
, int nargs
)
464 char *p
, buf
[sizeof("255.255.255.255/255.255.255.255\0")];
466 if (strlen(s
->value
) >= sizeof(buf
))
469 strcpy(buf
, s
->value
);
470 p
= strchr(buf
, '/');
478 rv
= dt_type_netmask4(s
, 0);
485 return inet_pton(AF_INET
, buf
, &a
);
489 dt_type_ipmask6(struct dt_state
*s
, int nargs
)
494 char *p
, buf
[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/"
495 "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255\0")];
497 if (strlen(s
->value
) >= sizeof(buf
))
500 strcpy(buf
, s
->value
);
501 p
= strchr(buf
, '/');
509 rv
= dt_type_netmask6(s
, 0);
516 return inet_pton(AF_INET6
, buf
, &a
);
520 dt_type_ipmask(struct dt_state
*s
, int nargs
)
522 return (dt_type_ipmask4(s
, 0) || dt_type_ipmask6(s
, 0));
526 dt_type_port(struct dt_state
*s
, int nargs
)
531 n
= strtoul(s
->value
, &e
, 10);
533 return (e
> s
->value
&& *e
== 0 && n
<= 65535);
537 dt_type_portrange(struct dt_state
*s
, int nargs
)
542 n
= strtoul(s
->value
, &e
, 10);
544 if (e
== s
->value
|| *e
!= '-')
547 m
= strtoul(e
+ 1, &e
, 10);
549 return (*e
== 0 && n
<= 65535 && m
<= 65535 && n
<= m
);
553 dt_type_macaddr(struct dt_state
*s
, int nargs
)
555 return !!ether_aton(s
->value
);
559 dt_type_uciname(struct dt_state
*s
, int nargs
)
564 *p
&& ((*p
>= 'A' && *p
<= 'Z') || (*p
>= 'a' && *p
<= 'z') ||
565 (*p
>= '0' && *p
<= '9') || (*p
== '_'));
572 dt_type_wpakey(struct dt_state
*s
, int nargs
)
574 int len
= strlen(s
->value
);
575 const char *p
= s
->value
;
585 return (len
>= 8 && len
<= 63);
589 dt_type_wepkey(struct dt_state
*s
, int nargs
)
591 int len
= strlen(s
->value
);
592 const char *p
= s
->value
;
594 if (!strncmp(p
, "s:", 2))
600 if (len
== 10 || len
== 26)
608 return (len
== 5 || len
== 13);
612 dt_type_hostname(struct dt_state
*s
, int nargs
)
614 const char *p
, *last
;
616 for (p
= last
= s
->value
; *p
; p
++)
620 if ((p
- last
) == 0 || (p
- last
) > 63)
626 else if ((*p
>= 'A' && *p
<= 'Z') || (*p
>= 'a' && *p
<= 'z') ||
627 (*p
>= '0' && *p
<= '9') || (*p
== '_') || (*p
== '-'))
635 return ((p
- last
) > 0 && (p
- last
) <= 255);
639 dt_type_host(struct dt_state
*s
, int nargs
)
641 return (dt_type_hostname(s
, 0) || dt_type_ipaddr(s
, 0));
645 dt_type_network(struct dt_state
*s
, int nargs
)
647 return (dt_type_uciname(s
, 0) || dt_type_host(s
, 0));
651 dt_type_phonedigit(struct dt_state
*s
, int nargs
)
656 *p
&& ((*p
>= '0' && *p
<= '9') || (*p
== '*') || (*p
== '#') ||
657 (*p
== '!') || (*p
== '.'));
664 dt_type_directory(struct dt_state
*s
, int nargs
)
667 return (!stat(s
->value
, &st
) && S_ISDIR(st
.st_mode
));
672 dt_type_device(struct dt_state
*s
, int nargs
)
675 return (!stat(s
->value
, &st
) &&
676 (S_ISBLK(st
.st_mode
) || S_ISCHR(st
.st_mode
)));
680 dt_type_file(struct dt_state
*s
, int nargs
)
683 return (!stat(s
->value
, &st
) && S_ISREG(st
.st_mode
));
687 static struct dt_fun dt_types
[] = {
688 { "or", dt_type_or
},
689 { "and", dt_type_and
},
690 { "not", dt_type_not
},
691 { "neg", dt_type_neg
},
692 { "list", dt_type_list
},
693 { "min", dt_type_min
},
694 { "max", dt_type_max
},
695 { "range", dt_type_range
},
696 { "minlength", dt_type_minlen
},
697 { "maxlength", dt_type_maxlen
},
698 { "rangelength", dt_type_rangelen
},
699 { "integer", dt_type_int
},
700 { "uinteger", dt_type_uint
},
701 { "float", dt_type_float
},
702 { "ufloat", dt_type_ufloat
},
703 { "bool", dt_type_bool
},
704 { "string", dt_type_string
},
705 { "ip4addr", dt_type_ip4addr
},
706 { "ip6addr", dt_type_ip6addr
},
707 { "ipaddr", dt_type_ipaddr
},
708 { "cidr4", dt_type_cidr4
},
709 { "cidr6", dt_type_cidr6
},
710 { "cidr", dt_type_cidr
},
711 { "netmask4", dt_type_netmask4
},
712 { "netmask6", dt_type_netmask6
},
713 { "ipmask4", dt_type_ipmask4
},
714 { "ipmask6", dt_type_ipmask6
},
715 { "ipmask", dt_type_ipmask
},
716 { "port", dt_type_port
},
717 { "portrange", dt_type_portrange
},
718 { "macaddr", dt_type_macaddr
},
719 { "uciname", dt_type_uciname
},
720 { "wpakey", dt_type_wpakey
},
721 { "wepkey", dt_type_wepkey
},
722 { "hostname", dt_type_hostname
},
723 { "host", dt_type_host
},
724 { "network", dt_type_network
},
725 { "phonedigit", dt_type_phonedigit
},
726 { "directory", dt_type_directory
},
727 { "device", dt_type_device
},
728 { "file", dt_type_file
},
733 static struct dt_fun
*
734 dt_lookup_function(const char *s
, const char *e
)
736 struct dt_fun
*fun
= dt_types
;
740 if (!strncmp(fun
->name
, s
, e
- s
) && *(fun
->name
+ (e
- s
)) == '\0')
750 dt_parse_atom(struct dt_state
*s
, const char *label
, const char *end
)
757 struct dt_op
*op
= &s
->stack
[s
->depth
];
759 if ((s
->depth
+ 1) >= (sizeof(s
->stack
) / sizeof(s
->stack
[0])))
761 printf("Syntax error, expression too long\n");
765 while (isspace(*label
))
768 /* test whether label is a float */
769 dval
= strtod(label
, &e
);
774 op
->type
= OP_NUMBER
;
775 op
->value
.number
= dval
;
776 op
->nextop
= ++s
->depth
;
780 else if ((*label
== '"') || (*label
== '\''))
782 for (p
= label
+ 1, q
= *label
, esc
= false; p
<= end
; p
++)
797 op
->type
= OP_STRING
;
798 op
->length
= (p
- label
) - 2;
799 op
->value
.string
= label
+ 1;
800 op
->nextop
= ++s
->depth
;
806 printf("Syntax error, unterminated string\n");
812 p
<= end
&& ((*p
>= 'A' && *p
<= 'Z') ||
813 (*p
>= 'a' && *p
<= 'z') ||
814 (*p
>= '0' && *p
<= '9') ||
818 func
= dt_lookup_function(label
, p
);
822 printf("Syntax error, unrecognized function\n");
827 op
->type
= OP_FUNCTION
;
828 op
->value
.function
= func
;
829 op
->nextop
= ++s
->depth
;
834 printf("Syntax error, unexpected EOF\n");
839 dt_parse_list(struct dt_state
*s
, const char *code
, const char *end
);
842 dt_parse_expr(const char *code
, const char *end
, struct dt_state
*s
)
846 if (!dt_parse_atom(s
, code
, end
))
849 tok
= &s
->stack
[s
->depth
- 1];
851 while (isspace(*tok
->next
))
854 if (tok
->type
== OP_FUNCTION
)
856 if (*tok
->next
== '(')
860 while (isspace(*end
) && end
> tok
->next
+ 1)
863 return dt_parse_list(s
, tok
->next
+ 1, end
);
865 else if (tok
->next
== end
)
867 return dt_parse_list(s
, tok
->next
, tok
->next
);
870 printf("Syntax error, expected '(' or EOF after function label\n");
873 else if (tok
->next
== end
)
878 printf("Syntax error, expected ',' after literal\n");
883 dt_parse_list(struct dt_state
*s
, const char *code
, const char *end
)
888 const char *p
, *last
;
894 fptr
= &s
->stack
[s
->depth
- 1];
896 for (nest
= 0, p
= last
= code
, esc
= false, c
= *p
;
898 p
++, c
= (p
< end
) ? *p
: '\0')
926 if (!dt_parse_expr(last
, p
, s
))
939 fptr
->nextop
= s
->depth
;
944 dt_step(struct dt_state
*s
)
947 struct dt_op
*op
= &s
->stack
[s
->pos
];
952 rv
= op
->value
.boolean
;
956 rv
= dt_test_number(op
->value
.number
, s
->value
);
960 rv
= dt_test_string(op
->value
.string
, op
->value
.string
+ op
->length
, s
->value
);
977 dt_call(struct dt_state
*s
)
980 struct dt_op
*fptr
= &s
->stack
[s
->pos
];
981 struct dt_fun
*func
= fptr
->value
.function
;
985 rv
= func
->call(s
, fptr
->length
);
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
)))