Repository navigation
It's possible to have if_indextoname and if_nametoindex without if_nameindex, but socket doesn't expose that #156439
Copy link
Copy link
Closed
Labels
OS-androidextension-modulesC modules in the Modules dirC modules in the Modules dirtopic-socketRelated to the socket, socketserver and selectors modulesRelated to the socket, socketserver and selectors modulestype-featureA feature request or enhancementA feature request or enhancement
Description
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) |
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
Linked PRs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
OS-androidextension-modulesC modules in the Modules dirC modules in the Modules dirtopic-socketRelated to the socket, socketserver and selectors modulesRelated to the socket, socketserver and selectors modulestype-featureA feature request or enhancementA feature request or enhancement
Activity
gh-156439: Gate `socket.if_{nametoindex, indextoname}` on respective …
pythongh-156439: Gate `socket.if_{nametoindex, indextoname}` on respe…