summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sommerseth <davids@redhat.com>2013-09-13 18:46:15 +0200
committerDavid Sommerseth <davids@redhat.com>2013-09-13 18:49:10 +0200
commit052d432d9be11a0b6b69826b540b03d1b80904a4 (patch)
tree32a44b8c6b40c62e3be372141796987b34328804
parentabab733a87025960acee7dd0a2c029e679a502a8 (diff)
downloadpython-ethtool-052d432d9be11a0b6b69826b540b03d1b80904a4.tar.gz
python-ethtool-052d432d9be11a0b6b69826b540b03d1b80904a4.tar.xz
python-ethtool-052d432d9be11a0b6b69826b540b03d1b80904a4.zip
Re-implement the IPv6 support
This uses the same approach as IPv4 uses. Signed-off-by: David Sommerseth <davids@redhat.com>
-rw-r--r--python-ethtool/etherinfo.c32
-rw-r--r--python-ethtool/etherinfo_obj.c57
-rw-r--r--python-ethtool/etherinfo_struct.h10
-rw-r--r--python-ethtool/ethtool.c4
-rw-r--r--python-ethtool/netlink-address.c104
5 files changed, 194 insertions, 13 deletions
diff --git a/python-ethtool/etherinfo.c b/python-ethtool/etherinfo.c
index 538bcb5..c8bbb0f 100644
--- a/python-ethtool/etherinfo.c
+++ b/python-ethtool/etherinfo.c
@@ -78,6 +78,7 @@ void free_etherinfo(struct etherinfo *ptr)
free(ptr->hwaddress);
}
Py_XDECREF(ptr->ipv4_addresses);
+ Py_XDECREF(ptr->ipv6_addresses);
free(ptr);
}
@@ -117,6 +118,7 @@ append_object_for_netlink_address(struct etherinfo *ethi,
assert(ethi);
assert(ethi->ipv4_addresses);
+ assert(ethi->ipv6_addresses);
assert(addr);
addr_obj = make_python_address_from_rtnl_addr(addr);
@@ -124,11 +126,24 @@ append_object_for_netlink_address(struct etherinfo *ethi,
return -1;
}
- if (-1 == PyList_Append(ethi->ipv4_addresses, addr_obj)) {
- Py_DECREF(addr_obj);
- return -1;
- }
+ switch (rtnl_addr_get_family(addr)) {
+ case AF_INET:
+ if (-1 == PyList_Append(ethi->ipv4_addresses, addr_obj)) {
+ Py_DECREF(addr_obj);
+ return -1;
+ }
+ break;
+
+ case AF_INET6:
+ if (-1 == PyList_Append(ethi->ipv6_addresses, addr_obj)) {
+ Py_DECREF(addr_obj);
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
Py_DECREF(addr_obj);
/* Success */
@@ -153,6 +168,7 @@ static void callback_nl_address(struct nl_object *obj, void *arg)
switch( rtnl_addr_get_family(rtaddr) ) {
case AF_INET:
+ case AF_INET6:
append_object_for_netlink_address(ethi, rtaddr);
return;
default:
@@ -168,7 +184,6 @@ static void callback_nl_address(struct nl_object *obj, void *arg)
*
*/
-
/**
* Query NETLINK for ethernet configuration
*
@@ -252,6 +267,13 @@ int get_etherinfo(struct etherinfo_obj_data *data, nlQuery query)
return 0;
}
+ /* Likewise for IPv6 addresses: */
+ Py_XDECREF(ethinf->ipv6_addresses);
+ ethinf->ipv6_addresses = PyList_New(0);
+ if (!ethinf->ipv6_addresses) {
+ return 0;
+ }
+
/* Retrieve all address information */
nl_cache_foreach_filter(addr_cache, OBJ_CAST(addr), callback_nl_address, ethinf);
rtnl_addr_put(addr);
diff --git a/python-ethtool/etherinfo_obj.c b/python-ethtool/etherinfo_obj.c
index c6ebacc..1a62fb8 100644
--- a/python-ethtool/etherinfo_obj.c
+++ b/python-ethtool/etherinfo_obj.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2011 Red Hat Inc.
+ * Copyright (C) 2009-2013 Red Hat Inc.
*
* David Sommerseth <davids@redhat.com>
*
@@ -27,6 +27,7 @@
#include "structmember.h"
#include <netlink/route/rtnl.h>
+#include <netlink/route/addr.h>
#include "etherinfo_struct.h"
#include "etherinfo.h"
@@ -242,11 +243,32 @@ PyObject *_ethtool_etherinfo_str(etherinfo_py *self)
}
}
+ if( self->data->ethinfo->ipv6_addresses ) {
+ Py_ssize_t i;
+ for (i = 0; i < PyList_Size(self->data->ethinfo->ipv6_addresses); i++) {
+ PyNetlinkIPv6Address *py_addr = (PyNetlinkIPv6Address *)PyList_GetItem(self->data->ethinfo->ipv6_addresses, i);
+ PyObject *tmp = PyString_FromFormat("\tIPv6 address: [");
+ PyString_Concat(&tmp, py_addr->ipv6_scope);
+ PyString_ConcatAndDel(&tmp, PyString_FromString("] "));
+ PyString_Concat(&tmp, py_addr->ipv6_address);
+ PyString_ConcatAndDel(&tmp, PyString_FromFormat("/%d", py_addr->ipv6_netmask));
+ PyString_ConcatAndDel(&tmp, PyString_FromString("\n"));
+ PyString_ConcatAndDel(&ret, tmp);
+ }
+ }
+
return ret;
}
-static PyObject *
-_ethtool_etherinfo_get_ipv4_addresses(etherinfo_py *self, PyObject *notused) {
+/**
+ * Returns a tuple list of configured IPv4 addresses
+ *
+ * @param self
+ * @param notused
+ *
+ * @return Returns a Python tuple list of NetlinkIP4Address objects
+ */
+static PyObject *_ethtool_etherinfo_get_ipv4_addresses(etherinfo_py *self, PyObject *notused) {
PyObject *ret;
if( !self || !self->data ) {
@@ -265,12 +287,41 @@ _ethtool_etherinfo_get_ipv4_addresses(etherinfo_py *self, PyObject *notused) {
/**
+ * Returns a tuple list of configured IPv4 addresses
+ *
+ * @param self
+ * @param notused
+ *
+ * @return Returns a Python tuple list of NetlinkIP6Address objects
+ */
+static PyObject *_ethtool_etherinfo_get_ipv6_addresses(etherinfo_py *self, PyObject *notused) {
+ PyObject *ret;
+
+ if( !self || !self->data ) {
+ PyErr_SetString(PyExc_AttributeError, "No data available");
+ return NULL;
+ }
+
+ get_etherinfo(self->data, NLQRY_ADDR);
+
+ /* Transfer ownership of reference: */
+ ret = self->data->ethinfo->ipv6_addresses;
+ self->data->ethinfo->ipv6_addresses = NULL;
+
+ return ret;
+}
+
+
+/**
* Defines all available methods in the ethtool.etherinfo class
*
*/
static PyMethodDef _ethtool_etherinfo_methods[] = {
{"get_ipv4_addresses", (PyCFunction)_ethtool_etherinfo_get_ipv4_addresses, METH_NOARGS,
"Retrieve configured IPv4 addresses. Returns a list of NetlinkIP4Address objects"},
+ {"get_ipv6_addresses", (PyCFunction)_ethtool_etherinfo_get_ipv6_addresses, METH_NOARGS,
+ "Retrieve configured IPv6 addresses. Returns a list of NetlinkIP6Address objects"},
+
{NULL} /**< No methods defined */
};
diff --git a/python-ethtool/etherinfo_struct.h b/python-ethtool/etherinfo_struct.h
index 6ae4d78..dff1105 100644
--- a/python-ethtool/etherinfo_struct.h
+++ b/python-ethtool/etherinfo_struct.h
@@ -35,6 +35,7 @@ struct etherinfo {
int index; /**< NETLINK index reference */
char *hwaddress; /**< HW address / MAC address of device */
PyObject *ipv4_addresses; /**< list of PyNetlinkIPv4Address instances */
+ PyObject *ipv6_addresses; /**< list of PyNetlinkIPv6Addresses instances */
};
/* Python object containing data baked from a (struct rtnl_addr) */
@@ -46,6 +47,15 @@ typedef struct PyNetlinkIPv4Address {
} PyNetlinkIPv4Address;
extern PyTypeObject ethtool_netlink_ipv4_address_Type;
+/* Python object containing data baked from a (struct rtnl_addr) */
+typedef struct PyNetlinkIPv6Address {
+ PyObject_HEAD
+ PyObject *ipv6_address; /**< string: Configured IPv6 address */
+ int ipv6_netmask; /**< int: Configured IPv6 prefix */
+ PyObject *ipv6_scope; /**< string: IPv6 address scope */
+} PyNetlinkIPv6Address;
+extern PyTypeObject ethtool_netlink_ipv6_address_Type;
+
/**
* Contains the internal data structure of the
* ethtool.etherinfo object.
diff --git a/python-ethtool/ethtool.c b/python-ethtool/ethtool.c
index 4701308..e58d5f9 100644
--- a/python-ethtool/ethtool.c
+++ b/python-ethtool/ethtool.c
@@ -962,7 +962,9 @@ PyMODINIT_FUNC initethtool(void)
Py_INCREF(&ethtool_etherinfoType);
PyModule_AddObject(m, "etherinfo", (PyObject *)&ethtool_etherinfoType);
- // Prepare the ethtool IPv4 address types
+ // Prepare the ethtool IPv6 and IPv4 address types
+ if (PyType_Ready(&ethtool_netlink_ipv6_address_Type) < 0)
+ return;
if (PyType_Ready(&ethtool_netlink_ipv4_address_Type))
return;
diff --git a/python-ethtool/netlink-address.c b/python-ethtool/netlink-address.c
index 35c0849..95c1c86 100644
--- a/python-ethtool/netlink-address.c
+++ b/python-ethtool/netlink-address.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012 Red Hat Inc.
+ * Copyright (C) 2011 - 2013 Red Hat Inc.
*
* David Malcolm <dmalcolm@redhat.com>
*
@@ -20,9 +20,106 @@
#include <arpa/inet.h>
#include <netlink/addr.h>
#include <netlink/route/addr.h>
+#include <netlink/route/rtnl.h>
#include "etherinfo_struct.h"
#include "etherinfo.h"
+/* IPv6 Addresses: */
+static PyObject *
+PyNetlinkIPv6Address_from_rtnl_addr(struct rtnl_addr *addr)
+{
+ PyNetlinkIPv6Address *py_obj;
+ char buf[INET6_ADDRSTRLEN+1];
+
+ py_obj = PyObject_New(PyNetlinkIPv6Address,
+ &ethtool_netlink_ipv6_address_Type);
+ if (!py_obj) {
+ return NULL;
+ }
+
+ /* Set ipv6_address: */
+ memset(&buf, 0, sizeof(buf));
+ if (!inet_ntop(AF_INET6, nl_addr_get_binary_addr(rtnl_addr_get_local(addr)),
+ buf, sizeof(buf))) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto error;
+ }
+ py_obj->ipv6_address = PyString_FromString(buf);
+ if (!py_obj->ipv6_address) {
+ goto error;
+ }
+
+ /* Set ipv6_netmask: */
+ py_obj->ipv6_netmask = rtnl_addr_get_prefixlen(addr);
+
+
+ /* Set ipv6_scope: */
+ memset(&buf, 0, sizeof(buf));
+ rtnl_scope2str(rtnl_addr_get_scope(addr), buf, sizeof(buf));
+ py_obj->ipv6_scope = PyString_FromString(buf);
+
+ return (PyObject*)py_obj;
+
+ error:
+ Py_DECREF(py_obj);
+ return NULL;
+}
+
+static void
+netlink_ipv6_address_dealloc(PyNetlinkIPv6Address *obj)
+{
+ Py_DECREF(obj->ipv6_address);
+ Py_DECREF(obj->ipv6_scope);
+
+ /* We can call PyObject_Del directly rather than calling through
+ tp_free since the type is not subtypable (Py_TPFLAGS_BASETYPE is
+ not set): */
+ PyObject_Del(obj);
+}
+
+static PyObject*
+netlink_ipv6_address_repr(PyNetlinkIPv6Address *obj)
+{
+ PyObject *result = PyString_FromString("ethtool.NetlinkIPv6Address(address='");
+ PyString_Concat(&result, obj->ipv6_address);
+ PyString_ConcatAndDel(&result,
+ PyString_FromFormat("/%d', scope=",
+ obj->ipv6_netmask));
+ PyString_Concat(&result, obj->ipv6_scope);
+ PyString_ConcatAndDel(&result, PyString_FromString(")"));
+ return result;
+}
+
+static PyMemberDef _ethtool_netlink_ipv6_address_members[] = {
+ {"address",
+ T_OBJECT_EX,
+ offsetof(PyNetlinkIPv6Address, ipv6_address),
+ 0,
+ NULL},
+ {"netmask",
+ T_INT,
+ offsetof(PyNetlinkIPv6Address, ipv6_netmask),
+ 0,
+ NULL},
+ {"scope",
+ T_OBJECT_EX,
+ offsetof(PyNetlinkIPv6Address, ipv6_scope),
+ 0,
+ NULL},
+ {NULL} /* End of member list */
+};
+
+PyTypeObject ethtool_netlink_ipv6_address_Type = {
+ PyVarObject_HEAD_INIT(0, 0)
+ .tp_name = "ethtool.NetlinkIPv6Address",
+ .tp_basicsize = sizeof(PyNetlinkIPv6Address),
+ .tp_dealloc = (destructor)netlink_ipv6_address_dealloc,
+ .tp_repr = (reprfunc)netlink_ipv6_address_repr,
+ .tp_members = _ethtool_netlink_ipv6_address_members,
+};
+
+
+
/* IPv4 Addresses: */
static PyObject *
PyNetlinkIPv4Address_from_rtnl_addr(struct rtnl_addr *addr)
@@ -143,9 +240,8 @@ make_python_address_from_rtnl_addr(struct rtnl_addr *addr)
case AF_INET:
return PyNetlinkIPv4Address_from_rtnl_addr(addr);
- /*
- For now, we just support IPv4 addresses.
- */
+ case AF_INET6:
+ return PyNetlinkIPv6Address_from_rtnl_addr(addr);
default:
return PyErr_SetFromErrno(PyExc_RuntimeError);