I have a problem with VTY validation. When there is wrong command formatting, we exit VTY parsing in error, which leads to a program exit in error.
However, if the format matches but the value is wrong in a way that the VTY format description is unable to detect, the way to escalate an error up the VTY call chain is a bit weird.
The concrete item in question is the SCCP address point code. The format is like A.B.C, while ranges are variable depending on configuration.
point-code 0.0.1
If I write 'point-code 0.0.99', it exceeds the range and I want to immediately abort the program, indicating the VTY config error.
If I return CMD_WARNING, it is merely ignored.
There are various CMD_ERR_* values to return, but there is no plain error like CMD_ERR_INVALID_VALUE.
I can for example return CMD_ERR_AMBIGUOUS; then the code will try to parse the same line a second time, to see whether the command succeeds on a child of the parent node (we had this before, about implicit node 'exit').
DLSS7 <002d> ../../src/osmo_ss7.c:244 1: Error parsing Pointcode '0.42.99' DLSS7 <002d> ../../src/osmo_ss7.c:244 1: Error parsing Pointcode '0.42.99' There is no such command. Error occurred during reading below line: point-code 0.42.99
% Power 21 dB is not an even value Invalid point code (0.42.99) Invalid point code (0.42.99)
This result is rather curious.
I would like to have a CMD_ERROR return value that immediately exits VTY parsing with a clear error return code.
(We can't abort with an assertion, because that would cause the program to exit in case someone enters a wrong value on the telnet VTY.)
This is the function in question:
int config_from_file(struct vty *vty, FILE * fp) { int ret; vector vline;
while (fgets(vty->buf, VTY_BUFSIZ, fp)) { vline = cmd_make_strvec(vty->buf);
/* In case of comment line */ if (vline == NULL) continue; /* Execute configuration command : this is strict match */ ret = cmd_execute_command_strict(vline, vty, NULL);
// I would insert something like this: // if (ret == CMD_ERROR) // return ret;
/* Try again with setting node to CONFIG_NODE */ while (ret != CMD_SUCCESS && ret != CMD_WARNING && ret != CMD_ERR_NOTHING_TODO && is_config_child(vty)) { vty_go_parent(vty); ret = cmd_execute_command_strict(vline, vty, NULL); // same here }
cmd_free_strvec(vline);
if (ret != CMD_SUCCESS && ret != CMD_WARNING && ret != CMD_ERR_NOTHING_TODO) return ret; } return CMD_SUCCESS; }
Am I on the right track here, have I missed something?
~N