summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@baturin.org>2018-06-24 17:09:19 +0200
committerDaniil Baturin <daniil@baturin.org>2018-06-24 17:09:19 +0200
commit345dd8b4c3eb14e1161f26076a7b368ae89dd56d (patch)
treef5392ea019b350e340a87cdfd4731a00414e4760
parent1489376748358222a1ba582cde019f494b6dcba3 (diff)
downloadvyatta-cfg-345dd8b4c3eb14e1161f26076a7b368ae89dd56d.tar.gz
vyatta-cfg-345dd8b4c3eb14e1161f26076a7b368ae89dd56d.zip
T710: move the executables from vyatta-util to vyatta-cfg
Do not use a shared library, since nothing else depends, or should depend on it.
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am11
-rw-r--r--configure.ac2
-rw-r--r--utils/ipset-check-member.c127
-rw-r--r--utils/misc.c21
-rw-r--r--utils/misc.h4
-rw-r--r--utils/type_check.c567
-rw-r--r--utils/type_check.h35
-rw-r--r--utils/vyatta-validate-type.c23
9 files changed, 792 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 09a489f..f809096 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,6 +36,8 @@ src/my_delete
src/check_tmpl
src/dump
src/exe_action
+src/vyatta-validate-type
+src/ipset-check-member
src/priority
src/net_set
src/cli_def.c
diff --git a/Makefile.am b/Makefile.am
index 0060b47..f1b98aa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,6 +19,8 @@ AM_CXXFLAGS += $(GOBJECT_CFLAGS)
AM_YFLAGS = -d --name-prefix=yy_`basename $* .y`_
AM_LFLAGS = --prefix=yy_`basename $* .l`_ -olex.yy.c
+ACLOCAL_AMFLAGS = -I m4
+
completion_DATA = etc/bash_completion.d/vyatta-cfg
initd_SCRIPTS = etc/init.d/vyatta-router
dhcphook_SCRIPTS = scripts/vyatta-dhclient-hook
@@ -83,12 +85,21 @@ vninc_HEADERS += src/cnode/cnode-algorithm.hpp
vpincdir = $(vincludedir)/cparse
vpinc_HEADERS = src/cparse/cparse.hpp
+src_ipset_check_member_SOURCES = utils/ipset-check-member.c
+src_ipset_check_member_SOURCES += utils/misc.c
+src_ipset_check_member_SOURCES += utils/type_check.c
+src_vyatta_validate_type_SOURCES = utils/vyatta-validate-type.c
+src_vyatta_validate_type_SOURCES += utils/misc.c
+src_vyatta_validate_type_SOURCES += utils/type_check.c
+
sbin_PROGRAMS = src/priority
sbin_PROGRAMS += src/exe_action
sbin_PROGRAMS += src/dump
sbin_PROGRAMS += src/check_tmpl
sbin_PROGRAMS += src/my_cli_bin
sbin_PROGRAMS += src/my_cli_shell_api
+sbin_PROGRAMS += src/ipset-check-member
+sbin_PROGRAMS += src/vyatta-validate-type
src_priority_SOURCES = src/priority.c
src_exe_action_SOURCES = src/exe_action.c
diff --git a/configure.ac b/configure.ac
index 17007be..4951509 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,8 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
+AC_CONFIG_MACRO_DIR([m4])
+
m4_define([VERSION_ID], [m4_esyscmd([
if test -f .version ; then
head -n 1 .version | tr -d \\n
diff --git a/utils/ipset-check-member.c b/utils/ipset-check-member.c
new file mode 100644
index 0000000..3805f9a
--- /dev/null
+++ b/utils/ipset-check-member.c
@@ -0,0 +1,127 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include "misc.h"
+#include "type_check.h"
+
+int
+check_port (char *port)
+{
+ if (re_match(port, "^[0-9]+-[0-9]+$")) {
+ if (!validateType("portrange", port, 1)) {
+ printf("Error: [%s] is not a valid port range\n",port);
+ return 0;
+ }
+ return 1;
+ }
+ else {
+ if (!validateType("port", port, 1)) {
+ printf("Error: [%s] is not a valid port\n",port);
+ return 0;
+ }
+ return 1;
+ }
+
+}
+
+int
+check_address (char *addr)
+{
+ if (re_match(addr, "^[^-]+-[^-]+")) {
+ if (!validateType("ipv4range", addr, 1)) {
+ printf("Error: [%s] is not a valid IPv4 address range\n", addr);
+ return 0;
+ }
+ /* check that both addresses are in the same /24 subnet */
+ unsigned int a1[4], a2[4];
+ uint32_t addr1 = 0;
+ uint32_t addr2 = 0;
+ uint32_t mask = 0xffffff00;
+ if (sscanf(addr, "%u.%u.%u.%u-%u.%u.%u.%u",
+ &a1[0], &a1[1], &a1[2], &a1[3],
+ &a2[0], &a2[1], &a2[2], &a2[3]) != 8)
+ return 0;
+ int i;
+ for (i = 0; i<4; ++i) {
+ addr1 <<= 8;
+ addr1 |= a1[i];
+ addr2 <<= 8;
+ addr2 |= a2[i];
+ }
+ addr1 = addr1 & mask;
+ addr2 = addr2 & mask;
+ struct in_addr in;
+ if (addr1 != addr2){
+ addr1 = htonl(addr1);
+ memcpy(&in, &addr1, sizeof(struct in_addr));
+ printf("Error: address range must be within %s/24\n", inet_ntoa(in));
+ return 0;
+ }
+ return 1;
+ }
+ if (strcmp(addr, "0.0.0.0") == 0) {
+ printf ("Error: zero IP address not valid in address-group");
+ return 0;
+ }
+ if (!validateType("ipv4", addr, 1)){
+ printf("Error: [%s] isn't valid IPv4 address\n", addr);
+ return 0;
+ }
+ return 1;
+}
+
+int
+check_network (char *network)
+{
+ if (!validateType("ipv4net", network, 1)) {
+ printf("Error: [%s] isn't a valid IPv4 network\n", network);
+ return 0;
+ }
+ if (re_match(network, "^0.0.0.0/0$")){
+ printf("Error: 0.0.0.0/0 invalid in network-group\n");
+ return 0;
+ }
+ if (re_match(network, "/0$")){
+ printf("Error: zero subnet invalid in network-group\n");
+ return 0;
+ }
+ return 1;
+}
+
+int
+check_member (char *type, char *member)
+{
+ if(strcmp(type, "port") == 0)
+ return (check_port(member));
+ else if (strcmp(type, "address") == 0)
+ return (check_address(member));
+ else if (strcmp(type, "network") == 0)
+ return (check_network(member));
+ else {
+ printf("%s is not a valid type\n", type);
+ return 1;
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret = 1;
+ if (argc < 3) {
+ printf("Usage: ipset-check-member <type> <port>\n");
+ return 1;
+ }
+ char type[10];
+ memset(type, 0, 10);
+ strcpy(type, argv[1]);
+
+ char member[40];
+ memset(member, 0, 40);
+ strcpy(member, argv[2]);
+ ret = check_member(type, member);
+ return (!ret);
+}
diff --git a/utils/misc.c b/utils/misc.c
new file mode 100644
index 0000000..d88f743
--- /dev/null
+++ b/utils/misc.c
@@ -0,0 +1,21 @@
+#include <regex.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+re_match(const char *string, char *pattern)
+{
+ int status;
+ regex_t re;
+ if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0) {
+ return 0;
+ }
+ status = regexec(&re, string, (size_t) 0, NULL, 0);
+ regfree(&re);
+ if (status != 0) {
+ return 0;
+ }
+ return 1;
+}
diff --git a/utils/misc.h b/utils/misc.h
new file mode 100644
index 0000000..dd8e9d0
--- /dev/null
+++ b/utils/misc.h
@@ -0,0 +1,4 @@
+int re_match(const char *string, char *pattern);
+int isValidPortNumber (int port);
+int isValidPortRange (int start, int stop);
+int isValidPortName (const char *name, const char *proto);
diff --git a/utils/type_check.c b/utils/type_check.c
new file mode 100644
index 0000000..e75fc20
--- /dev/null
+++ b/utils/type_check.c
@@ -0,0 +1,567 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include "misc.h"
+#include "type_check.h"
+
+fn_ptr
+get_validator (const char *type)
+{
+ if (strcmp(type, "ipv4") == 0)
+ return &validate_ipv4;
+ else if (strcmp(type, "ipv4net") == 0)
+ return &validate_ipv4net;
+ else if (strcmp(type, "ipv4net_addr") == 0)
+ return &validate_ipv4net_addr;
+ else if (strcmp(type, "ipv4range") == 0)
+ return &validate_ipv4range;
+ else if (strcmp(type, "ipv4_negate") == 0)
+ return &validate_ipv4_negate;
+ else if (strcmp(type, "ipv4net_negate") == 0)
+ return &validate_ipv4net_negate;
+ else if (strcmp(type, "ipv4range_negate") == 0)
+ return &validate_ipv4range_negate;
+ else if (strcmp(type, "iptables4_addr") == 0)
+ return &validate_iptables4_addr;
+ else if (strcmp(type, "protocol") == 0)
+ return &validate_protocol;
+ else if (strcmp(type, "protocol_negate") == 0)
+ return &validate_protocol_negate;
+ else if (strcmp(type, "macaddr") == 0)
+ return &validate_macaddr;
+ else if (strcmp(type, "sys_macaddr") == 0)
+ return &validate_sys_macaddr;
+ else if (strcmp(type, "macaddr_negate") == 0)
+ return &validate_macaddr_negate;
+ else if (strcmp(type, "ipv6") == 0)
+ return &validate_ipv6;
+ else if (strcmp(type, "ipv6_negate") == 0)
+ return &validate_ipv6_negate;
+ else if (strcmp(type, "ipv6net") == 0)
+ return &validate_ipv6net;
+ else if (strcmp(type, "ipv6net_negate") == 0)
+ return &validate_ipv6net_negate;
+ else if (strcmp(type, "hex16") == 0)
+ return &validate_hex16;
+ else if (strcmp(type, "hex32") == 0)
+ return &validate_hex32;
+ else if (strcmp(type, "ipv6_addr_param") == 0)
+ return &validate_ipv6_addr_param;
+ else if (strcmp(type, "restrictive_filename") == 0)
+ return &validate_restrictive_filename;
+ else if (strcmp(type, "no_bash_special") == 0)
+ return &validate_no_bash_special;
+ else if (strcmp(type, "u32") == 0)
+ return &validate_u32;
+ else if (strcmp(type, "bool") == 0)
+ return &validate_bool;
+ else if (strcmp(type, "port") == 0)
+ return &validate_port;
+ else if (strcmp(type, "portrange") == 0)
+ return &validate_portrange;
+ else if (strcmp(type, "port_negate") == 0)
+ return &validate_port_negate;
+ else if (strcmp(type, "portrange_negate") == 0)
+ return &validate_portrange_negate;
+ else
+ return NULL;
+ return NULL;
+}
+
+int
+validate_ipv4 (const char *str)
+{
+ if (!str)
+ return 0;
+ unsigned int a[4];
+ if (strlen(str) == 0){
+ return 0;
+ }
+ if (!re_match(str, "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$"))
+ return 0;
+ if (sscanf(str, "%u.%u.%u.%u", &a[0], &a[1], &a[2], &a[3])
+ != 4)
+ return 0;
+ int i;
+ for (i = 0; i < 4; i++) {
+ if (a[i] > 255)
+ return 0;
+ }
+ return 1;
+}
+
+int
+validate_ipv4net (const char *str)
+{
+ if (!str)
+ return 0;
+ unsigned int a[4], plen;
+ uint32_t addr;
+ if (!re_match(str, "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+/[0-9]+$"))
+ return 0;
+ if (sscanf(str, "%u.%u.%u.%u/%u", &a[0], &a[1], &a[2], &a[3], &plen)
+ != 5)
+ return 0;
+ addr = 0;
+ int i;
+ for (i = 0; i < 4; i++) {
+ if (a[i] > 255)
+ return 0;
+ addr <<= 8;
+ addr |= a[i];
+ }
+ if ((plen == 0 && addr != 0) || plen > 32)
+ return 0;
+ return 1;
+}
+
+int
+validate_ipv4net_addr (const char *str)
+{
+ if (!str)
+ return 0;
+ unsigned int a[4], plen;
+ uint32_t addr;
+ if (!re_match(str, "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+/[0-9]+$"))
+ return 0;
+ if (sscanf(str, "%u.%u.%u.%u/%u", &a[0], &a[1], &a[2], &a[3], &plen)
+ != 5)
+ return 0;
+ addr = 0;
+ int i;
+ for (i = 0; i < 4; i++) {
+ if (a[i] > 255)
+ return 0;
+ addr <<= 8;
+ addr |= a[i];
+ }
+ if ((plen == 0 && addr != 0) || plen > 32)
+ return 0;
+ if (plen < 31) {
+ uint32_t net_mask = ~0 << (32 - plen);
+ uint32_t broadcast = (addr & net_mask) | (~0 &~ net_mask);
+ if ((addr & net_mask) != addr)
+ return 0;
+ if (broadcast != 0 && addr == broadcast)
+ return 0;
+ }
+ return 1;
+}
+
+int
+validate_ipv4range (const char *str)
+{
+ if (!str)
+ return 0;
+ if (!re_match(str,
+ "^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+-[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$"))
+ return 0;
+
+ uint32_t addr1 = 0;
+ uint32_t addr2 = 0;
+ unsigned int a1[4], a2[4];
+ if (sscanf(str, "%u.%u.%u.%u-%u.%u.%u.%u",
+ &a1[0], &a1[1], &a1[2], &a1[3],
+ &a2[0], &a2[1], &a2[2], &a2[3]) != 8)
+ return 0;
+ int i;
+ for (i = 0; i < 4; i++) {
+ if (a1[i] > 255)
+ return 0;
+ addr1 <<= 8;
+ addr1 |= a1[i];
+
+ if (a2[i] >255)
+ return 0;
+ addr2 <<=8;
+ addr2 |= a2[i];
+ }
+ if (addr1 >= addr2)
+ return 0;
+ return 1;
+}
+
+int
+validate_ipv4_negate (const char *str)
+{
+ if (!str)
+ return 0;
+ char ipv4[15];
+ memset(ipv4, '\0', 15);
+ if (sscanf(str, "!%15s", ipv4) != 1)
+ return validate_ipv4(str);
+ return validate_ipv4(ipv4);
+}
+
+int
+validate_ipv4net_negate (const char *str)
+{
+ if (!str)
+ return 0;
+ char ipv4net[18];
+ memset(ipv4net, '\0', 18);
+ if (sscanf(str, "!%18s", ipv4net) != 1)
+ return validate_ipv4net(str);
+ return validate_ipv4net(ipv4net);
+}
+
+int
+validate_ipv4range_negate (const char *str)
+{
+ if (!str)
+ return 0;
+ char ipv4[31];
+ memset(ipv4, '\0', 31);
+ if (sscanf(str, "!%31s", ipv4) != 1)
+ return validate_ipv4range(str);
+ return validate_ipv4range(ipv4);
+}
+
+int
+validate_iptables4_addr (const char *str)
+{
+ if (!str)
+ return 0;
+ if (!validate_ipv4_negate(str) &&
+ !validate_ipv4net_negate(str) &&
+ !validate_ipv4range_negate(str))
+ return 0;
+ return 1;
+}
+
+int
+validate_protocol (const char *str)
+{
+ if (!str)
+ return 0;
+ if (strcmp(str, "all") == 0)
+ return 1;
+ if (strcmp(str, "ip") == 0 || strcmp(str, "0") == 0)
+ return 1;
+ if (re_match(str, "^[0-9]+$")) {
+ int val = atoi(str);
+ if (val >= 1 && val <= 255)
+ return 1;
+ }
+ struct protoent *p;
+ p = getprotobyname(str);
+ if (!p)
+ return 0;
+ if (p->p_proto) {
+ return 1;
+ }
+ return 0;
+}
+
+int
+validate_protocol_negate (const char *str)
+{
+ if (!str)
+ return 0;
+ char proto[100];
+ memset(proto, '\0', 100);
+ if (sscanf(str, "!%100s", proto) != 1)
+ return validate_protocol(str);
+ return validate_protocol(proto);
+}
+
+int
+validate_sys_macaddr (const char *str)
+{
+ if (!str)
+ return 0;
+ if (!validate_macaddr(str))
+ return 0;
+
+ int a[6];
+ int sum = 0;
+
+ if (sscanf(str, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5])
+ != 6) {
+ printf("Error: wrong number of octets\n");
+ return 0;
+ }
+
+ if (a[0] & 1){
+ printf("Error: %x:%x:%x:%x:%x:%x is a multicast address\n",a[0],a[1],a[2],a[3],a[4],a[5]);
+ return 0;
+ }
+
+ if ((a[0] == 0) && (a[1] == 0) && (a[2] == 94) &&(a[3] == 0) && (a[4] == 1)) {
+ printf("Error: %x:%x:%x:%x:%x:%x is a vrrp mac address\n",a[0],a[1],a[2],a[3],a[4],a[5]);
+ return 0;
+ }
+
+ int i;
+ for (i=0; i<6; ++i){
+ sum += a[i];
+ }
+
+ if (sum == 0){
+ printf("Error: zero is not a valid address\n");
+ return 0;
+ }
+ return 1;
+}
+
+int
+validate_macaddr (const char *str)
+{
+ if (!str)
+ return 0;
+ return re_match(str, "^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$");
+}
+
+int
+validate_macaddr_negate (const char *str)
+{
+ if (!str)
+ return 0;
+ char macaddr[17];
+ memset(macaddr,'\0',17);
+ if (sscanf(str, "!%17s", macaddr) != 1)
+ return validate_macaddr(str);
+ return validate_macaddr(macaddr);
+}
+
+int
+validate_ipv6 (const char *str)
+{
+ if (!str)
+ return 0;
+ struct in6_addr addr;
+ if (inet_pton(AF_INET6, str, &addr) <= 0)
+ return 0;
+ return 1;
+}
+
+int
+validate_ipv6net (const char *str)
+{
+ if (!str)
+ return 0;
+ unsigned int prefix_len;
+ struct in6_addr addr;
+ char *slash, *endp;
+
+ slash = strchr(str, '/');
+ if (!slash)
+ return 0;
+ *slash++ = 0;
+ prefix_len = strtoul(slash, &endp, 10);
+ if (*slash == '\0' || *endp != '\0')
+ return 0;
+ else if (prefix_len > 128)
+ return 0;
+ else if (inet_pton(AF_INET6, str, &addr) <= 0)
+ return 0;
+ else
+ return 1;
+}
+
+int
+validate_ipv6_negate (const char *str)
+{
+ if (!str)
+ return 0;
+ char ipv6[39];
+ memset(ipv6, '\0', 39);
+ if (sscanf(str, "!%39s", ipv6) != 1)
+ return validate_ipv6(str);
+ return validate_ipv6(ipv6);
+}
+
+int
+validate_ipv6net_negate (const char *str)
+{
+ if (!str)
+ return 0;
+ char ipv6net[43];
+ memset(ipv6net, '\0', 43);
+ if (sscanf(str, "!%43s", ipv6net) != 1)
+ return validate_ipv6net(str);
+ return validate_ipv6net(ipv6net);
+}
+
+int
+validate_hex16 (const char *str)
+{
+ if (!str)
+ return 0;
+ return re_match(str, "^[0-9a-fA-F]{4}$");
+}
+
+int
+validate_hex32 (const char *str)
+{
+ if (!str)
+ return 0;
+ return re_match(str, "^[0-9a-fA-F]{8}$");
+}
+
+int
+validate_ipv6_addr_param (const char *str)
+{
+ if (!str)
+ return 0;
+ char value[87];
+ char ipv6_1[43];
+ char ipv6_2[43];
+ memset(ipv6_1, '\0', 43);
+ memset(ipv6_2, '\0', 43);
+ if (sscanf(str, "!%87s", value) == 1)
+ str = value;
+ if (re_match(str, "^[^-]+-[^-]+$")){
+ char *dash = strrchr(str, '-');
+ strncpy(ipv6_1, str, dash - str);
+ strncpy(ipv6_2, dash+1, strchr(str,'\0') - dash+1);
+ if (validate_ipv6(ipv6_1))
+ return validate_ipv6(ipv6_2);
+ else
+ return 0;
+ }
+ if (strchr(str, '/') != NULL)
+ return validate_ipv6net(str);
+ else
+ return validate_ipv6(str);
+}
+
+int
+validate_restrictive_filename (const char *str)
+{
+ if (!str)
+ return 0;
+ return re_match(str, "^[-_.a-zA-Z0-9]+$");
+}
+
+int
+validate_no_bash_special (const char *str)
+{
+ if (!str)
+ return 0;
+ return (!re_match(str,"[;&\"'`!$><|]"));
+}
+
+int
+validate_u32 (const char *str)
+{
+ if (!str)
+ return 0;
+ if (!re_match(str, "^[0-9]+$"))
+ return 0;
+ unsigned long int val = strtoul(str, NULL, 0);
+ unsigned long int max = 4294967296;
+ if (val > max)
+ return 0;
+ return 1;
+}
+
+int
+validate_bool (const char *str)
+{
+ if (!str)
+ return 0;
+ if (strcmp(str, "true") == 0)
+ return 1;
+ else if (strcmp(str, "false") == 0)
+ return 1;
+ return 0;
+}
+
+int
+validate_port (const char * str)
+{
+ if (!str)
+ return 0;
+ int port;
+ struct servent *s;
+ if (re_match(str, "^[0-9]+$")) {
+ port = atoi(str);
+ if ( port < 1 || port > 65535 )
+ return 0;
+ else
+ return 1;
+ } else {
+ s = getservbyname(str, NULL);
+ if (!s)
+ return 0;
+ if (s->s_port)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+int
+validate_portrange (const char * str)
+{
+ if (!str)
+ return 0;
+ int start, stop;
+ start = stop = 0;
+ char start_str[6], stop_str[6];
+ memset(start_str, '\0', 6);
+ memset(stop_str, '\0', 6);
+ if (!re_match(str, "^[0-9]+-[0-9]+$"))
+ return 0;
+ if (sscanf(str, "%d-%d", &start, &stop) != 2)
+ return 0;
+ sprintf(start_str, "%d", start);
+ sprintf(stop_str, "%d", stop);
+ if (!validate_port(start_str))
+ return 0;
+ if (!validate_port(stop_str))
+ return 0;
+ if (stop <= start) {
+ return 0;
+ }
+ return 1;
+}
+
+int
+validate_port_negate (const char *str)
+{
+ if (!str)
+ return 0;
+ char port[5];
+ memset(port, '\0', 5);
+ if (sscanf(str, "!%5s", port) != 1)
+ return validate_port(str);
+ return validate_port(port);
+}
+
+int
+validate_portrange_negate (const char *str)
+{
+ if (!str)
+ return 0;
+ char port[11];
+ memset(port, '\0', 11);
+ if (sscanf(str, "!%11s", port) != 1)
+ return validate_portrange(str);
+ return validate_portrange(port);
+}
+
+int
+validateType (const char *type, const char *str, int quiet)
+{
+ if (!str)
+ return 0;
+ int (*validator)(const char *) = NULL;
+ validator = get_validator(type);
+ if (validator == NULL) {
+ if (!quiet)
+ printf("type: \"%s\" is not defined\n", type);
+ return 0;
+ }
+ if (!(*validator)(str)) {
+ if (!quiet)
+ printf("\"%s\" is not a valid value of type \"%s\"\n", str, type);
+ return 0;
+ }
+ return 1;
+}
diff --git a/utils/type_check.h b/utils/type_check.h
new file mode 100644
index 0000000..17c29dc
--- /dev/null
+++ b/utils/type_check.h
@@ -0,0 +1,35 @@
+typedef int (*fn_ptr) (const char*);
+
+fn_ptr get_validator (const char *type);
+
+int validate_ipv4 (const char *);
+int validate_ipv4net (const char *);
+int validate_ipv4net_addr (const char *);
+int validate_ipv4range (const char *);
+int validate_ipv4_negate (const char *);
+int validate_ipv4net_negate (const char *);
+int validate_ipv4range_negate (const char *);
+int validate_iptables4_addr (const char *);
+int validate_protocol (const char *);
+int validate_protocol_negate (const char *);
+int validate_macaddr (const char *);
+int validate_sys_macaddr (const char *);
+int validate_macaddr_negate (const char *);
+int validate_ipv6 (const char *);
+int validate_ipv6net (const char *);
+int validate_ipv6_negate (const char *);
+int validate_ipv6net_negate (const char *);
+int validate_hex16 (const char *);
+int validate_hex32 (const char *);
+int validate_ipv6_addr_param (const char *);
+int validate_restrictive_filename (const char *);
+int validate_no_bash_special (const char *);
+int validate_u32 (const char *);
+int validate_bool (const char *);
+int validate_port (const char *);
+int validate_portrange (const char *);
+int validate_port_negate (const char *);
+int validate_portrange_negate (const char *);
+
+int validateType (const char *, const char *, int);
+
diff --git a/utils/vyatta-validate-type.c b/utils/vyatta-validate-type.c
new file mode 100644
index 0000000..57c6e39
--- /dev/null
+++ b/utils/vyatta-validate-type.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "type_check.h"
+
+int
+main (int argc, char *argv[])
+{
+ if (argc < 2) {
+ printf("usage: vyatta-validate-type [-q] <type> <value>\n");
+ return 1;
+ }
+ if (strcmp(argv[1], "-q") == 0){
+ if (validateType(argv[2], argv[3], 1)) {
+ return 0;
+ }
+ return 1;
+ }
+ if (validateType(argv[1], argv[2], 0)) {
+ return 0;
+ }
+ return 1;
+}