Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

663 ptp ifaces #668

Merged
merged 4 commits into from
Aug 5, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Bug tracker at https://github.com/giampaolo/psutil/issues
**Enhancements**

- #648: CI test integration for OSX. (patch by Jeff Tang)
- #663: net_if_addrs() now returns point-to-point addresses (for VPNs).

**Bug fixes**

Expand Down
12 changes: 6 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,12 @@ Network
...]
>>>
>>> psutil.net_if_addrs()
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1'),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]}
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
>>>
>>> psutil.net_if_stats()
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
Expand Down
23 changes: 15 additions & 8 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -410,28 +410,33 @@ Network
Return the addresses associated to each NIC (network interface card)
installed on the system as a dictionary whose keys are the NIC names and
value is a list of namedtuples for each address assigned to the NIC.
Each namedtuple includes 4 fields:
Each namedtuple includes 5 fields:

- **family**
- **address**
- **netmask**
- **broadcast**
- **ptp**

*family* can be either
`AF_INET <http://docs.python.org//library/socket.html#socket.AF_INET>`__,
`AF_INET6 <http://docs.python.org//library/socket.html#socket.AF_INET6>`__
or :const:`psutil.AF_LINK`, which refers to a MAC address.
*address* is the primary address, *netmask* and *broadcast* may be ``None``.
*address* is the primary address and it is always set.
*netmask*, *broadcast* and *ptp* may be ``None``.
*ptp* stands for "point to point" and references the destination address on a
point to point interface (tipically a VPN).
*broadcast* and *ptp* are mutually exclusive.
Example::

>>> import psutil
>>> psutil.net_if_addrs()
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1'),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]}
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
>>>

See also `examples/ifconfig.py <https://github.com/giampaolo/psutil/blob/master/examples/ifconfig.py>`__
Expand All @@ -446,6 +451,8 @@ Network

*New in 3.0.0*

*Changed in 3.1.2:* *ptp* field was added.

.. function:: net_if_stats()

Return information about each NIC (network interface card) installed on the
Expand Down
2 changes: 2 additions & 0 deletions examples/ifconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ def main():
print(" broadcast : %s" % addr.broadcast)
if addr.netmask:
print(" netmask : %s" % addr.netmask)
if addr.ptp:
print(" p2p : %s" % addr.ptp)
print("")


Expand Down
15 changes: 10 additions & 5 deletions psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1749,17 +1749,22 @@ def net_if_addrs():
"""Return the addresses associated to each NIC (network interface
card) installed on the system as a dictionary whose keys are the
NIC names and value is a list of namedtuples for each address
assigned to the NIC. Each namedtuple includes 4 fields:
assigned to the NIC. Each namedtuple includes 5 fields:

- family
- address
- netmask
- broadcast
- ptp

'family' can be either socket.AF_INET, socket.AF_INET6 or
psutil.AF_LINK, which refers to a MAC address.
'address' is the primary address, 'netmask' and 'broadcast'
may be None.
'address' is the primary address and it is always set.
'netmask' and 'broadcast' and 'ptp' may be None.
'ptp' stands for "point to point" and references the destination
address on a point to point interface (tipically a VPN).
'broadcast' and 'ptp' are mutually exclusive.

Note: you can have more than one address of the same family
associated with each interface.
"""
Expand All @@ -1769,7 +1774,7 @@ def net_if_addrs():
rawlist = _psplatform.net_if_addrs()
rawlist.sort(key=lambda x: x[1]) # sort by family
ret = collections.defaultdict(list)
for name, fam, addr, mask, broadcast in rawlist:
for name, fam, addr, mask, broadcast, ptp in rawlist:
if has_enums:
try:
fam = socket.AddressFamily(fam)
Expand All @@ -1782,7 +1787,7 @@ def net_if_addrs():
# We re-set the family here so that repr(family)
# will show AF_LINK rather than AF_PACKET
fam = _psplatform.AF_LINK
ret[name].append(_common.snic(fam, addr, mask, broadcast))
ret[name].append(_common.snic(fam, addr, mask, broadcast, ptp))
return dict(ret)


Expand Down
2 changes: 1 addition & 1 deletion psutil/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def socktype_to_enum(num):
sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr',
'status', 'pid'])
# psutil.net_if_addrs()
snic = namedtuple('snic', ['family', 'address', 'netmask', 'broadcast'])
snic = namedtuple('snic', ['family', 'address', 'netmask', 'broadcast', 'ptp'])
# psutil.net_if_stats()
snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu'])

Expand Down
34 changes: 26 additions & 8 deletions psutil/_psutil_posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if.h>

#ifdef __linux
#include <netdb.h>
Expand Down Expand Up @@ -163,6 +164,7 @@ psutil_net_if_addrs(PyObject* self, PyObject* args)
PyObject *py_address = NULL;
PyObject *py_netmask = NULL;
PyObject *py_broadcast = NULL;
PyObject *py_ptp = NULL;

if (py_retlist == NULL)
return NULL;
Expand All @@ -185,20 +187,34 @@ psutil_net_if_addrs(PyObject* self, PyObject* args)
py_netmask = psutil_convert_ipaddr(ifa->ifa_netmask, family);
if (py_netmask == NULL)
goto error;
#ifdef __linux
py_broadcast = psutil_convert_ipaddr(ifa->ifa_ifu.ifu_broadaddr, family);
#else
py_broadcast = psutil_convert_ipaddr(ifa->ifa_broadaddr, family);
#endif
if (py_broadcast == NULL)

if (ifa->ifa_flags & IFF_BROADCAST) {
py_broadcast = psutil_convert_ipaddr(ifa->ifa_broadaddr, family);
Py_INCREF(Py_None);
py_ptp = Py_None;
}
else if (ifa->ifa_flags & IFF_POINTOPOINT) {
py_ptp = psutil_convert_ipaddr(ifa->ifa_dstaddr, family);
Py_INCREF(Py_None);
py_broadcast = Py_None;
}
else {
Py_INCREF(Py_None);
Py_INCREF(Py_None);
py_broadcast = Py_None;
py_ptp = Py_None;
}

if ((py_broadcast == NULL) || (py_ptp == NULL))
goto error;
py_tuple = Py_BuildValue(
"(siOOO)",
"(siOOOO)",
ifa->ifa_name,
family,
py_address,
py_netmask,
py_broadcast
py_broadcast,
py_ptp
);

if (! py_tuple)
Expand All @@ -209,6 +225,7 @@ psutil_net_if_addrs(PyObject* self, PyObject* args)
Py_DECREF(py_address);
Py_DECREF(py_netmask);
Py_DECREF(py_broadcast);
Py_DECREF(py_ptp);
}

freeifaddrs(ifaddr);
Expand All @@ -222,6 +239,7 @@ psutil_net_if_addrs(PyObject* self, PyObject* args)
Py_XDECREF(py_address);
Py_XDECREF(py_netmask);
Py_XDECREF(py_broadcast);
Py_XDECREF(py_ptp);
return NULL;
}

Expand Down
8 changes: 7 additions & 1 deletion test/test_psutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -1069,13 +1069,19 @@ def test_net_if_addrs(self):
s = socket.socket(af, socktype, proto)
with contextlib.closing(s):
s.bind(sa)
for ip in (addr.address, addr.netmask, addr.broadcast):
for ip in (addr.address, addr.netmask, addr.broadcast,
addr.ptp):
if ip is not None:
# TODO: skip AF_INET6 for now because I get:
# AddressValueError: Only hex digits permitted in
# u'c6f3%lxcbr0' in u'fe80::c8e0:fff:fe54:c6f3%lxcbr0'
if addr.family != AF_INET6:
check_ip_address(ip, addr.family)
# broadcast and ptp addresses are mutually exclusive
if addr.broadcast:
self.assertIsNone(addr.ptp)
elif addr.ptp:
self.assertIsNone(addr.broadcast)

if BSD or OSX or SUNOS:
if hasattr(socket, "AF_LINK"):
Expand Down