diff options
-rw-r--r-- | python-ethtool/etherinfo_obj.c | 42 | ||||
-rw-r--r-- | python-ethtool/etherinfo_struct.h | 22 | ||||
-rw-r--r-- | python-ethtool/ethtool.c | 4 | ||||
-rw-r--r-- | python-ethtool/netlink-address.c | 222 |
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) == ðtool_netlink_ipv4_address_Type) { - return (PyNetlinkIPv4Address*)item; + if (Py_TYPE(item) == ðtool_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 *)ðtool_etherinfoType); // Prepare the ethtool IPv6 and IPv4 address types - if (PyType_Ready(ðtool_netlink_ipv6_address_Type) < 0) - return; - if (PyType_Ready(ðtool_netlink_ipv4_address_Type)) + if (PyType_Ready(ðtool_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, - ðtool_netlink_ipv6_address_Type); + py_obj = PyObject_New(PyNetlinkIPaddress, + ðtool_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, - ðtool_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); |