Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

socket.if_nametoindex('no-such-iface') raises OSError() without setting errno #100218

Open
socketpair opened this issue Dec 13, 2022 · 6 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@socketpair
Copy link
Contributor

try:
    if_nametoindex('qweqweq')
except Exception as err:
    print(err.errno)

None

I think it's a bug because I can not distinguish from any other OS errors precisely (like EPERM vs ENOENT or so)

@socketpair socketpair added the type-bug An unexpected behavior, bug, or error label Dec 13, 2022
@socketpair socketpair changed the title socket.if_nametoindex('no-such-iface') raises OSError() wothout setting errno socket.if_nametoindex('no-such-iface') raises OSError() without setting errno Dec 13, 2022
@sobolevn
Copy link
Member

There's a comment in the source code: /* if_nametoindex() doesn't set errno */

@socketpair
Copy link
Contributor Author

Then it should not be OSError or it has to set some errno, like ENOENT or so.

static PyObject *
socket_if_nametoindex(PyObject *self, PyObject *args)
{
    PyObject *oname;
#ifdef MS_WINDOWS
    NET_IFINDEX index;
#else
    unsigned long index;
#endif
    if (!PyArg_ParseTuple(args, "O&:if_nametoindex",
                          PyUnicode_FSConverter, &oname))
        return NULL;

    index = if_nametoindex(PyBytes_AS_STRING(oname));
    Py_DECREF(oname);
    if (index == 0) {
        /* if_nametoindex() doesn't set errno */
        PyErr_SetString(PyExc_OSError, "no interface with this name");
        return NULL;
    }

    return PyLong_FromUnsignedLong(index);
}

Another example from the same file:

    if (h->h_addrtype != af) {
        /* Let's get real error message to return */
        errno = EAFNOSUPPORT;
        PyErr_SetFromErrno(PyExc_OSError);
        return NULL;
    }

I propose the same change. i.e. errno= ENOENT + PyErr_SetFromErrno(PyExc_OSError);

@socketpair
Copy link
Contributor Author

socketpair commented Dec 13, 2022

man if_nametoindex:

On success, if_nametoindex() returns the index number of the network interface;
on error, 0 is returned and errno is set to indicate the error.

It MUST set errno on error! I think there was some incorrect libc implementation when the code was written. So, a crutch like the one I described before is not ever required. As a solution, we can do the following :

errno = ENOENT; // for buggy if_nametoindex implementations, where they don't set errno.
index = if_nametoindex(PyBytes_AS_STRING(oname));
Py_DECREF(oname);
if (index == 0) {
    PyErr_SetFromErrno(PyExc_OSError);
    return NULL;
}

@socketpair
Copy link
Contributor Author

@sobolevn

@sobolevn
Copy link
Member

Sorry, I am not qualified enought in this module to make decisions :)
I've just highlighted that this is a known thing. Probably, you can go to the original comment PR and try to figure out what were the alternatives.

@arhadthedev
Copy link
Member

cc @gpshead as a network expert.

@iritkatriel iritkatriel added the stdlib Python modules in the Lib dir label Nov 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

4 participants