(index int, name string) tuples.
:exc:`OSError` if the system call fails.
- .. availability:: Unix.
+ .. availability:: Unix, Windows.
.. versionadded:: 3.3
+ .. versionchanged:: 3.8
+ Windows support was added.
+
.. function:: if_nametoindex(if_name)
interface name.
:exc:`OSError` if no interface with the given name exists.
- .. availability:: Unix.
+ .. availability:: Unix, Windows.
.. versionadded:: 3.3
+ .. versionchanged:: 3.8
+ Windows support was added.
+
.. function:: if_indextoname(if_index)
interface index number.
:exc:`OSError` if no interface with the given index exists.
- .. availability:: Unix.
+ .. availability:: Unix, Windows.
.. versionadded:: 3.3
+ .. versionchanged:: 3.8
+ Windows support was added.
+
.. _socket-objects:
creating a server socket, including accepting both IPv4 and IPv6 connections
on the same socket. (Contributed by Giampaolo Rodola in :issue:`17561`.)
+The :func:`socket.if_nameindex()`, :func:`socket.if_nametoindex()`, and
+:func:`socket.if_indextoname()` functions have been implemented on Windows.
+(Contributed by Zackery Spytz in :issue:`37007`.)
+
shlex
----------
self.assertIsInstance(_name, str)
self.assertEqual(name, _name)
- @unittest.skipUnless(hasattr(socket, 'if_nameindex'),
- 'socket.if_nameindex() not available.')
- def testInvalidInterfaceNameIndex(self):
- # test nonexistent interface index/name
+ @unittest.skipUnless(hasattr(socket, 'if_indextoname'),
+ 'socket.if_indextoname() not available.')
+ def testInvalidInterfaceIndexToName(self):
self.assertRaises(OSError, socket.if_indextoname, 0)
- self.assertRaises(OSError, socket.if_nametoindex, '_DEADBEEF')
- # test with invalid values
- self.assertRaises(TypeError, socket.if_nametoindex, 0)
self.assertRaises(TypeError, socket.if_indextoname, '_DEADBEEF')
+ @unittest.skipUnless(hasattr(socket, 'if_nametoindex'),
+ 'socket.if_nametoindex() not available.')
+ def testInvalidInterfaceNameToIndex(self):
+ self.assertRaises(TypeError, socket.if_nametoindex, 0)
+ self.assertRaises(OSError, socket.if_nametoindex, '_DEADBEEF')
+
@unittest.skipUnless(hasattr(sys, 'getrefcount'),
'test needs sys.getrefcount()')
def testRefCountGetNameInfo(self):
self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, 0))
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
- @unittest.skipUnless(
- hasattr(socket, 'if_nameindex'),
- 'if_nameindex is not supported')
+ @unittest.skipIf(sys.platform == 'win32', 'does not work on Windows')
@unittest.skipIf(AIX, 'Symbolic scope id does not work')
def test_getaddrinfo_ipv6_scopeid_symbolic(self):
# Just pick up any network interface (Linux, Mac OS X)
self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, ifindex))
@unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.')
- @unittest.skipUnless(
- hasattr(socket, 'if_nameindex'),
- 'if_nameindex is not supported')
+ @unittest.skipIf(sys.platform == 'win32', 'does not work on Windows')
@unittest.skipIf(AIX, 'Symbolic scope id does not work')
def test_getnameinfo_ipv6_scopeid_symbolic(self):
# Just pick up any network interface.
--- /dev/null
+Implement :func:`socket.if_nameindex()`, :func:`socket.if_nametoindex()`, and
+:func:`socket.if_indextoname()` on Windows.
/* Provides the IsWindows7SP1OrGreater() function */
#include <versionhelpers.h>
+// For if_nametoindex() and if_indextoname()
+#include <iphlpapi.h>
/* remove some flags on older version Windows during run-time.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms738596.aspx */
A value of None indicates that new socket objects have no timeout.\n\
When the socket module is first imported, the default is None.");
-#ifdef HAVE_IF_NAMEINDEX
+#if defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)
/* Python API for getting interface indices and names */
static PyObject *
socket_if_nameindex(PyObject *self, PyObject *arg)
{
- PyObject *list;
+ 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) {
+ Py_DECREF(list);
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
- list = PyList_New(0);
- if (list == NULL) {
- if_freenameindex(ni);
- return NULL;
- }
-
#ifdef _Py_MEMORY_SANITIZER
__msan_unpoison(ni, sizeof(ni));
__msan_unpoison(&ni[0], sizeof(ni[0]));
if_freenameindex(ni);
return list;
+#endif
}
PyDoc_STRVAR(if_nameindex_doc,
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;
static PyObject *
socket_if_indextoname(PyObject *self, PyObject *arg)
{
+#ifdef MS_WINDOWS
+ NET_IFINDEX index;
+#else
unsigned long index;
+#endif
char name[IF_NAMESIZE + 1];
index = PyLong_AsUnsignedLong(arg);
\n\
Returns the interface name corresponding to the interface index if_index.");
-#endif /* HAVE_IF_NAMEINDEX */
+#endif // defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)
#ifdef CMSG_LEN
METH_NOARGS, getdefaulttimeout_doc},
{"setdefaulttimeout", socket_setdefaulttimeout,
METH_O, setdefaulttimeout_doc},
-#ifdef HAVE_IF_NAMEINDEX
+#if defined(HAVE_IF_NAMEINDEX) || defined(MS_WINDOWS)
{"if_nameindex", socket_if_nameindex,
METH_NOARGS, if_nameindex_doc},
{"if_nametoindex", socket_if_nametoindex,
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
- <AdditionalDependencies>ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>