diff -Naur iproute2-ok/include/iptables_common.h iproute2/include/iptables_common.h --- iproute2-ok/include/iptables_common.h 2008-07-01 18:28:41.000000000 +0300 +++ iproute2/include/iptables_common.h 2008-07-01 18:39:11.000000000 +0300 @@ -3,10 +3,14 @@ /* Shared definitions between ipv4 and ipv6. */ enum exittype { - OTHER_PROBLEM = 1, - PARAMETER_PROBLEM, - VERSION_PROBLEM, - RESOURCE_PROBLEM + OTHER_PROBLEM = 1, + PARAMETER_PROBLEM, + VERSION_PROBLEM, + RESOURCE_PROBLEM, + P_ONLY_ONCE, + P_NO_INVERT, + P_BAD_VALUE, + P_ONE_ACTION, }; /* this is a special 64bit data type that is 8-byte aligned */ diff -Naur iproute2-ok/tc/m_ipt.c iproute2/tc/m_ipt.c --- iproute2-ok/tc/m_ipt.c 2008-07-01 18:28:41.000000000 +0300 +++ iproute2/tc/m_ipt.c 2008-07-01 18:42:59.000000000 +0300 @@ -22,6 +22,7 @@ #include "tc_util.h" #include #include +#include #include #include #include @@ -59,6 +60,91 @@ char *lib_dir; +bool strtonuml(const char *s, char **end, unsigned long *value, + unsigned long min, unsigned long max) +{ + unsigned long v; + char *my_end; + + errno = 0; + v = strtoul(s, &my_end, 0); + + if (my_end == s) + return false; + if (end != NULL) + *end = my_end; + + if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { + if (value != NULL) + *value = v; + if (end == NULL) + return *my_end == '\0'; + return true; + } + + return false; +} + +bool strtonum(const char *s, char **end, unsigned int *value, + unsigned int min, unsigned int max) +{ + unsigned long v; + bool ret; + + ret = strtonuml(s, end, &v, min, max); + if (value != NULL) + *value = v; + return ret; +} + +void param_act(unsigned int status, const char *p1, ...) +{ + const char *p2, *p3; + va_list args; + bool b; + + va_start(args, p1); + + switch (status) { + case P_ONLY_ONCE: + p2 = va_arg(args, const char *); + b = va_arg(args, unsigned int); + if (!b) + return; + exit_error(PARAMETER_PROBLEM, + "%s: \"%s\" option may only be specified once", + p1, p2); + break; + case P_NO_INVERT: + p2 = va_arg(args, const char *); + b = va_arg(args, unsigned int); + if (!b) + return; + exit_error(PARAMETER_PROBLEM, + "%s: \"%s\" option cannot be inverted", p1, p2); + break; + case P_BAD_VALUE: + p2 = va_arg(args, const char *); + p3 = va_arg(args, const char *); + exit_error(PARAMETER_PROBLEM, + "%s: Bad value for \"%s\" option: \"%s\"", + p1, p2, p3); + break; + case P_ONE_ACTION: + b = va_arg(args, unsigned int); + if (!b) + return; + exit_error(PARAMETER_PROBLEM, + "%s: At most one action is possible", p1); + break; + default: + exit_error(status, p1, args); + break; + } + + va_end(args); +} + void register_target(struct iptables_target *me) {