summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sommerseth <davids@redhat.com>2013-09-13 20:18:57 +0200
committerDavid Sommerseth <davids@redhat.com>2013-09-13 20:18:57 +0200
commitd3f5fd74bdb903c032eca8ab4e391172d3162c76 (patch)
tree89da2c01762ecf0bb8cee3b195b36ecc329abb28
parentf8b0e05c03add3d0bd7736c3e3f81e8eb28bc7c3 (diff)
downloadpython-ethtool-d3f5fd74bdb903c032eca8ab4e391172d3162c76.tar.gz
python-ethtool-d3f5fd74bdb903c032eca8ab4e391172d3162c76.tar.xz
python-ethtool-d3f5fd74bdb903c032eca8ab4e391172d3162c76.zip
Merge PyNetlinkIPv4Address and PyNetlinkIPv6Address classes
Simplify the overall implementation by reusing code more efficiently. The differences between the IPv4 and IPv6 implementation in libnl is minimal and can more easily be differentiated those few places its needed instead. Signed-off-by: David Sommerseth <davids@redhat.com>
-rw-r--r--python-ethtool/etherinfo_obj.c42
-rw-r--r--python-ethtool/etherinfo_struct.h22
-rw-r--r--python-ethtool/ethtool.c4
-rw-r--r--python-ethtool/netlink-address.c222
4 files changed, 123 insertions, 167 deletions
diff --git a/python-ethtool/etherinfo_obj.c b/python-ethtool/etherinfo_obj.c
index 1a62fb8..a251b56 100644
--- a/python-ethtool/etherinfo_obj.c
+++ b/python-ethtool/etherinfo_obj.c
@@ -100,8 +100,7 @@ int _ethtool_etherinfo_init(etherinfo_py *self, PyObject *args, PyObject *kwds)
The return value is a *borrowed reference* (or NULL)
*/
-static PyNetlinkIPv4Address*
-get_last_address(etherinfo_py *self)
+static PyNetlinkIPaddress * get_last_ipv4_address(etherinfo_py *self)
{
Py_ssize_t size;
PyObject *list;
@@ -119,8 +118,8 @@ get_last_address(etherinfo_py *self)
size = PyList_Size(list);
if (size > 0) {
PyObject *item = PyList_GetItem(list, size - 1);
- if (Py_TYPE(item) == &ethtool_netlink_ipv4_address_Type) {
- return (PyNetlinkIPv4Address*)item;
+ if (Py_TYPE(item) == &ethtool_netlink_ip_address_Type) {
+ return (PyNetlinkIPaddress*)item;
}
}
@@ -138,7 +137,7 @@ get_last_address(etherinfo_py *self)
PyObject *_ethtool_etherinfo_getter(etherinfo_py *self, PyObject *attr_o)
{
char *attr = PyString_AsString(attr_o);
- PyNetlinkIPv4Address *py_addr;
+ PyNetlinkIPaddress *py_addr;
if( !self || !self->data ) {
PyErr_SetString(PyExc_AttributeError, "No data available");
@@ -153,24 +152,24 @@ PyObject *_ethtool_etherinfo_getter(etherinfo_py *self, PyObject *attr_o)
} else if( strcmp(attr, "ipv4_address") == 0 ) {
get_etherinfo(self->data, NLQRY_ADDR);
/* For compatiblity with old approach, return last IPv4 address: */
- py_addr = get_last_address(self);
+ py_addr = get_last_ipv4_address(self);
if (py_addr) {
- if (py_addr->ipv4_address) {
- Py_INCREF(py_addr->ipv4_address);
- return py_addr->ipv4_address;
+ if (py_addr->local) {
+ Py_INCREF(py_addr->local);
+ return py_addr->local;
}
}
Py_RETURN_NONE;
} else if( strcmp(attr, "ipv4_netmask") == 0 ) {
get_etherinfo(self->data, NLQRY_ADDR);
- py_addr = get_last_address(self);
+ py_addr = get_last_ipv4_address(self);
if (py_addr) {
- return PyInt_FromLong(py_addr->ipv4_netmask);
+ return PyInt_FromLong(py_addr->prefixlen);
}
return PyInt_FromLong(0);
} else if( strcmp(attr, "ipv4_broadcast") == 0 ) {
get_etherinfo(self->data, NLQRY_ADDR);
- py_addr = get_last_address(self);
+ py_addr = get_last_ipv4_address(self);
if (py_addr) {
if (py_addr->ipv4_broadcast) {
Py_INCREF(py_addr->ipv4_broadcast);
@@ -229,10 +228,10 @@ PyObject *_ethtool_etherinfo_str(etherinfo_py *self)
if( self->data->ethinfo->ipv4_addresses ) {
Py_ssize_t i;
for (i = 0; i < PyList_Size(self->data->ethinfo->ipv4_addresses); i++) {
- PyNetlinkIPv4Address *py_addr = (PyNetlinkIPv4Address *)PyList_GetItem(self->data->ethinfo->ipv4_addresses, i);
+ PyNetlinkIPaddress *py_addr = (PyNetlinkIPaddress *)PyList_GetItem(self->data->ethinfo->ipv4_addresses, i);
PyObject *tmp = PyString_FromFormat("\tIPv4 address: ");
- PyString_Concat(&tmp, py_addr->ipv4_address);
- PyString_ConcatAndDel(&tmp, PyString_FromFormat("/%d", py_addr->ipv4_netmask));
+ PyString_Concat(&tmp, py_addr->local);
+ PyString_ConcatAndDel(&tmp, PyString_FromFormat("/%d", py_addr->prefixlen));
if (py_addr->ipv4_broadcast ) {
PyString_ConcatAndDel(&tmp,
PyString_FromString(" Broadcast: "));
@@ -246,12 +245,12 @@ 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);
+ PyNetlinkIPaddress *py_addr = (PyNetlinkIPaddress *)PyList_GetItem(self->data->ethinfo->ipv6_addresses, i);
PyObject *tmp = PyString_FromFormat("\tIPv6 address: [");
- PyString_Concat(&tmp, py_addr->ipv6_scope);
+ PyString_Concat(&tmp, py_addr->scope);
PyString_ConcatAndDel(&tmp, PyString_FromString("] "));
- PyString_Concat(&tmp, py_addr->ipv6_address);
- PyString_ConcatAndDel(&tmp, PyString_FromFormat("/%d", py_addr->ipv6_netmask));
+ PyString_Concat(&tmp, py_addr->local);
+ PyString_ConcatAndDel(&tmp, PyString_FromFormat("/%d", py_addr->prefixlen));
PyString_ConcatAndDel(&tmp, PyString_FromString("\n"));
PyString_ConcatAndDel(&ret, tmp);
}
@@ -318,10 +317,9 @@ static PyObject *_ethtool_etherinfo_get_ipv6_addresses(etherinfo_py *self, PyObj
*/
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"},
+ "Retrieve configured IPv4 addresses. Returns a list of NetlinkIPaddress objects"},
{"get_ipv6_addresses", (PyCFunction)_ethtool_etherinfo_get_ipv6_addresses, METH_NOARGS,
- "Retrieve configured IPv6 addresses. Returns a list of NetlinkIP6Address objects"},
-
+ "Retrieve configured IPv6 addresses. Returns a list of NetlinkIPaddress objects"},
{NULL} /**< No methods defined */
};
diff --git a/python-ethtool/etherinfo_struct.h b/python-ethtool/etherinfo_struct.h
index dff1105..72e4962 100644
--- a/python-ethtool/etherinfo_struct.h
+++ b/python-ethtool/etherinfo_struct.h
@@ -39,22 +39,16 @@ struct etherinfo {
};
/* Python object containing data baked from a (struct rtnl_addr) */
-typedef struct PyNetlinkIPv4Address {
+typedef struct PyNetlinkIPaddress {
PyObject_HEAD
- PyObject *ipv4_address; /**< string: Configured IPv4 address */
- int ipv4_netmask; /**< int: Configured IPv4 netmask */
+ int family; /**< int: must be AF_INET or AF_INET6 */
+ PyObject *local; /**< string: Configured local IP address */
+ PyObject *peer; /**< string: Configured peer IP address */
PyObject *ipv4_broadcast; /**< string: Configured IPv4 broadcast address */
-} 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;
+ int prefixlen; /**< int: Configured network prefix (netmask) */
+ PyObject *scope; /**< string: IP address scope */
+} PyNetlinkIPaddress;
+extern PyTypeObject ethtool_netlink_ip_address_Type;
/**
* Contains the internal data structure of the
diff --git a/python-ethtool/ethtool.c b/python-ethtool/ethtool.c
index a471726..7e7ff1d 100644
--- a/python-ethtool/ethtool.c
+++ b/python-ethtool/ethtool.c
@@ -969,9 +969,7 @@ PyMODINIT_FUNC initethtool(void)
PyModule_AddObject(m, "etherinfo", (PyObject *)&ethtool_etherinfoType);
// 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))
+ if (PyType_Ready(&ethtool_netlink_ip_address_Type))
return;
// Setup constants
diff --git a/python-ethtool/netlink-address.c b/python-ethtool/netlink-address.c
index 95c1c86..50a96d7 100644
--- a/python-ethtool/netlink-address.c
+++ b/python-ethtool/netlink-address.c
@@ -24,135 +24,60 @@
#include "etherinfo_struct.h"
#include "etherinfo.h"
-/* IPv6 Addresses: */
+
+/* IP Address parsing: */
static PyObject *
-PyNetlinkIPv6Address_from_rtnl_addr(struct rtnl_addr *addr)
+PyNetlinkIPaddress_from_rtnl_addr(struct rtnl_addr *addr)
{
- PyNetlinkIPv6Address *py_obj;
+ PyNetlinkIPaddress *py_obj;
char buf[INET6_ADDRSTRLEN+1];
+ struct nl_addr *peer_addr = NULL, *brdcst = NULL;
- py_obj = PyObject_New(PyNetlinkIPv6Address,
- &ethtool_netlink_ipv6_address_Type);
+ py_obj = PyObject_New(PyNetlinkIPaddress,
+ &ethtool_netlink_ip_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) {
+ /* Set IP address family. Only AF_INET and AF_INET6 is supported */
+ py_obj->family = rtnl_addr_get_family(addr);
+ if (py_obj->family != AF_INET && py_obj->family != AF_INET6) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Only IPv4 (AF_INET) and IPv6 (AF_INET6) address types are supported");
goto error;
}
- /* Set ipv6_netmask: */
- py_obj->ipv6_netmask = rtnl_addr_get_prefixlen(addr);
-
-
- /* Set ipv6_scope: */
+ /* Set local IP address: */
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)
-{
- PyNetlinkIPv4Address *py_obj;
- char buf[INET_ADDRSTRLEN+1];
- struct nl_addr *brdcst;
-
- py_obj = PyObject_New(PyNetlinkIPv4Address,
- &ethtool_netlink_ipv4_address_Type);
- if (!py_obj) {
- return NULL;
- }
-
- /* Set ipv4_address: */
- memset(&buf, 0, sizeof(buf));
- if (!inet_ntop(AF_INET, nl_addr_get_binary_addr(rtnl_addr_get_local(addr)),
+ if (!inet_ntop(py_obj->family, nl_addr_get_binary_addr(rtnl_addr_get_local(addr)),
buf, sizeof(buf))) {
PyErr_SetFromErrno(PyExc_RuntimeError);
goto error;
}
- py_obj->ipv4_address = PyString_FromString(buf);
- if (!py_obj->ipv4_address) {
+ py_obj->local = PyString_FromString(buf);
+ if (!py_obj->local) {
goto error;
}
- /* Set ipv4_netmask: */
- py_obj->ipv4_netmask = rtnl_addr_get_prefixlen(addr);
+ /* Set peer IP address: */
+ memset(&buf, 0, sizeof(buf));
+ if ((peer_addr = rtnl_addr_get_peer(addr))) {
+ nl_addr2str(peer_addr, buf, sizeof(buf));
+ py_obj->peer = PyString_FromString(buf);
+ if (!py_obj->local) {
+ goto error;
+ }
+ } else {
+ py_obj->peer = NULL;
+ }
+
+ /* Set IP address prefix length (netmask): */
+ py_obj->prefixlen = rtnl_addr_get_prefixlen(addr);
/* Set ipv4_broadcast: */
py_obj->ipv4_broadcast = NULL;
brdcst = rtnl_addr_get_broadcast(addr);
- if( brdcst ) {
+ if( py_obj->family == AF_INET && brdcst ) {
memset(&buf, 0, sizeof(buf));
if (!inet_ntop(AF_INET, nl_addr_get_binary_addr(brdcst),
buf, sizeof(buf))) {
@@ -165,6 +90,11 @@ PyNetlinkIPv4Address_from_rtnl_addr(struct rtnl_addr *addr)
}
}
+ /* Set IP address scope: */
+ memset(&buf, 0, sizeof(buf));
+ rtnl_scope2str(rtnl_addr_get_scope(addr), buf, sizeof(buf));
+ py_obj->scope = PyString_FromString(buf);
+
return (PyObject*)py_obj;
error:
@@ -173,10 +103,12 @@ PyNetlinkIPv4Address_from_rtnl_addr(struct rtnl_addr *addr)
}
static void
-netlink_ipv4_address_dealloc(PyNetlinkIPv4Address *obj)
+netlink_ip_address_dealloc(PyNetlinkIPaddress *obj)
{
- Py_DECREF(obj->ipv4_address);
+ Py_DECREF(obj->local);
+ Py_XDECREF(obj->peer);
Py_XDECREF(obj->ipv4_broadcast);
+ Py_XDECREF(obj->scope);
/* We can call PyObject_Del directly rather than calling through
tp_free since the type is not subtypable (Py_TPFLAGS_BASETYPE is
@@ -185,51 +117,87 @@ netlink_ipv4_address_dealloc(PyNetlinkIPv4Address *obj)
}
static PyObject*
-netlink_ipv4_address_repr(PyNetlinkIPv4Address *obj)
+netlink_ip_address_repr(PyNetlinkIPaddress *obj)
{
- PyObject *result = PyString_FromString("ethtool.NetlinkIPv4Address(address='");
- PyString_Concat(&result, obj->ipv4_address);
+ PyObject *result = PyString_FromString("ethtool.NetlinkIPaddress(family=");
+ char buf[256];
+
+ memset(&buf, 0, sizeof(buf));
+ nl_af2str(obj->family, buf, sizeof(buf));
PyString_ConcatAndDel(&result,
- PyString_FromFormat("', netmask=%d",
- obj->ipv4_netmask));
- if (obj->ipv4_broadcast) {
+ PyString_FromFormat("%s, address='", buf));
+ PyString_Concat(&result, obj->local);
+
+ if (obj->family == AF_INET) {
+ PyString_ConcatAndDel(&result,
+ PyString_FromFormat("', netmask=%d",
+ obj->prefixlen));
+ } else if (obj->family == AF_INET6) {
+ PyString_ConcatAndDel(&result,
+ PyString_FromFormat("/%d'",
+ obj->prefixlen));
+ }
+
+ if (obj->peer) {
+ PyString_ConcatAndDel(&result, PyString_FromString(", peer_address='"));
+ PyString_Concat(&result, obj->peer);
+ PyString_ConcatAndDel(&result, PyString_FromString("'"));
+ }
+
+ if (obj->family == AF_INET && obj->ipv4_broadcast) {
PyString_ConcatAndDel(&result, PyString_FromString(", broadcast='"));
PyString_Concat(&result, obj->ipv4_broadcast);
PyString_ConcatAndDel(&result, PyString_FromString("'"));
}
+
+ PyString_ConcatAndDel(&result, PyString_FromString(", scope="));
+ PyString_Concat(&result, obj->scope);
+
PyString_ConcatAndDel(&result, PyString_FromString(")"));
+
return result;
}
-static PyMemberDef _ethtool_netlink_ipv4_address_members[] = {
+
+static PyMemberDef _ethtool_netlink_ip_address_members[] = {
{"address",
T_OBJECT_EX,
- offsetof(PyNetlinkIPv4Address, ipv4_address),
+ offsetof(PyNetlinkIPaddress, local),
+ 0,
+ NULL},
+ {"peer_address",
+ T_OBJECT_EX,
+ offsetof(PyNetlinkIPaddress, peer),
0,
NULL},
{"netmask",
T_INT,
- offsetof(PyNetlinkIPv4Address, ipv4_netmask),
+ offsetof(PyNetlinkIPaddress, prefixlen),
0,
NULL},
{"broadcast",
T_OBJECT, /* can be NULL */
- offsetof(PyNetlinkIPv4Address, ipv4_broadcast),
+ offsetof(PyNetlinkIPaddress, ipv4_broadcast),
+ 0,
+ NULL},
+ {"scope",
+ T_OBJECT_EX,
+ offsetof(PyNetlinkIPaddress, scope),
0,
NULL},
{NULL} /* End of member list */
};
-PyTypeObject ethtool_netlink_ipv4_address_Type = {
+PyTypeObject ethtool_netlink_ip_address_Type = {
PyVarObject_HEAD_INIT(0, 0)
- .tp_name = "ethtool.NetlinkIPv4Address",
- .tp_basicsize = sizeof(PyNetlinkIPv4Address),
- .tp_dealloc = (destructor)netlink_ipv4_address_dealloc,
- .tp_repr = (reprfunc)netlink_ipv4_address_repr,
- .tp_members = _ethtool_netlink_ipv4_address_members,
+ .tp_name = "ethtool.NetlinkIPaddress",
+ .tp_basicsize = sizeof(PyNetlinkIPaddress),
+ .tp_dealloc = (destructor)netlink_ip_address_dealloc,
+ .tp_repr = (reprfunc)netlink_ip_address_repr,
+ .tp_members = _ethtool_netlink_ip_address_members,
};
-/* Factory function, in case we want to generalize this to add IPv6 support */
+
PyObject *
make_python_address_from_rtnl_addr(struct rtnl_addr *addr)
{
@@ -238,10 +206,8 @@ make_python_address_from_rtnl_addr(struct rtnl_addr *addr)
switch( rtnl_addr_get_family(addr) ) {
case AF_INET:
- return PyNetlinkIPv4Address_from_rtnl_addr(addr);
-
case AF_INET6:
- return PyNetlinkIPv6Address_from_rtnl_addr(addr);
+ return PyNetlinkIPaddress_from_rtnl_addr(addr);
default:
return PyErr_SetFromErrno(PyExc_RuntimeError);