Deprecate unmaintainable uses of strncmp to implement abbreviations.

This commit replaces those with two new functions that simplify the code
and produce warnings that the syntax is deprecated.  A small number of
sensible abbreviations may be explicitly added based on user feedback.

There were previously three types of strncmp use in ipfw:
 - Most commonly, strncmp(av, "string", sizeof(av)) was used to allow av
   to match string or any shortened form of it.  I have replaced this
   with a new function _substrcmp(av, "string") which returns 0 if av
   is a substring of "string", but emits a warning if av is not exactly
   "string".

 - The next type was two instances of strncmp(av, "by", 2) which allowed
   the abbreviation of bytes to "by", "byt", etc.  Unfortunately, it
   also supported "bykHUygh&*g&*7*ui".  I added a second new function
   _substrcmp2(av, "by", "bytes") which acts like the strncmp did, but
   complains if the user doesn't spell out the word "bytes".

 - There is also one correct use of strncmp to match "table(" which might
   have another token after it without a space.

Since I changed all the lines anyway, I also fixed the treatment of
strncmp's return as a boolean in many cases.  I also modified a few
strcmp cases as well to be fully consistent.
This commit is contained in:
brooks 2005-01-15 01:46:41 +00:00
parent 3e538fd2f7
commit a7b7255dba

View File

@ -448,6 +448,56 @@ match_value(struct _s_x *p, int value)
return NULL;
}
/*
* _substrcmp takes two strings and returns 1 if they do not match,
* and 0 if they match exactly or the first string is a sub-string
* of the second. A warning is printed to stderr in the case that the
* first string is a sub-string of the second.
*
* This function will be removed in the future through the usual
* deprecation process.
*/
static int
_substrcmp(const char *str1, const char* str2)
{
if (strncmp(str1, str2, strlen(str1)) != 0)
return 1;
if (strlen(str1) != strlen(str2))
warnx("DEPRECATED: '%s' matched '%s' as a sub-string",
str1, str2);
return 0;
}
/*
* _substrcmp2 takes three strings and returns 1 if the first two do not match,
* and 0 if they match exactly or the second string is a sub-string
* of the first. A warning is printed to stderr in the case that the
* first string does not match the third.
*
* This function exists to warn about the bizzare construction
* strncmp(str, "by", 2) which is used to allow people to use a shotcut
* for "bytes". The problem is that in addition to accepting "by",
* "byt", "byte", and "bytes", it also excepts "by_rabid_dogs" and any
* other string beginning with "by".
*
* This function will be removed in the future through the usual
* deprecation process.
*/
static int
_substrcmp2(const char *str1, const char* str2, const char* str3)
{
if (strncmp(str1, str2, strlen(str2)) != 0)
return 1;
if (strcmp(str1, str3) != 0)
warnx("DEPRECATED: '%s' matched '%s'",
str1, str3);
return 0;
}
/*
* prints one port, symbolic or numeric
*/
@ -1760,7 +1810,7 @@ sets_handler(int ac, char *av[])
if (!ac)
errx(EX_USAGE, "set needs command");
if (!strncmp(*av, "show", strlen(*av)) ) {
if (_substrcmp(*av, "show") == 0) {
void *data;
char const *msg;
@ -1784,7 +1834,7 @@ sets_handler(int ac, char *av[])
msg = "";
}
printf("\n");
} else if (!strncmp(*av, "swap", strlen(*av))) {
} else if (_substrcmp(*av, "swap") == 0) {
ac--; av++;
if (ac != 2)
errx(EX_USAGE, "set swap needs 2 set numbers\n");
@ -1796,14 +1846,14 @@ sets_handler(int ac, char *av[])
errx(EX_DATAERR, "invalid set number %s\n", av[1]);
masks[0] = (4 << 24) | (new_set << 16) | (rulenum);
i = do_cmd(IP_FW_DEL, masks, sizeof(uint32_t));
} else if (!strncmp(*av, "move", strlen(*av))) {
} else if (_substrcmp(*av, "move") == 0) {
ac--; av++;
if (ac && !strncmp(*av, "rule", strlen(*av))) {
if (ac && _substrcmp(*av, "rule") == 0) {
cmd = 2;
ac--; av++;
} else
cmd = 3;
if (ac != 3 || strncmp(av[1], "to", strlen(*av)))
if (ac != 3 || _substrcmp(av[1], "to") != 0)
errx(EX_USAGE, "syntax: set move [rule] X to Y\n");
rulenum = atoi(av[0]);
new_set = atoi(av[2]);
@ -1814,9 +1864,9 @@ sets_handler(int ac, char *av[])
errx(EX_DATAERR, "invalid dest. set %s\n", av[1]);
masks[0] = (cmd << 24) | (new_set << 16) | (rulenum);
i = do_cmd(IP_FW_DEL, masks, sizeof(uint32_t));
} else if (!strncmp(*av, "disable", strlen(*av)) ||
!strncmp(*av, "enable", strlen(*av)) ) {
int which = !strncmp(*av, "enable", strlen(*av)) ? 1 : 0;
} else if (_substrcmp(*av, "disable") == 0 ||
_substrcmp(*av, "enable") == 0 ) {
int which = _substrcmp(*av, "enable") == 0 ? 1 : 0;
ac--; av++;
masks[0] = masks[1] = 0;
@ -1828,9 +1878,9 @@ sets_handler(int ac, char *av[])
errx(EX_DATAERR,
"invalid set number %d\n", i);
masks[which] |= (1<<i);
} else if (!strncmp(*av, "disable", strlen(*av)))
} else if (_substrcmp(*av, "disable") == 0)
which = 0;
else if (!strncmp(*av, "enable", strlen(*av)))
else if (_substrcmp(*av, "enable") == 0)
which = 1;
else
errx(EX_DATAERR,
@ -1856,22 +1906,22 @@ sysctl_handler(int ac, char *av[], int which)
if (ac == 0) {
warnx("missing keyword to enable/disable\n");
} else if (strncmp(*av, "firewall", strlen(*av)) == 0) {
} else if (_substrcmp(*av, "firewall") == 0) {
sysctlbyname("net.inet.ip.fw.enable", NULL, 0,
&which, sizeof(which));
} else if (strncmp(*av, "one_pass", strlen(*av)) == 0) {
} else if (_substrcmp(*av, "one_pass") == 0) {
sysctlbyname("net.inet.ip.fw.one_pass", NULL, 0,
&which, sizeof(which));
} else if (strncmp(*av, "debug", strlen(*av)) == 0) {
} else if (_substrcmp(*av, "debug") == 0) {
sysctlbyname("net.inet.ip.fw.debug", NULL, 0,
&which, sizeof(which));
} else if (strncmp(*av, "verbose", strlen(*av)) == 0) {
} else if (_substrcmp(*av, "verbose") == 0) {
sysctlbyname("net.inet.ip.fw.verbose", NULL, 0,
&which, sizeof(which));
} else if (strncmp(*av, "dyn_keepalive", strlen(*av)) == 0) {
} else if (_substrcmp(*av, "dyn_keepalive") == 0) {
sysctlbyname("net.inet.ip.fw.dyn_keepalive", NULL, 0,
&which, sizeof(which));
} else if (strncmp(*av, "altq", strlen(*av)) == 0) {
} else if (_substrcmp(*av, "altq") == 0) {
altq_set_enabled(which);
} else {
warnx("unrecognize enable/disable keyword: %s\n", *av);
@ -2122,15 +2172,15 @@ fill_ip(ipfw_insn_ip *cmd, char *av)
cmd->o.len &= ~F_LEN_MASK; /* zero len */
if (!strncmp(av, "any", strlen(av)))
if (_substrcmp(av, "any") == 0)
return;
if (!strncmp(av, "me", strlen(av))) {
if (_substrcmp(av, "me") == 0) {
cmd->o.len |= F_INSN_SIZE(ipfw_insn);
return;
}
if (!strncmp(av, "table(", 6)) {
if (strncmp(av, "table(", 6) == 0) {
char *p = strchr(av + 6, ',');
if (p)
@ -2341,7 +2391,7 @@ delete(int ac, char *av[])
av++; ac--;
NEED1("missing rule specification");
if (ac > 0 && !strncmp(*av, "set", strlen(*av))) {
if (ac > 0 && _substrcmp(*av, "set") == 0) {
do_set = 1; /* delete set */
ac--; av++;
}
@ -2389,7 +2439,7 @@ fill_iface(ipfw_insn_if *cmd, char *arg)
cmd->o.len |= F_INSN_SIZE(ipfw_insn_if);
/* Parse the interface or address */
if (!strcmp(arg, "any"))
if (strcmp(arg, "any") == 0)
cmd->o.len = 0; /* effectively ignore this command */
else if (!isdigit(*arg)) {
strlcpy(cmd->name, arg, sizeof(cmd->name));
@ -2446,7 +2496,8 @@ config_pipe(int ac, char **av)
if (*end == 'K' || *end == 'k') {
p.fs.flags_fs |= DN_QSIZE_IS_BYTES;
p.fs.qsize *= 1024;
} else if (*end == 'B' || !strncmp(end, "by", 2)) {
} else if (*end == 'B' ||
_substrcmp2(end, "by", "bytes") == 0) {
p.fs.flags_fs |= DN_QSIZE_IS_BYTES;
}
ac--; av++;
@ -2603,7 +2654,8 @@ config_pipe(int ac, char **av)
end++;
p.bandwidth *= 1000000;
}
if (*end == 'B' || !strncmp(end, "by", 2))
if (*end == 'B' ||
_substrcmp2(end, "by", "bytes") == 0)
p.bandwidth *= 8;
if (p.bandwidth < 0)
errx(EX_DATAERR, "bandwidth too large");
@ -2736,7 +2788,7 @@ get_mac_addr_mask(char *p, uint8_t *addr, uint8_t *mask)
for (i=0; i<6; i++)
addr[i] = mask[i] = 0;
if (!strcmp(p, "any"))
if (strcmp(p, "any") == 0)
return;
for (i=0; *p && i<6;i++, p++) {
@ -2857,7 +2909,7 @@ add_proto(ipfw_insn *cmd, char *av)
struct protoent *pe;
u_char proto = 0;
if (!strncmp(av, "all", strlen(av)))
if (_substrcmp(av, "all") == 0)
; /* same as "ip" */
else if ((proto = atoi(av)) > 0)
; /* all done! */
@ -2907,7 +2959,7 @@ add_dstip(ipfw_insn *cmd, char *av)
static ipfw_insn *
add_ports(ipfw_insn *cmd, char *av, u_char proto, int opcode)
{
if (!strncmp(av, "any", strlen(av))) {
if (_substrcmp(av, "any") == 0) {
return NULL;
} else if (fill_newports((ipfw_insn_u16 *)cmd, av, proto)) {
/* XXX todo: check that we have a protocol with ports */
@ -2979,7 +3031,7 @@ add(int ac, char *av[])
}
/* [set N] -- set number (0..RESVD_SET), optional */
if (ac > 1 && !strncmp(*av, "set", strlen(*av))) {
if (ac > 1 && _substrcmp(*av, "set") == 0) {
int set = strtoul(av[1], NULL, 10);
if (set < 0 || set > RESVD_SET)
errx(EX_DATAERR, "illegal set %s", av[1]);
@ -2988,7 +3040,7 @@ add(int ac, char *av[])
}
/* [prob D] -- match probability, optional */
if (ac > 1 && !strncmp(*av, "prob", strlen(*av))) {
if (ac > 1 && _substrcmp(*av, "prob") == 0) {
match_prob = strtod(av[1], NULL);
if (match_prob <= 0 || match_prob > 1)
@ -3132,7 +3184,7 @@ add(int ac, char *av[])
have_log = (ipfw_insn *)c;
cmd->len = F_INSN_SIZE(ipfw_insn_log);
cmd->opcode = O_LOG;
if (ac && !strncmp(*av, "logamount", strlen(*av))) {
if (ac && _substrcmp(*av, "logamount") == 0) {
ac--; av++;
NEED1("logamount requires argument");
l = atoi(*av);
@ -3193,8 +3245,8 @@ add(int ac, char *av[])
#define CLOSE_PAR \
if (open_par) { \
if (ac && ( \
!strncmp(*av, ")", strlen(*av)) || \
!strncmp(*av, "}", strlen(*av)) )) { \
strcmp(*av, ")") == 0 || \
strcmp(*av, "}") == 0)) { \
prev = NULL; \
open_par = 0; \
ac--; av++; \
@ -3203,7 +3255,7 @@ add(int ac, char *av[])
}
#define NOT_BLOCK \
if (ac && !strncmp(*av, "not", strlen(*av))) { \
if (ac && _substrcmp(*av, "not") == 0) { \
if (cmd->len & F_NOT) \
errx(EX_USAGE, "double \"not\" not allowed\n"); \
cmd->len |= F_NOT; \
@ -3211,7 +3263,7 @@ add(int ac, char *av[])
}
#define OR_BLOCK(target) \
if (ac && !strncmp(*av, "or", strlen(*av))) { \
if (ac && _substrcmp(*av, "or") == 0) { \
if (prev == NULL || open_par == 0) \
errx(EX_DATAERR, "invalid OR block"); \
prev->len |= F_OR; \
@ -3230,8 +3282,8 @@ add(int ac, char *av[])
*/
NOT_BLOCK;
NEED1("missing protocol");
if (!strncmp(*av, "MAC", strlen(*av)) ||
!strncmp(*av, "mac", strlen(*av))) {
if (_substrcmp(*av, "MAC") == 0 ||
_substrcmp(*av, "mac") == 0) {
ac--; av++; /* the "MAC" keyword */
add_mac(cmd, ac, av); /* exits in case of errors */
cmd = next_cmd(cmd);
@ -3269,7 +3321,7 @@ add(int ac, char *av[])
/*
* "from", mandatory
*/
if (!ac || strncmp(*av, "from", strlen(*av)))
if (!ac || _substrcmp(*av, "from") != 0)
errx(EX_USAGE, "missing ``from''");
ac--; av++;
@ -3293,7 +3345,7 @@ add(int ac, char *av[])
*/
NOT_BLOCK; /* optional "not" */
if (ac) {
if (!strncmp(*av, "any", strlen(*av)) ||
if (_substrcmp(*av, "any") == 0 ||
add_ports(cmd, *av, proto, O_IP_SRCPORT)) {
ac--; av++;
if (F_LEN(cmd) != 0)
@ -3304,7 +3356,7 @@ add(int ac, char *av[])
/*
* "to", mandatory
*/
if (!ac || strncmp(*av, "to", strlen(*av)))
if (!ac || _substrcmp(*av, "to") != 0)
errx(EX_USAGE, "missing ``to''");
av++; ac--;
@ -3328,7 +3380,7 @@ add(int ac, char *av[])
*/
NOT_BLOCK; /* optional "not" */
if (ac) {
if (!strncmp(*av, "any", strlen(*av)) ||
if (_substrcmp(*av, "any") == 0 ||
add_ports(cmd, *av, proto, O_IP_DSTPORT)) {
ac--; av++;
if (F_LEN(cmd) != 0)
@ -3665,7 +3717,7 @@ add(int ac, char *av[])
case TOK_SRCPORT:
NEED1("missing source port");
if (!strncmp(*av, "any", strlen(*av)) ||
if (_substrcmp(*av, "any") == 0 ||
add_ports(cmd, *av, proto, O_IP_SRCPORT)) {
ac--; av++;
} else
@ -3674,7 +3726,7 @@ add(int ac, char *av[])
case TOK_DSTPORT:
NEED1("missing destination port");
if (!strncmp(*av, "any", strlen(*av)) ||
if (_substrcmp(*av, "any") == 0 ||
add_ports(cmd, *av, proto, O_IP_DSTPORT)) {
ac--; av++;
} else
@ -3920,8 +3972,8 @@ table_handler(int ac, char *av[])
} else
errx(EX_USAGE, "table number required");
NEED1("table needs command");
if (strncmp(*av, "add", strlen(*av)) == 0 ||
strncmp(*av, "delete", strlen(*av)) == 0) {
if (_substrcmp(*av, "add") == 0 ||
_substrcmp(*av, "delete") == 0) {
do_add = **av == 'a';
ac--; av++;
if (!ac)
@ -3945,10 +3997,10 @@ table_handler(int ac, char *av[])
&ent, sizeof(ent)) < 0)
err(EX_OSERR, "setsockopt(IP_FW_TABLE_%s)",
do_add ? "ADD" : "DEL");
} else if (strncmp(*av, "flush", strlen(*av)) == 0) {
} else if (_substrcmp(*av, "flush") == 0) {
if (do_cmd(IP_FW_TABLE_FLUSH, &ent.tbl, sizeof(ent.tbl)) < 0)
err(EX_OSERR, "setsockopt(IP_FW_TABLE_FLUSH)");
} else if (strncmp(*av, "list", strlen(*av)) == 0) {
} else if (_substrcmp(*av, "list") == 0) {
a = ent.tbl;
l = sizeof(a);
if (do_cmd(IP_FW_TABLE_GETSIZE, &a, (uintptr_t)&l) < 0)
@ -4160,9 +4212,9 @@ ipfw_main(int oldac, char **oldav)
* optional: pipe or queue
*/
do_pipe = 0;
if (!strncmp(*av, "pipe", strlen(*av)))
if (_substrcmp(*av, "pipe") == 0)
do_pipe = 1;
else if (!strncmp(*av, "queue", strlen(*av)))
else if (_substrcmp(*av, "queue") == 0)
do_pipe = 2;
if (do_pipe) {
ac--;
@ -4182,30 +4234,30 @@ ipfw_main(int oldac, char **oldav)
av[1] = p;
}
if (!strncmp(*av, "add", strlen(*av)))
if (_substrcmp(*av, "add") == 0)
add(ac, av);
else if (do_pipe && !strncmp(*av, "config", strlen(*av)))
else if (do_pipe && _substrcmp(*av, "config") == 0)
config_pipe(ac, av);
else if (!strncmp(*av, "delete", strlen(*av)))
else if (_substrcmp(*av, "delete") == 0)
delete(ac, av);
else if (!strncmp(*av, "flush", strlen(*av)))
else if (_substrcmp(*av, "flush") == 0)
flush(do_force);
else if (!strncmp(*av, "zero", strlen(*av)))
else if (_substrcmp(*av, "zero") == 0)
zero(ac, av, IP_FW_ZERO);
else if (!strncmp(*av, "resetlog", strlen(*av)))
else if (_substrcmp(*av, "resetlog") == 0)
zero(ac, av, IP_FW_RESETLOG);
else if (!strncmp(*av, "print", strlen(*av)) ||
!strncmp(*av, "list", strlen(*av)))
else if (_substrcmp(*av, "print") == 0 ||
_substrcmp(*av, "list") == 0)
list(ac, av, do_acct);
else if (!strncmp(*av, "set", strlen(*av)))
else if (_substrcmp(*av, "set") == 0)
sets_handler(ac, av);
else if (!strncmp(*av, "table", strlen(*av)))
else if (_substrcmp(*av, "table") == 0)
table_handler(ac, av);
else if (!strncmp(*av, "enable", strlen(*av)))
else if (_substrcmp(*av, "enable") == 0)
sysctl_handler(ac, av, 1);
else if (!strncmp(*av, "disable", strlen(*av)))
else if (_substrcmp(*av, "disable") == 0)
sysctl_handler(ac, av, 0);
else if (!strncmp(*av, "show", strlen(*av)))
else if (_substrcmp(*av, "show") == 0)
list(ac, av, 1 /* show counters */);
else
errx(EX_USAGE, "bad command `%s'", *av);