From a76dfd064b9bd5eb0c6965b6e08136eb68f40fa7 Mon Sep 17 00:00:00 2001 From: David Sommerseth Date: Thu, 20 Mar 2014 19:02:54 +0100 Subject: [PATCH] Adding some extra upstream patches, until they appear in a new release Signed-off-by: David Sommerseth --- ...-extra-error-checks-with-libnl-calls.patch | 55 ++++ 0002-fix-get_module-errno-setting.patch | 69 +++++ ...ify-errno-derived-exception-handling.patch | 243 ++++++++++++++++++ ...valid-non-existing-devices-as-ENODEV.patch | 61 +++++ python-ethtool.spec | 9 + 5 files changed, 437 insertions(+) create mode 100644 0001-Added-some-extra-error-checks-with-libnl-calls.patch create mode 100644 0002-fix-get_module-errno-setting.patch create mode 100644 0004-exceptions-Simplify-errno-derived-exception-handling.patch create mode 100644 0005-Report-invalid-non-existing-devices-as-ENODEV.patch diff --git a/0001-Added-some-extra-error-checks-with-libnl-calls.patch b/0001-Added-some-extra-error-checks-with-libnl-calls.patch new file mode 100644 index 0000000..7ba2b16 --- /dev/null +++ b/0001-Added-some-extra-error-checks-with-libnl-calls.patch @@ -0,0 +1,55 @@ +From b15cd540acf49a283d30c28e1424230e51440772 Mon Sep 17 00:00:00 2001 +From: David Sommerseth +Date: Fri, 10 Jan 2014 17:57:05 +0100 +Subject: [PATCH 1/5] Added some extra error checks with libnl calls + +Signed-off-by: David Sommerseth +--- + python-ethtool/etherinfo.c | 8 ++++++-- + python-ethtool/netlink.c | 4 ++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/python-ethtool/etherinfo.c b/python-ethtool/etherinfo.c +index bac0fe7..c5e6798 100644 +--- a/python-ethtool/etherinfo.c ++++ b/python-ethtool/etherinfo.c +@@ -185,7 +185,9 @@ int get_etherinfo_link(PyEtherInfo *self) + return 0; + } + link = rtnl_link_alloc(); +- /* FIXME: Error handling? */ ++ if( !link ) { ++ return 0; ++ } + rtnl_link_set_ifindex(link, self->index); + nl_cache_foreach_filter(link_cache, OBJ_CAST(link), callback_nl_link, self); + rtnl_link_put(link); +@@ -236,7 +238,9 @@ PyObject * get_etherinfo_address(PyEtherInfo *self, nlQuery query) + return NULL; + } + addr = rtnl_addr_alloc(); +- /* FIXME: Error handling? */ ++ if( !addr ) { ++ return NULL; ++ } + rtnl_addr_set_ifindex(addr, self->index); + + switch( query ) { +diff --git a/python-ethtool/netlink.c b/python-ethtool/netlink.c +index 9ba8338..d311405 100644 +--- a/python-ethtool/netlink.c ++++ b/python-ethtool/netlink.c +@@ -57,8 +57,8 @@ int open_netlink(PyEtherInfo *ethi) + + /* No earlier connections exists, establish a new one */ + nlconnection = nl_socket_alloc(); +- nl_connect(nlconnection, NETLINK_ROUTE); +- if( (nlconnection != NULL) ) { ++ if( nlconnection != NULL ) { ++ nl_connect(nlconnection, NETLINK_ROUTE); + /* Force O_CLOEXEC flag on the NETLINK socket */ + if( fcntl(nl_socket_get_fd(nlconnection), F_SETFD, FD_CLOEXEC) == -1 ) { + fprintf(stderr, +-- +1.8.3.1 + diff --git a/0002-fix-get_module-errno-setting.patch b/0002-fix-get_module-errno-setting.patch new file mode 100644 index 0000000..2b40278 --- /dev/null +++ b/0002-fix-get_module-errno-setting.patch @@ -0,0 +1,69 @@ +From a6f163fafaccd9bea4b2807961ef8ed8776a629a Mon Sep 17 00:00:00 2001 +From: "Antoni S. Puimedon" +Date: Mon, 11 Nov 2013 15:21:26 +0000 +Subject: [PATCH 2/5] fix get_module errno setting. + +The current code is only setting the errno string but doesn't set +the first argument to the IOError exception, i.e., errno. +This patch builds a tuple (errno, strerror(errno)) so that the +Exception has the errno properly set. + +Signed-off-by: Antoni S. Puimedon +Signed-off-by: David Sommerseth +--- + python-ethtool/ethtool.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/python-ethtool/ethtool.c b/python-ethtool/ethtool.c +index 65abb21..453f08b 100644 +--- a/python-ethtool/ethtool.c ++++ b/python-ethtool/ethtool.c +@@ -450,6 +450,7 @@ static PyObject *get_module(PyObject *self __unused, PyObject *args) + + if (err < 0) { /* failed? */ + int eno = errno; ++ PyObject *err_obj; + FILE *file; + int found = 0; + char driver[101], dev[101]; +@@ -458,8 +459,11 @@ static PyObject *get_module(PyObject *self __unused, PyObject *args) + /* Before bailing, maybe it is a PCMCIA/PC Card? */ + file = fopen("/var/lib/pcmcia/stab", "r"); + if (file == NULL) { +- sprintf(buf, "[Errno %d] %s", eno, strerror(eno)); +- PyErr_SetString(PyExc_IOError, buf); ++ err_obj = Py_BuildValue("(is)", eno, strerror(eno)); ++ if (err_obj != NULL) { ++ PyErr_SetObject(PyExc_IOError, err_obj); ++ Py_DECREF(err_obj); ++ } + return NULL; + } + +@@ -480,8 +484,11 @@ static PyObject *get_module(PyObject *self __unused, PyObject *args) + } + fclose(file); + if (!found) { +- sprintf(buf, "[Errno %d] %s", eno, strerror(eno)); +- PyErr_SetString(PyExc_IOError, buf); ++ err_obj = Py_BuildValue("(is)", eno, strerror(eno)); ++ if (err_obj != NULL) { ++ PyErr_SetObject(PyExc_IOError, err_obj); ++ Py_DECREF(err_obj); ++ } + return NULL; + } else + return PyString_FromString(driver); +@@ -514,8 +521,7 @@ static PyObject *get_businfo(PyObject *self __unused, PyObject *args) + /* Open control socket. */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); +- return NULL; ++ return PyErr_SetFromErrno(PyExc_OSError); + } + + /* Get current settings. */ +-- +1.8.3.1 + diff --git a/0004-exceptions-Simplify-errno-derived-exception-handling.patch b/0004-exceptions-Simplify-errno-derived-exception-handling.patch new file mode 100644 index 0000000..a5723bd --- /dev/null +++ b/0004-exceptions-Simplify-errno-derived-exception-handling.patch @@ -0,0 +1,243 @@ +From 505bca305c4c0e2d3a29e24b27bf03c358db11cf Mon Sep 17 00:00:00 2001 +From: "Antoni S. Puimedon" +Date: Fri, 17 Jan 2014 23:27:42 +0100 +Subject: [PATCH 4/5] exceptions: Simplify errno derived exception handling + +Errnos are missing from some exceptions and in others the code could +be simplified by just using the convenience method PyErr_FromErrno. + +Signed-off-by: Antoni S. Puimedon +Acked-by: David Sommerseth +Message-Id: 1389997662-8460-1-git-send-email-asegurap@redhat.com +Signed-off-by: David Sommerseth +--- + python-ethtool/ethtool.c | 86 +++++++++++++----------------------------------- + 1 file changed, 23 insertions(+), 63 deletions(-) + +diff --git a/python-ethtool/ethtool.c b/python-ethtool/ethtool.c +index 453f08b..0f9cdbb 100644 +--- a/python-ethtool/ethtool.c ++++ b/python-ethtool/ethtool.c +@@ -55,10 +55,8 @@ static PyObject *get_active_devices(PyObject *self __unused, PyObject *args __un + PyObject *list; + struct ifaddrs *ifaddr, *ifa; + +- if (getifaddrs(&ifaddr) == -1) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); +- return NULL; +- } ++ if (getifaddrs(&ifaddr) == -1) ++ return PyErr_SetFromErrno(PyExc_OSError); + + list = PyList_New(0); + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { +@@ -83,15 +81,13 @@ static PyObject *get_devices(PyObject *self __unused, PyObject *args __unused) + FILE *fd = fopen(_PATH_PROCNET_DEV, "r"); + + if (fd == NULL) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); +- return NULL; ++ return PyErr_SetFromErrno(PyExc_OSError); + } + /* skip over first two lines */ + ret = fgets(buffer, 256, fd); + ret = fgets(buffer, 256, fd); + if( !ret ) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); +- return NULL; ++ return PyErr_SetFromErrno(PyExc_OSError); + } + + while (!feof(fd)) { +@@ -134,18 +130,13 @@ static PyObject *get_hwaddress(PyObject *self __unused, PyObject *args) + /* Open control socket. */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); +- return NULL; ++ return PyErr_SetFromErrno(PyExc_OSError); + } + + /* Get current settings. */ + err = ioctl(fd, SIOCGIFHWADDR, &ifr); + if (err < 0) { +- char buf[2048]; +- int eno = errno; +- +- snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno)); +- PyErr_SetString(PyExc_IOError, buf); ++ PyErr_SetFromErrno(PyExc_IOError); + close(fd); + return NULL; + } +@@ -181,17 +172,13 @@ static PyObject *get_ipaddress(PyObject *self __unused, PyObject *args) + /* Open control socket. */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); +- return NULL; ++ return PyErr_SetFromErrno(PyExc_OSError); + } + + /* Get current settings. */ + err = ioctl(fd, SIOCGIFADDR, &ifr); + if (err < 0) { +- char buf[2048]; +- int eno = errno; +- snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno)); +- PyErr_SetString(PyExc_IOError, buf); ++ PyErr_SetFromErrno(PyExc_IOError); + close(fd); + return NULL; + } +@@ -276,7 +263,7 @@ static PyObject *get_interfaces_info(PyObject *self __unused, PyObject *args) { + + dev = PyObject_New(PyEtherInfo, &PyEtherInfo_Type); + if( !dev ) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); ++ PyErr_SetFromErrno(PyExc_OSError); + free(fetch_devs); + return NULL; + } +@@ -311,15 +298,11 @@ static PyObject *get_flags (PyObject *self __unused, PyObject *args) + /* Open control socket. */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); +- return NULL; ++ return PyErr_SetFromErrno(PyExc_OSError); + } + err = ioctl(fd, SIOCGIFFLAGS, &ifr); + if(err < 0) { +- char buf[2048]; +- int eno = errno; +- snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno)); +- PyErr_SetString(PyExc_IOError, buf); ++ PyErr_SetFromErrno(PyExc_IOError); + close(fd); + return NULL; + } +@@ -348,17 +331,13 @@ static PyObject *get_netmask (PyObject *self __unused, PyObject *args) + /* Open control socket. */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); +- return NULL; ++ return PyErr_SetFromErrno(PyExc_OSError); + } + + /* Get current settings. */ + err = ioctl(fd, SIOCGIFNETMASK, &ifr); + if (err < 0) { +- char buf[2048]; +- int eno = errno; +- snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno)); +- PyErr_SetString(PyExc_IOError, buf); ++ PyErr_SetFromErrno(PyExc_IOError); + close(fd); + return NULL; + } +@@ -392,17 +371,13 @@ static PyObject *get_broadcast(PyObject *self __unused, PyObject *args) + /* Open control socket. */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); +- return NULL; ++ return PyErr_SetFromErrno(PyExc_OSError); + } + + /* Get current settings. */ + err = ioctl(fd, SIOCGIFBRDADDR, &ifr); + if (err < 0) { +- char buf[2048]; +- int eno = errno; +- snprintf(buf, sizeof(buf), "[Errno %d] %s", eno, strerror(eno)); +- PyErr_SetString(PyExc_IOError, buf); ++ PyErr_SetFromErrno(PyExc_IOError); + close(fd); + return NULL; + } +@@ -441,16 +416,14 @@ static PyObject *get_module(PyObject *self __unused, PyObject *args) + /* Open control socket. */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); +- return NULL; ++ return PyErr_SetFromErrno(PyExc_OSError); + } + + /* Get current settings. */ + err = ioctl(fd, SIOCETHTOOL, &ifr); + + if (err < 0) { /* failed? */ +- int eno = errno; +- PyObject *err_obj; ++ PyErr_SetFromErrno(PyExc_IOError); + FILE *file; + int found = 0; + char driver[101], dev[101]; +@@ -459,11 +432,6 @@ static PyObject *get_module(PyObject *self __unused, PyObject *args) + /* Before bailing, maybe it is a PCMCIA/PC Card? */ + file = fopen("/var/lib/pcmcia/stab", "r"); + if (file == NULL) { +- err_obj = Py_BuildValue("(is)", eno, strerror(eno)); +- if (err_obj != NULL) { +- PyErr_SetObject(PyExc_IOError, err_obj); +- Py_DECREF(err_obj); +- } + return NULL; + } + +@@ -484,14 +452,11 @@ static PyObject *get_module(PyObject *self __unused, PyObject *args) + } + fclose(file); + if (!found) { +- err_obj = Py_BuildValue("(is)", eno, strerror(eno)); +- if (err_obj != NULL) { +- PyErr_SetObject(PyExc_IOError, err_obj); +- Py_DECREF(err_obj); +- } + return NULL; +- } else ++ } else { ++ PyErr_Clear(); + return PyString_FromString(driver); ++ } + } + + close(fd); +@@ -528,11 +493,8 @@ static PyObject *get_businfo(PyObject *self __unused, PyObject *args) + err = ioctl(fd, SIOCETHTOOL, &ifr); + + if (err < 0) { /* failed? */ +- int eno = errno; ++ PyErr_SetFromErrno(PyExc_IOError); + close(fd); +- +- sprintf(buf, "[Errno %d] %s", eno, strerror(eno)); +- PyErr_SetString(PyExc_IOError, buf); + return NULL; + } + +@@ -556,16 +518,14 @@ static int send_command(int cmd, const char *devname, void *value) + /* Open control socket. */ + fd = socket(AF_INET, SOCK_DGRAM, 0), err; + if (fd < 0) { +- PyErr_SetString(PyExc_OSError, strerror(errno)); ++ PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + + /* Get current settings. */ + err = ioctl(fd, SIOCETHTOOL, &ifr); + if (err < 0) { +- char buf[2048]; +- sprintf(buf, "[Errno %d] %s", errno, strerror(errno)); +- PyErr_SetString(PyExc_IOError, buf); ++ PyErr_SetFromErrno(PyExc_IOError); + } + + close(fd); +-- +1.8.3.1 + diff --git a/0005-Report-invalid-non-existing-devices-as-ENODEV.patch b/0005-Report-invalid-non-existing-devices-as-ENODEV.patch new file mode 100644 index 0000000..043cc34 --- /dev/null +++ b/0005-Report-invalid-non-existing-devices-as-ENODEV.patch @@ -0,0 +1,61 @@ +From 3463fc5556f731aa2e29981bdb27cb50364770dd Mon Sep 17 00:00:00 2001 +From: David Sommerseth +Date: Fri, 7 Feb 2014 13:53:36 +0100 +Subject: [PATCH 5/5] Report invalid/non-existing devices as ENODEV + +Without this patch py-ethtool will just report with a very +generic system error exception if trying to query a non-existing +network interface. This patch will change this to report the +error using ENODEV instead. + +Signed-off-by: David Sommerseth +Reviewed-by: Antoni S. Puimedon +--- + python-ethtool/etherinfo.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/python-ethtool/etherinfo.c b/python-ethtool/etherinfo.c +index c5e6798..24147bc 100644 +--- a/python-ethtool/etherinfo.c ++++ b/python-ethtool/etherinfo.c +@@ -118,6 +118,9 @@ static int _set_device_index(PyEtherInfo *self) + struct nl_cache *link_cache; + struct rtnl_link *link; + ++ /* Reset errno, as we will use it to report errors further on */ ++ errno = 0; ++ + /* Find the interface index we're looking up. + * As we don't expect it to change, we're reusing a "cached" + * interface index if we have that +@@ -129,6 +132,7 @@ static int _set_device_index(PyEtherInfo *self) + + link = rtnl_link_get_by_name(link_cache, PyString_AsString(self->device)); + if( !link ) { ++ errno = ENODEV; + nl_cache_free(link_cache); + return 0; + } +@@ -177,6 +181,9 @@ int get_etherinfo_link(PyEtherInfo *self) + } + + if( _set_device_index(self) != 1) { ++ if( errno != 0 ) { ++ PyErr_SetString(PyExc_IOError, strerror(errno)); ++ } + return 0; + } + +@@ -227,6 +234,9 @@ PyObject * get_etherinfo_address(PyEtherInfo *self, nlQuery query) + } + + if( _set_device_index(self) != 1) { ++ if( errno != 0 ) { ++ return PyErr_SetFromErrno(PyExc_IOError); ++ } + return NULL; + } + +-- +1.8.3.1 + diff --git a/python-ethtool.spec b/python-ethtool.spec index d437f59..dac3dc4 100644 --- a/python-ethtool.spec +++ b/python-ethtool.spec @@ -12,6 +12,11 @@ Group: System Environment/Libraries BuildRequires: python-devel libnl3-devel asciidoc BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +Patch1: 0001-Added-some-extra-error-checks-with-libnl-calls.patch +Patch2: 0002-fix-get_module-errno-setting.patch +Patch4: 0004-exceptions-Simplify-errno-derived-exception-handling.patch +Patch5: 0005-Report-invalid-non-existing-devices-as-ENODEV.patch + %description Python bindings for the ethtool kernel interface, that allows querying and changing of Ethernet card settings, such as speed, port, auto-negotiation, and @@ -19,6 +24,10 @@ PCI locations. %prep %setup -q +%patch1 -p1 +%patch2 -p1 +%patch4 -p1 +%patch5 -p1 %build %{__python} setup.py build