f94a071e21100147f4de83df74b01474ae928a8c
8 #include <netinet/ether.h>
11 #include "libvalidate.h"
32 struct dt_fun
*function
;
40 struct dt_op stack
[32];
45 bool (*call
)(struct dt_state
*s
, int nargs
);
49 dt_test_number(double number
, const char *value
)
54 n
= strtod(value
, &e
);
56 return (e
> value
&& *e
== 0 && n
== number
);
60 dt_test_string(const char *s
, const char *end
, const char *value
)
69 if (!esc
&& *s
== '\\')
88 return (*s
== *value
|| (s
> end
&& *value
== 0));
92 dt_step(struct dt_state
*s
);
95 dt_call(struct dt_state
*s
);
98 dt_type_or(struct dt_state
*s
, int nargs
)
108 dt_type_and(struct dt_state
*s
, int nargs
)
118 dt_type_not(struct dt_state
*s
, int nargs
)
127 dt_type_neg(struct dt_state
*s
, int nargs
)
130 const char *value
= s
->value
;
135 if (*s
->value
== '!')
136 while (isspace(*++s
->value
));
145 dt_type_list(struct dt_state
*s
, int nargs
)
149 char *p
, *str
= strdup(s
->value
);
150 const char *value
= s
->value
;
155 for (p
= strtok(str
, " \t"); p
; p
= strtok(NULL
, " \t"))
175 dt_type_min(struct dt_state
*s
, int nargs
)
180 if (nargs
>= 1 && s
->stack
[s
->pos
].type
== OP_NUMBER
)
182 n
= strtol(s
->value
, &e
, 0);
184 return (e
> s
->value
&& *e
== 0 &&
185 n
>= s
->stack
[s
->pos
].value
.number
);
192 dt_type_max(struct dt_state
*s
, int nargs
)
197 if (nargs
>= 1 && s
->stack
[s
->pos
].type
== OP_NUMBER
)
199 n
= strtol(s
->value
, &e
, 0);
201 return (e
> s
->value
&& *e
== 0 &&
202 n
<= s
->stack
[s
->pos
].value
.number
);
209 dt_type_range(struct dt_state
*s
, int nargs
)
215 s
->stack
[s
->pos
].type
== OP_NUMBER
&&
216 s
->stack
[s
->pos
+ 1].type
== OP_NUMBER
)
218 n
= strtol(s
->value
, &e
, 0);
220 return (e
> s
->value
&& *e
== 0 &&
221 n
>= s
->stack
[s
->pos
].value
.number
&&
222 n
<= s
->stack
[s
->pos
+ 1].value
.number
);
229 dt_type_minlen(struct dt_state
*s
, int nargs
)
231 if (nargs
>= 1 && s
->stack
[s
->pos
].type
== OP_NUMBER
)
232 return (strlen(s
->value
) >= s
->stack
[s
->pos
].value
.number
);
238 dt_type_maxlen(struct dt_state
*s
, int nargs
)
240 if (nargs
>= 1 && s
->stack
[s
->pos
].type
== OP_NUMBER
)
241 return (strlen(s
->value
) <= s
->stack
[s
->pos
].value
.number
);
247 dt_type_rangelen(struct dt_state
*s
, int nargs
)
250 s
->stack
[s
->pos
].type
== OP_NUMBER
&&
251 s
->stack
[s
->pos
+ 1].type
== OP_NUMBER
)
252 return (strlen(s
->value
) >= s
->stack
[s
->pos
].value
.number
&&
253 strlen(s
->value
) <= s
->stack
[s
->pos
+ 1].value
.number
);
259 dt_type_int(struct dt_state
*s
, int nargs
)
263 strtol(s
->value
, &e
, 0);
265 return (e
> s
->value
&& *e
== 0);
269 dt_type_uint(struct dt_state
*s
, int nargs
)
274 n
= strtol(s
->value
, &e
, 0);
276 return (e
> s
->value
&& *e
== 0 && n
>= 0);
280 dt_type_float(struct dt_state
*s
, int nargs
)
284 strtod(s
->value
, &e
);
286 return (e
> s
->value
&& *e
== 0);
290 dt_type_ufloat(struct dt_state
*s
, int nargs
)
295 n
= strtod(s
->value
, &e
);
297 return (e
> s
->value
&& *e
== 0 && n
>= 0.0);
301 dt_type_bool(struct dt_state
*s
, int nargs
)
304 const char *values
[] = {
305 "0", "off", "false", "no",
306 "1", "on", "true", "yes"
309 for (i
= 0; i
< sizeof(values
) / sizeof(values
[0]); i
++)
310 if (!strcasecmp(values
[i
], s
->value
))
317 dt_type_string(struct dt_state
*s
, int nargs
)
323 dt_type_ip4addr(struct dt_state
*s
, int nargs
)
326 return inet_pton(AF_INET
, s
->value
, &a
);
330 dt_type_ip6addr(struct dt_state
*s
, int nargs
)
333 return inet_pton(AF_INET6
, s
->value
, &a
);
337 dt_type_ipaddr(struct dt_state
*s
, int nargs
)
339 return (dt_type_ip4addr(s
, 0) || dt_type_ip6addr(s
, 0));
343 dt_type_netmask4(struct dt_state
*s
, int nargs
)
348 if (!inet_pton(AF_INET
, s
->value
, &a
))
354 a
.s_addr
= ntohl(a
.s_addr
);
356 for (i
= 0; (i
< 32) && !(a
.s_addr
& (1 << i
)); i
++);
358 return ((uint32_t)(~((1 << i
) - 1)) == a
.s_addr
);
362 dt_type_netmask6(struct dt_state
*s
, int nargs
)
367 if (!inet_pton(AF_INET6
, s
->value
, &a
))
370 for (i
= 0; (i
< 16) && (a
.s6_addr
[i
] == 0xFF); i
++);
375 if ((a
.s6_addr
[i
] != 255) && (a
.s6_addr
[i
] != 254) &&
376 (a
.s6_addr
[i
] != 252) && (a
.s6_addr
[i
] != 248) &&
377 (a
.s6_addr
[i
] != 240) && (a
.s6_addr
[i
] != 224) &&
378 (a
.s6_addr
[i
] != 192) && (a
.s6_addr
[i
] != 128) &&
382 for (; (i
< 16) && (a
.s6_addr
[i
] == 0); i
++);
388 dt_type_cidr4(struct dt_state
*s
, int nargs
)
392 char *p
, buf
[sizeof("255.255.255.255/32\0")];
394 if (strlen(s
->value
) >= sizeof(buf
))
397 strcpy(buf
, s
->value
);
398 p
= strchr(buf
, '/');
404 n
= strtoul(p
, &p
, 10);
406 if ((*p
!= 0) || (n
> 32))
410 return inet_pton(AF_INET
, buf
, &a
);
414 dt_type_cidr6(struct dt_state
*s
, int nargs
)
418 char *p
, buf
[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128\0")];
420 if (strlen(s
->value
) >= sizeof(buf
))
423 strcpy(buf
, s
->value
);
424 p
= strchr(buf
, '/');
430 n
= strtoul(p
, &p
, 10);
432 if ((*p
!= 0) || (n
> 128))
436 return inet_pton(AF_INET6
, buf
, &a
);
440 dt_type_cidr(struct dt_state
*s
, int nargs
)
442 return (dt_type_cidr4(s
, 0) || dt_type_cidr6(s
, 0));
446 dt_type_ipmask4(struct dt_state
*s
, int nargs
)
451 char *p
, buf
[sizeof("255.255.255.255/255.255.255.255\0")];
453 if (strlen(s
->value
) >= sizeof(buf
))
456 strcpy(buf
, s
->value
);
457 p
= strchr(buf
, '/');
465 rv
= dt_type_netmask4(s
, 0);
472 return inet_pton(AF_INET
, buf
, &a
);
476 dt_type_ipmask6(struct dt_state
*s
, int nargs
)
481 char *p
, buf
[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/"
482 "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255\0")];
484 if (strlen(s
->value
) >= sizeof(buf
))
487 strcpy(buf
, s
->value
);
488 p
= strchr(buf
, '/');
496 rv
= dt_type_netmask6(s
, 0);
503 return inet_pton(AF_INET6
, buf
, &a
);
507 dt_type_ipmask(struct dt_state
*s
, int nargs
)
509 return (dt_type_ipmask4(s
, 0) || dt_type_ipmask6(s
, 0));
513 dt_type_port(struct dt_state
*s
, int nargs
)
518 n
= strtoul(s
->value
, &e
, 10);
520 return (e
> s
->value
&& *e
== 0 && n
<= 65535);
524 dt_type_portrange(struct dt_state
*s
, int nargs
)
529 n
= strtoul(s
->value
, &e
, 10);
531 if (e
== s
->value
|| *e
!= '-')
534 m
= strtoul(e
+ 1, &e
, 10);
536 return (*e
== 0 && n
<= 65535 && m
<= 65535 && n
<= m
);
540 dt_type_macaddr(struct dt_state
*s
, int nargs
)
542 return !!ether_aton(s
->value
);
546 dt_type_uciname(struct dt_state
*s
, int nargs
)
551 *p
&& ((*p
>= 'A' && *p
<= 'Z') || (*p
>= 'a' && *p
<= 'z') ||
552 (*p
>= '0' && *p
<= '9') || (*p
== '_'));
559 dt_type_wpakey(struct dt_state
*s
, int nargs
)
561 int len
= strlen(s
->value
);
562 const char *p
= s
->value
;
572 return (len
>= 8 && len
<= 63);
576 dt_type_wepkey(struct dt_state
*s
, int nargs
)
578 int len
= strlen(s
->value
);
579 const char *p
= s
->value
;
581 if (!strncmp(p
, "s:", 2))
587 if (len
== 10 || len
== 26)
595 return (len
== 5 || len
== 13);
599 dt_type_hostname(struct dt_state
*s
, int nargs
)
601 const char *p
, *last
;
603 for (p
= last
= s
->value
; *p
; p
++)
607 if ((p
- last
) == 0 || (p
- last
) > 63)
613 else if ((*p
>= 'A' && *p
<= 'Z') || (*p
>= 'a' && *p
<= 'z') ||
614 (*p
>= '0' && *p
<= '9') || (*p
== '_') || (*p
== '-'))
622 return ((p
- last
) > 0 && (p
- last
) <= 255);
626 dt_type_host(struct dt_state
*s
, int nargs
)
628 return (dt_type_hostname(s
, 0) || dt_type_ipaddr(s
, 0));
632 dt_type_network(struct dt_state
*s
, int nargs
)
634 return (dt_type_uciname(s
, 0) || dt_type_host(s
, 0));
638 dt_type_phonedigit(struct dt_state
*s
, int nargs
)
643 *p
&& ((*p
>= '0' && *p
<= '9') || (*p
== '*') || (*p
== '#') ||
644 (*p
== '!') || (*p
== '.'));
651 dt_type_directory(struct dt_state
*s
, int nargs
)
654 return (!stat(s
->value
, &st
) && S_ISDIR(st
.st_mode
));
659 dt_type_device(struct dt_state
*s
, int nargs
)
662 return (!stat(s
->value
, &st
) &&
663 (S_ISBLK(st
.st_mode
) || S_ISCHR(st
.st_mode
)));
667 dt_type_file(struct dt_state
*s
, int nargs
)
670 return (!stat(s
->value
, &st
) && S_ISREG(st
.st_mode
));
674 static struct dt_fun dt_types
[] = {
675 { "or", dt_type_or
},
676 { "and", dt_type_and
},
677 { "not", dt_type_not
},
678 { "neg", dt_type_neg
},
679 { "list", dt_type_list
},
680 { "min", dt_type_min
},
681 { "max", dt_type_max
},
682 { "range", dt_type_range
},
683 { "minlength", dt_type_minlen
},
684 { "maxlength", dt_type_maxlen
},
685 { "rangelength", dt_type_rangelen
},
686 { "integer", dt_type_int
},
687 { "uinteger", dt_type_uint
},
688 { "float", dt_type_float
},
689 { "ufloat", dt_type_ufloat
},
690 { "bool", dt_type_bool
},
691 { "string", dt_type_string
},
692 { "ip4addr", dt_type_ip4addr
},
693 { "ip6addr", dt_type_ip6addr
},
694 { "ipaddr", dt_type_ipaddr
},
695 { "cidr4", dt_type_cidr4
},
696 { "cidr6", dt_type_cidr6
},
697 { "cidr", dt_type_cidr
},
698 { "netmask4", dt_type_netmask4
},
699 { "netmask6", dt_type_netmask6
},
700 { "ipmask4", dt_type_ipmask4
},
701 { "ipmask6", dt_type_ipmask6
},
702 { "ipmask", dt_type_ipmask
},
703 { "port", dt_type_port
},
704 { "portrange", dt_type_portrange
},
705 { "macaddr", dt_type_macaddr
},
706 { "uciname", dt_type_uciname
},
707 { "wpakey", dt_type_wpakey
},
708 { "wepkey", dt_type_wepkey
},
709 { "hostname", dt_type_hostname
},
710 { "host", dt_type_host
},
711 { "network", dt_type_network
},
712 { "phonedigit", dt_type_phonedigit
},
713 { "directory", dt_type_directory
},
714 { "device", dt_type_device
},
715 { "file", dt_type_file
},
720 static struct dt_fun
*
721 dt_lookup_function(const char *s
, const char *e
)
723 struct dt_fun
*fun
= dt_types
;
727 if (!strncmp(fun
->name
, s
, e
- s
) && *(fun
->name
+ (e
- s
)) == '\0')
737 dt_parse_atom(struct dt_state
*s
, const char *label
, const char *end
)
744 struct dt_op
*op
= &s
->stack
[s
->depth
];
746 if ((s
->depth
+ 1) >= (sizeof(s
->stack
) / sizeof(s
->stack
[0])))
748 printf("Syntax error, expression too long\n");
752 while (isspace(*label
))
755 /* test whether label is a float */
756 dval
= strtod(label
, &e
);
761 op
->type
= OP_NUMBER
;
762 op
->value
.number
= dval
;
763 op
->nextop
= ++s
->depth
;
767 else if ((*label
== '"') || (*label
== '\''))
769 for (p
= label
+ 1, q
= *label
, esc
= false; p
<= end
; p
++)
784 op
->type
= OP_STRING
;
785 op
->length
= (p
- label
) - 2;
786 op
->value
.string
= label
+ 1;
787 op
->nextop
= ++s
->depth
;
793 printf("Syntax error, unterminated string\n");
799 p
<= end
&& ((*p
>= 'A' && *p
<= 'Z') ||
800 (*p
>= 'a' && *p
<= 'z') ||
801 (*p
>= '0' && *p
<= '9') ||
805 func
= dt_lookup_function(label
, p
);
809 printf("Syntax error, unrecognized function\n");
814 op
->type
= OP_FUNCTION
;
815 op
->value
.function
= func
;
816 op
->nextop
= ++s
->depth
;
821 printf("Syntax error, unexpected EOF\n");
826 dt_parse_list(struct dt_state
*s
, const char *code
, const char *end
);
829 dt_parse_expr(const char *code
, const char *end
, struct dt_state
*s
)
833 if (!dt_parse_atom(s
, code
, end
))
836 tok
= &s
->stack
[s
->depth
- 1];
838 while (isspace(*tok
->next
))
841 if (tok
->type
== OP_FUNCTION
)
843 if (*tok
->next
== '(')
847 while (isspace(*end
) && end
> tok
->next
+ 1)
850 return dt_parse_list(s
, tok
->next
+ 1, end
);
852 else if (tok
->next
== end
)
854 return dt_parse_list(s
, tok
->next
, tok
->next
);
857 printf("Syntax error, expected '(' or EOF after function label\n");
860 else if (tok
->next
== end
)
865 printf("Syntax error, expected ',' after literal\n");
870 dt_parse_list(struct dt_state
*s
, const char *code
, const char *end
)
875 const char *p
, *last
;
881 fptr
= &s
->stack
[s
->depth
- 1];
883 for (nest
= 0, p
= last
= code
, esc
= false, c
= *p
;
885 p
++, c
= (p
< end
) ? *p
: '\0')
913 if (!dt_parse_expr(last
, p
, s
))
926 fptr
->nextop
= s
->depth
;
931 dt_step(struct dt_state
*s
)
934 struct dt_op
*op
= &s
->stack
[s
->pos
];
939 rv
= op
->value
.boolean
;
943 rv
= dt_test_number(op
->value
.number
, s
->value
);
947 rv
= dt_test_string(op
->value
.string
, op
->value
.string
+ op
->length
, s
->value
);
964 dt_call(struct dt_state
*s
)
967 struct dt_op
*fptr
= &s
->stack
[s
->pos
];
968 struct dt_fun
*func
= fptr
->value
.function
;
972 rv
= func
->call(s
, fptr
->length
);
974 s
->pos
= fptr
->nextop
;
980 dt_parse(const char *code
, const char *value
)
982 struct dt_state s
= {
987 .value
.function
= &dt_types
[0],
993 if (!value
|| !*value
)
996 if (!dt_parse_list(&s
, code
, code
+ strlen(code
)))