summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2020-09-24 16:00:55 +0200
committerGiampaolo Rodola <g.rodola@gmail.com>2020-09-24 16:00:55 +0200
commit271ff58460bd488bb9f538e20d44187ab63a15da (patch)
tree445d3e7bcafdb0779128fe113e8ac23a03b4e2fa
parentf9b1b5e431ecbecf76b255737d5738ba2c69c1ba (diff)
downloadpsutil-ipv6-zone-id.tar.gz
remove zone_id portion from IPv6 addressesipv6-zone-id
-rw-r--r--psutil/_psutil_posix.c14
-rwxr-xr-xpsutil/tests/test_linux.py20
2 files changed, 33 insertions, 1 deletions
diff --git a/psutil/_psutil_posix.c b/psutil/_psutil_posix.c
index 1182765d..fefee855 100644
--- a/psutil/_psutil_posix.c
+++ b/psutil/_psutil_posix.c
@@ -15,6 +15,7 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
+#include <string.h>
#ifdef PSUTIL_SUNOS10
#include "arch/solaris/v10/ifaddrs.h"
@@ -176,6 +177,7 @@ psutil_convert_ipaddr(struct sockaddr *addr, int family) {
size_t len;
const char *data;
char *ptr;
+ char *percentp;
if (addr == NULL) {
Py_INCREF(Py_None);
@@ -198,6 +200,18 @@ psutil_convert_ipaddr(struct sockaddr *addr, int family) {
return Py_None;
}
else {
+ // IPv6 addresses can have a percent symbol at the end.
+ // E.g. these 2 are equivalent:
+ // "fe80::1ff:fe23:4567:890a"
+ // "fe80::1ff:fe23:4567:890a%eth0"
+ // That is the "zone id" portion, which usually is the name
+ // of the network interface. Let's remove it (ifconfig cmd
+ // does the same).
+ if (family == AF_INET6) {
+ percentp = strchr(buf, '%');
+ if (percentp != NULL)
+ buf[percentp - buf] = '\0';
+ }
return Py_BuildValue("s", buf);
}
}
diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py
index 09461ec5..583af837 100755
--- a/psutil/tests/test_linux.py
+++ b/psutil/tests/test_linux.py
@@ -75,6 +75,23 @@ def get_ipv4_address(ifname):
struct.pack('256s', ifname))[20:24])
+def get_ipv6_address(ifname):
+ with open("/proc/net/if_inet6", 'rt') as f:
+ for line in f.readlines():
+ fields = line.split()
+ if fields[-1] == ifname:
+ break
+ else:
+ raise ValueError("could not find interface %r" % ifname)
+ unformatted = fields[0]
+ groups = []
+ for i in range(0, len(unformatted), 4):
+ groups.append(unformatted[i:i + 4])
+ formatted = ":".join(groups)
+ packed = socket.inet_pton(socket.AF_INET6, formatted)
+ return socket.inet_ntop(socket.AF_INET6, packed)
+
+
def get_mac_address(ifname):
import fcntl
ifname = ifname[:15]
@@ -890,7 +907,8 @@ class TestSystemNetIfAddrs(PsutilTestCase):
self.assertEqual(addr.address, get_mac_address(name))
elif addr.family == socket.AF_INET:
self.assertEqual(addr.address, get_ipv4_address(name))
- # TODO: test for AF_INET6 family
+ elif addr.family == socket.AF_INET6:
+ self.assertEqual(addr.address, get_ipv6_address(name))
# XXX - not reliable when having virtual NICs installed by Docker.
# @unittest.skipIf(not which('ip'), "'ip' utility not available")