/* * Copyright (C) 2011 - 2013 Red Hat Inc. * * David Malcolm * * This application is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; version 2. * * This application is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. */ /* Python object corresponding to a (struct rtnl_addr) */ #include #include "structmember.h" #include #include #include #include #include "etherinfo_struct.h" #include "etherinfo.h" /* IP Address parsing: */ static PyObject * PyNetlinkIPaddress_from_rtnl_addr(struct rtnl_addr *addr) { PyNetlinkIPaddress *py_obj; char buf[INET6_ADDRSTRLEN+1]; struct nl_addr *peer_addr = NULL, *brdcst = NULL; py_obj = PyObject_New(PyNetlinkIPaddress, ðtool_netlink_ip_address_Type); if (!py_obj) { return NULL; } /* 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 local IP address: */ memset(&buf, 0, sizeof(buf)); 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->local = PyString_FromString(buf); if (!py_obj->local) { goto error; } /* 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( 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))) { PyErr_SetFromErrno(PyExc_RuntimeError); goto error; } py_obj->ipv4_broadcast = PyString_FromString(buf); if (!py_obj->ipv4_broadcast) { goto error; } } /* 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: Py_DECREF(py_obj); return NULL; } static void netlink_ip_address_dealloc(PyNetlinkIPaddress *obj) { 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 not set): */ PyObject_Del(obj); } static PyObject* netlink_ip_address_repr(PyNetlinkIPaddress *obj) { 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("%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_ip_address_members[] = { {"address", T_OBJECT_EX, offsetof(PyNetlinkIPaddress, local), 0, NULL}, {"peer_address", T_OBJECT_EX, offsetof(PyNetlinkIPaddress, peer), 0, NULL}, {"netmask", T_INT, offsetof(PyNetlinkIPaddress, prefixlen), 0, NULL}, {"broadcast", T_OBJECT, /* can be NULL */ offsetof(PyNetlinkIPaddress, ipv4_broadcast), 0, NULL}, {"scope", T_OBJECT_EX, offsetof(PyNetlinkIPaddress, scope), 0, NULL}, {NULL} /* End of member list */ }; PyTypeObject ethtool_netlink_ip_address_Type = { PyVarObject_HEAD_INIT(0, 0) .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, }; PyObject * make_python_address_from_rtnl_addr(struct rtnl_addr *addr) { assert(addr); switch( rtnl_addr_get_family(addr) ) { case AF_INET: case AF_INET6: return PyNetlinkIPaddress_from_rtnl_addr(addr); default: return PyErr_SetFromErrno(PyExc_RuntimeError); } } /* Local variables: c-basic-offset: 8 indent-tabs-mode: y End: */