Specific reason why iptables would return an exit code of 3 (instead of 1?) when executed without sufficient privileges

exit-statusiptablesposix

I simply forgot to use sudo:

usr@arch ~[0] $ iptables -L
iptables v1.4.21: can't initialize iptables table `filter': Permission
denied (you must be root)
Perhaps iptables or your kernel needs to be upgraded.
usr@arch ~[3] $ <---

My bash PS1 prompt echoes the last command exit status ($?). The iptables manpages doesn't refer to a return code of 3:

Various error messages are printed to standard error. The exit code
is 0 for correct functioning. Errors which appear to be caused by
invalid or abused command line parameters cause an exit code of 2, and
other errors cause an exit code of 1.

The SUSv3/POSIX discusses exit status for commands.1 A command such as mount – which has 7 different exit statuses for error conditions – executed without privileges returns 1; something that's documented in its manpages: incorrect invocation or permissions.


Q.
So why does iptables and mount differ in that respect – is it purely application specific? Why is it that doing an strace on the former outputs things such as: socket(PF_INET, SOCK_RAW, IPPROTO_RAW) = -1 EPERM (Operation not permitted) – shouldn't it be EACCES instead? Why is it that tracing unprivileged mount calls does not reveal similar errors and do these have an impact on the exit status; or is -1 a failure whatever the reason? Where does that 3 come from?


1. Also: GNU Bash; more generally; random weirdness; recent question with reference to codes being application specific + historical /usr/include/sysexits.h etc.

Best Answer

The documentation is incomplete. The code contains the following list of error codes used internally:

enum xtables_exittype {
    OTHER_PROBLEM = 1,
    PARAMETER_PROBLEM,
    VERSION_PROBLEM,
    RESOURCE_PROBLEM,
    XTF_ONLY_ONCE,
    XTF_NO_INVERT,
    XTF_BAD_VALUE,
    XTF_ONE_ACTION,
};

And when it tries to initialize, it does:

if (!*handle)
    xtables_error(VERSION_PROBLEM,
           "can't initialize iptables table `%s': %s",
           *table, iptc_strerror(errno));

xtables_error prints the error message and exits with the given exit code.

The code seems to be deficient, IMHO, in assuming that a failure here is due to a version problem, without checking the errno to see that it's actually EPERM.

Related Question