Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5ed2e77

Browse files
committed
Issue #1746656: Add if_nameindex, if_nametoindex, if_indextoname
methods to the socket module.
1 parent 1a4de20 commit 5ed2e77

7 files changed

Lines changed: 429 additions & 248 deletions

File tree

Doc/library/socket.rst

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,39 @@ The module :mod:`socket` exports the following constants and functions:
536536
.. versionadded:: 3.3
537537

538538

539+
.. function:: if_nameindex()
540+
541+
Returns a list of network interface information
542+
(index, name as a byte string) tuples.
543+
:exc:`socket.error` if the system call fails for any reason.
544+
545+
Availability: Unix.
546+
547+
.. versionadded:: 3.3
548+
549+
550+
.. function:: if_nametoindex(if_name)
551+
552+
Returns a network interface index number corresponding to an
553+
interface name byte string.
554+
:exc:`socket.error` if no interface with the given name exists.
555+
556+
Availability: Unix.
557+
558+
.. versionadded:: 3.3
559+
560+
561+
.. function:: if_indextoname(if_index)
562+
563+
Returns a network interface name byte string corresponding to a
564+
interface index.
565+
:exc:`socket.error` if no interface with the given index exists.
566+
567+
Availability: Unix.
568+
569+
.. versionadded:: 3.3
570+
571+
539572
.. data:: SocketType
540573

541574
This is a Python type object that represents the socket object type. It is the

Lib/test/test_socket.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,16 @@ def test_sethostname(self):
372372
finally:
373373
socket.sethostname(oldhn)
374374

375+
@unittest.skipUnless(hasattr(socket, 'if_nameindex'),
376+
'socket.if_nameindex() not available.')
377+
def testInterfaceNameIndex(self):
378+
interfaces = socket.if_nameindex()
379+
for index, name in interfaces:
380+
# interface indices are non-zero integers
381+
self.assertGreater(index, 0)
382+
self.assertEqual(index, socket.if_nametoindex(name))
383+
self.assertEqual(name, socket.if_indextoname(index))
384+
375385
def testRefCountGetNameInfo(self):
376386
# Testing reference count for getnameinfo
377387
if hasattr(sys, "getrefcount"):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Added the if_nameindex, if_indextoname, if_nametoindex methods to
14+
the socket module as requested in issue #1746656.
15+
1316
- Issue #12044: Fixed subprocess.Popen when used as a context manager to
1417
wait for the process to end when exiting the context to avoid unintentionally
1518
leaving zombie processes around.

Modules/socketmodule.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ Module interface:
4242
- socket.inet_ntoa(packed IP) -> IP address string
4343
- socket.getdefaulttimeout() -> None | float
4444
- socket.setdefaulttimeout(None | float)
45+
- socket.if_nameindex() -> list of tuples (if_index, if_name)
46+
- socket.if_nametoindex(name) -> corresponding interface index
47+
- socket.if_indextoname(index) -> corresponding interface name
4548
- an Internet socket address is a pair (hostname, port)
4649
where hostname can be anything recognized by gethostbyname()
4750
(including the dd.dd.dd.dd notation) and port is in host byte order
@@ -133,6 +136,9 @@ setblocking(0 | 1) -- set or clear the blocking I/O flag\n\
133136
setsockopt(level, optname, value) -- set socket options\n\
134137
settimeout(None | float) -- set or clear the timeout\n\
135138
shutdown(how) -- shut down traffic in one or both directions\n\
139+
if_nameindex() -- return all network interface indices and names\n\
140+
if_nametoindex(name) -- returns the corresponding interface index\n\
141+
if_indextoname(index) -- returns the corresponding interface name\n\
136142
\n\
137143
[*] not available on all platforms!");
138144

@@ -4267,6 +4273,102 @@ A value of None indicates that new socket objects have no timeout.\n\
42674273
When the socket module is first imported, the default is None.");
42684274

42694275

4276+
#ifdef HAVE_IF_NAMEINDEX
4277+
/* Python API for getting interface indices and names */
4278+
4279+
static PyObject *
4280+
socket_if_nameindex(PyObject *self, PyObject *arg)
4281+
{
4282+
int i = 0;
4283+
PyObject *list;
4284+
struct if_nameindex *ni = if_nameindex();
4285+
4286+
if (ni == NULL) {
4287+
PyErr_SetString(socket_error, "if_nameindex() returned NULL.");
4288+
return NULL;
4289+
}
4290+
4291+
list = PyList_New(0);
4292+
if (list == NULL) {
4293+
if_freenameindex(ni);
4294+
return NULL;
4295+
}
4296+
4297+
while (ni[i].if_index != 0 && i < INT_MAX) {
4298+
PyObject *ni_tuple = Py_BuildValue(
4299+
"Iy", ni[i].if_index, ni[i].if_name);
4300+
4301+
if (ni_tuple == NULL || PyList_Append(list, ni_tuple) == -1) {
4302+
Py_XDECREF(ni_tuple);
4303+
goto error;
4304+
}
4305+
Py_DECREF(ni_tuple);
4306+
4307+
++i;
4308+
}
4309+
4310+
if_freenameindex(ni);
4311+
return list;
4312+
4313+
error:
4314+
Py_DECREF(list);
4315+
if_freenameindex(ni);
4316+
return NULL;
4317+
}
4318+
4319+
PyDoc_STRVAR(if_nameindex_doc,
4320+
"if_nameindex()\n\
4321+
\n\
4322+
Returns a list of network interface information (index, name) tuples.");
4323+
4324+
4325+
PyObject*
4326+
socket_if_nametoindex(PyObject *self, PyObject *arg)
4327+
{
4328+
char* ifname = PyBytes_AsString(arg);
4329+
unsigned long index;
4330+
4331+
if (ifname == NULL)
4332+
return NULL;
4333+
4334+
index = if_nametoindex(ifname);
4335+
if (index == 0) {
4336+
PyErr_SetString(socket_error, "no interface with this name");
4337+
return NULL;
4338+
}
4339+
4340+
return PyLong_FromUnsignedLong(index);
4341+
}
4342+
4343+
PyDoc_STRVAR(if_nametoindex_doc,
4344+
"if_nametoindex(if_name)\n\
4345+
\n\
4346+
Returns the interface index corresponding to the interface name if_name.");
4347+
4348+
4349+
PyObject*
4350+
socket_if_indextoname(PyObject *self, PyObject *arg)
4351+
{
4352+
unsigned long index = PyLong_AsUnsignedLongMask(arg);
4353+
char name[IF_NAMESIZE + 1]; /* or use IFNAMSIZ ?*/
4354+
char *ret = if_indextoname(index, &name[0]);
4355+
4356+
if (ret == NULL) {
4357+
PyErr_SetString(socket_error, "no interface with this index");
4358+
return NULL;
4359+
}
4360+
4361+
return PyBytes_FromString(name);
4362+
}
4363+
4364+
PyDoc_STRVAR(if_indextoname_doc,
4365+
"if_indextoname(if_index)\n\
4366+
\n\
4367+
Returns the interface name corresponding to the interface index if_index.");
4368+
4369+
#endif /* HAVE_IF_NAMEINDEX */
4370+
4371+
42704372
/* List of functions exported by this module. */
42714373

42724374
static PyMethodDef socket_methods[] = {
@@ -4322,6 +4424,14 @@ static PyMethodDef socket_methods[] = {
43224424
METH_NOARGS, getdefaulttimeout_doc},
43234425
{"setdefaulttimeout", socket_setdefaulttimeout,
43244426
METH_O, setdefaulttimeout_doc},
4427+
#ifdef HAVE_IF_NAMEINDEX
4428+
{"if_nameindex", socket_if_nameindex,
4429+
METH_NOARGS, if_nameindex_doc},
4430+
{"if_nametoindex", socket_if_nametoindex,
4431+
METH_O, if_nametoindex_doc},
4432+
{"if_indextoname", socket_if_indextoname,
4433+
METH_O, if_indextoname_doc},
4434+
#endif
43254435
{NULL, NULL} /* Sentinel */
43264436
};
43274437

0 commit comments

Comments
 (0)