summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);