Skip to content

It's possible to have if_indextoname and if_nametoindex without if_nameindex, but socket doesn't expose that #156439

Description

@A5rocks

Bug report

Bug description:

I may be misreading the code, but it seems like if_indextoname is conditionally defined only if if_nameindex is (

cpython/Modules/socketmodule.c

Lines 7315 to 7459 in fe3a26f

#if defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)
/* Python API for getting interface indices and names */
/*[clinic input]
_socket.if_nameindex
Return a list of network interface information (index, name) tuples.
[clinic start generated code]*/
static PyObject *
_socket_if_nameindex_impl(PyObject *module)
/*[clinic end generated code: output=93c863a6262059c4 input=d6438bb556de2100]*/
{
PyObject *list = PyList_New(0);
if (list == NULL) {
return NULL;
}
#ifdef MS_WINDOWS
PMIB_IF_TABLE2 tbl;
int ret;
if ((ret = GetIfTable2Ex(MibIfTableRaw, &tbl)) != NO_ERROR) {
Py_DECREF(list);
// ret is used instead of GetLastError()
return PyErr_SetFromWindowsErr(ret);
}
for (ULONG i = 0; i < tbl->NumEntries; ++i) {
MIB_IF_ROW2 r = tbl->Table[i];
WCHAR buf[NDIS_IF_MAX_STRING_SIZE + 1];
if ((ret = ConvertInterfaceLuidToNameW(&r.InterfaceLuid, buf,
Py_ARRAY_LENGTH(buf)))) {
Py_DECREF(list);
FreeMibTable(tbl);
// ret is used instead of GetLastError()
return PyErr_SetFromWindowsErr(ret);
}
PyObject *tuple = Py_BuildValue("Iu", r.InterfaceIndex, buf);
if (tuple == NULL || PyList_Append(list, tuple) == -1) {
Py_XDECREF(tuple);
Py_DECREF(list);
FreeMibTable(tbl);
return NULL;
}
Py_DECREF(tuple);
}
FreeMibTable(tbl);
return list;
#else
int i;
struct if_nameindex *ni;
ni = if_nameindex();
if (ni == NULL) {
PyErr_SetFromErrno(PyExc_OSError);
Py_DECREF(list);
return NULL;
}
#ifdef _Py_MEMORY_SANITIZER
__msan_unpoison(ni, sizeof(ni));
__msan_unpoison(&ni[0], sizeof(ni[0]));
#endif
for (i = 0; ni[i].if_index != 0 && i < INT_MAX; i++) {
#ifdef _Py_MEMORY_SANITIZER
/* This one isn't the end sentinel, the next one must exist. */
__msan_unpoison(&ni[i+1], sizeof(ni[0]));
/* Otherwise Py_BuildValue internals are flagged by MSan when
they access the not-msan-tracked if_name string data. */
{
char *to_sanitize = ni[i].if_name;
do {
__msan_unpoison(to_sanitize, 1);
} while (*to_sanitize++ != '\0');
}
#endif
PyObject *ni_tuple = Py_BuildValue("IO&",
ni[i].if_index, unicode_fsdecode, ni[i].if_name);
if (ni_tuple == NULL || PyList_Append(list, ni_tuple) == -1) {
Py_XDECREF(ni_tuple);
Py_DECREF(list);
if_freenameindex(ni);
return NULL;
}
Py_DECREF(ni_tuple);
}
if_freenameindex(ni);
return list;
#endif
}
/*[clinic input]
_socket.if_nametoindex
oname: unicode_fs_encoded
/
Returns the interface index corresponding to the interface name if_name.
[clinic start generated code]*/
static PyObject *
_socket_if_nametoindex_impl(PyObject *module, PyObject *oname)
/*[clinic end generated code: output=289a411614f30244 input=6125dc20683560cf]*/
{
#ifdef MS_WINDOWS
NET_IFINDEX index;
#else
unsigned long index;
#endif
errno = ENODEV; // in case 'if_nametoindex' does not set errno
index = if_nametoindex(PyBytes_AS_STRING(oname));
if (index == 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return PyLong_FromUnsignedLong(index);
}
/*[clinic input]
@permit_long_summary
_socket.if_indextoname
if_index as index: NET_IFINDEX
/
Returns the interface name corresponding to the interface index if_index.
[clinic start generated code]*/
static PyObject *
_socket_if_indextoname_impl(PyObject *module, NET_IFINDEX index)
/*[clinic end generated code: output=e48bc324993052e0 input=2a0026b271cd43ae]*/
{
errno = ENXIO; // in case 'if_indextoname' does not set errno
char name[IF_NAMESIZE + 1];
if (if_indextoname(index, name) == NULL) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return PyUnicode_DecodeFSDefault(name);
}
#endif // defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)
). This is an issue on e.g. Android, where (I believe) if_indextoname is available on many API versions but if_nameindex is only available on API 24+.

I haven't actually tested anything since I don't have access to an Android emulator, but based on some source code reading I think I'm right?

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    OS-androidextension-modulesC modules in the Modules dirtopic-socketRelated to the socket, socketserver and selectors modulestype-featureA feature request or enhancement

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions