|
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from pyroute2.common import map_namespace
|
|
from pyroute2.netlink import genlmsg
|
|
from pyroute2.netlink.generic import GenericNetlinkSocket
|
|
from pyroute2.netlink.nlsocket import Marshal
|
|
from pyroute2.netlink import NLM_F_REQUEST
|
|
from pyroute2.netlink import NLM_F_DUMP
|
|
from socket import if_nametoindex
|
|
from socket import if_indextoname
|
|
|
|
|
|
BATADV_CMD_UNSPEC = 0
|
|
BATADV_CMD_GET_MESH_INFO = 1
|
|
BATADV_CMD_TP_METER = 2
|
|
BATADV_CMD_TP_METER_CANCEL = 3
|
|
BATADV_CMD_GET_ROUTING_ALGOS = 4
|
|
BATADV_CMD_GET_HARDIFS = 5
|
|
BATADV_CMD_GET_TRANSTABLE_LOCAL = 6
|
|
BATADV_CMD_GET_TRANSTABLE_GLOBAL = 7
|
|
BATADV_CMD_GET_ORIGINATORS = 8
|
|
BATADV_CMD_GET_NEIGHBORS = 9
|
|
BATADV_CMD_GET_GATEWAYS = 10
|
|
BATADV_CMD_GET_BLA_CLAIM = 11
|
|
BATADV_CMD_GET_BLA_BACKBONE = 12
|
|
BATADV_CMD_GET_DAT_CACHE = 13
|
|
BATADV_CMD_GET_MCAST_FLAGS = 14
|
|
BATADV_CMD_MAX = BATADV_CMD_GET_MCAST_FLAGS
|
|
|
|
(BATADV_NAMES, BATADV_VALUES) = map_namespace('BATADV_CMD_', globals())
|
|
|
|
|
|
class batadvcmd(genlmsg):
|
|
prefix = 'BATADV_ATTR_'
|
|
|
|
'''
|
|
Message class that will be used to communicate
|
|
with the kernel module
|
|
'''
|
|
nla_map = (('BATADV_ATTR_UNSPEC', 'none'),
|
|
('BATADV_ATTR_VERSION', 'asciiz'),
|
|
('BATADV_ATTR_ALGO_NAME', 'asciiz'),
|
|
('BATADV_ATTR_MESH_IFINDEX', 'uint32'),
|
|
('BATADV_ATTR_MESH_IFNAME', 'asciiz'),
|
|
('BATADV_ATTR_MESH_ADDRESS', 'l2addr'),
|
|
('BATADV_ATTR_HARD_IFINDEX', 'uint32'),
|
|
('BATADV_ATTR_HARD_IFNAME', 'asciiz'),
|
|
('BATADV_ATTR_HARD_ADDRESS', 'l2addr'),
|
|
('BATADV_ATTR_ORIG_ADDRESS', 'l2addr'),
|
|
('BATADV_ATTR_TPMETER_RESULT', 'uint8'),
|
|
('BATADV_ATTR_TPMETER_TEST_TIME', 'uint32'),
|
|
('BATADV_ATTR_TPMETER_BYTES', 'uint64'),
|
|
('BATADV_ATTR_TPMETER_COOKIE', 'uint32'),
|
|
('BATADV_ATTR_PAD', 'none'),
|
|
('BATADV_ATTR_ACTIVE', 'flag'),
|
|
('BATADV_ATTR_TT_ADDRESS', 'l2addr'),
|
|
('BATADV_ATTR_TT_TTVN', 'uint8'),
|
|
('BATADV_ATTR_TT_LAST_TTVN', 'uint8'),
|
|
('BATADV_ATTR_TT_CRC32', 'uint32'),
|
|
('BATADV_ATTR_TT_VID', 'uint16'),
|
|
('BATADV_ATTR_TT_FLAGS', 'uint32'),
|
|
('BATADV_ATTR_FLAG_BEST', 'flag'),
|
|
('BATADV_ATTR_LAST_SEEN_MSECS', 'uint32'),
|
|
('BATADV_ATTR_NEIGH_ADDRESS', 'l2addr'),
|
|
('BATADV_ATTR_TQ', 'uint8'),
|
|
('BATADV_ATTR_THROUGHPUT', 'uint32'),
|
|
('BATADV_ATTR_BANDWIDTH_UP', 'uint32'),
|
|
('BATADV_ATTR_BANDWIDTH_DOWN', 'uint32'),
|
|
('BATADV_ATTR_ROUTER', 'l2addr'),
|
|
('BATADV_ATTR_BLA_OWN', 'flag'),
|
|
('BATADV_ATTR_BLA_ADDRESS', 'l2addr'),
|
|
('BATADV_ATTR_BLA_VID', 'uint16'),
|
|
('BATADV_ATTR_BLA_BACKBONE', 'l2addr'),
|
|
('BATADV_ATTR_BLA_CRC', 'uint16'),
|
|
('BATADV_ATTR_DAT_CACHE_IP4ADDRESS', 'ip4addr'),
|
|
('BATADV_ATTR_DAT_CACHE_HWADDRESS', 'l2addr'),
|
|
('BATADV_ATTR_DAT_CACHE_VID', 'uint16'),
|
|
('BATADV_ATTR_MCAST_FLAGS', 'uint32'),
|
|
('BATADV_ATTR_MCAST_FLAGS_PRIV', 'uint32'))
|
|
|
|
|
|
class MarshalBatadv(Marshal):
|
|
msg_map = {BATADV_CMD_UNSPEC: batadvcmd,
|
|
BATADV_CMD_GET_MESH_INFO: batadvcmd,
|
|
BATADV_CMD_TP_METER: batadvcmd,
|
|
BATADV_CMD_TP_METER_CANCEL: batadvcmd,
|
|
BATADV_CMD_GET_ROUTING_ALGOS: batadvcmd,
|
|
BATADV_CMD_GET_HARDIFS: batadvcmd,
|
|
BATADV_CMD_GET_TRANSTABLE_LOCAL: batadvcmd,
|
|
BATADV_CMD_GET_TRANSTABLE_GLOBAL: batadvcmd,
|
|
BATADV_CMD_GET_ORIGINATORS: batadvcmd,
|
|
BATADV_CMD_GET_NEIGHBORS: batadvcmd,
|
|
BATADV_CMD_GET_GATEWAYS: batadvcmd,
|
|
BATADV_CMD_GET_BLA_CLAIM: batadvcmd,
|
|
BATADV_CMD_GET_BLA_BACKBONE: batadvcmd,
|
|
BATADV_CMD_GET_DAT_CACHE: batadvcmd,
|
|
BATADV_CMD_GET_MCAST_FLAGS: batadvcmd}
|
|
|
|
|
|
class BatadvSocket(GenericNetlinkSocket):
|
|
def __init__(self):
|
|
GenericNetlinkSocket.__init__(self)
|
|
self.marshal = MarshalBatadv()
|
|
|
|
def bind(self, groups=0, **kwarg):
|
|
GenericNetlinkSocket.bind(self, 'batadv', batadvcmd,
|
|
groups, None, **kwarg)
|
|
|
|
class Batadv(BatadvSocket):
|
|
|
|
__meshif = 'bat0'
|
|
__meshif_index = 0
|
|
|
|
def __init__(self, *argv, **kwarg):
|
|
# continue with init
|
|
super(Batadv, self).__init__(*argv, **kwarg)
|
|
|
|
if 'meshif' in kwarg:
|
|
self.__meshif = kwarg.pop('meshif')
|
|
|
|
self.__meshif_index = if_nametoindex(self.__meshif)
|
|
|
|
try:
|
|
self.bind()
|
|
except:
|
|
super(Batadv, self).close()
|
|
raise
|
|
|
|
def get_neighbors(self):
|
|
msg = batadvcmd()
|
|
msg['cmd'] = BATADV_NAMES['BATADV_CMD_GET_NEIGHBORS']
|
|
msg['attrs'] = [
|
|
['BATADV_ATTR_MESH_IFINDEX', self.__meshif_index],
|
|
]
|
|
|
|
return self.nlm_request(msg,
|
|
msg_type=self.prid,
|
|
msg_flags=NLM_F_REQUEST | NLM_F_DUMP)
|
|
|
|
def get_originators(self):
|
|
msg = batadvcmd()
|
|
msg['cmd'] = BATADV_NAMES['BATADV_CMD_GET_ORIGINATORS']
|
|
msg['attrs'] = [
|
|
['BATADV_ATTR_MESH_IFINDEX', self.__meshif_index],
|
|
]
|
|
|
|
return self.nlm_request(msg,
|
|
msg_type=self.prid,
|
|
msg_flags=NLM_F_REQUEST | NLM_F_DUMP)
|
|
|
|
def main():
|
|
batadv = Batadv()
|
|
|
|
orig2tq = {}
|
|
for q in batadv.get_originators():
|
|
tq = q.get_attr('BATADV_ATTR_TQ')
|
|
if not tq:
|
|
continue
|
|
|
|
neigh = q.get_attr('BATADV_ATTR_NEIGH_ADDRESS')
|
|
if not neigh:
|
|
continue
|
|
|
|
orig = q.get_attr('BATADV_ATTR_ORIG_ADDRESS')
|
|
if not orig:
|
|
continue
|
|
|
|
hardif = q.get_attr('BATADV_ATTR_HARD_IFINDEX')
|
|
if not hardif:
|
|
continue
|
|
|
|
if orig != neigh:
|
|
continue
|
|
|
|
orig2tq[(neigh, hardif)] = tq
|
|
|
|
print("IF Neighbor last-seen TQ")
|
|
|
|
# this is not really necessary when we actually have done the orig == neigh
|
|
# check before - so printing orig2tq is nearly enough
|
|
for q in batadv.get_neighbors():
|
|
tq = '?'
|
|
|
|
hardif = q.get_attr('BATADV_ATTR_HARD_IFINDEX')
|
|
if not hardif:
|
|
continue
|
|
|
|
last_seen = q.get_attr('BATADV_ATTR_LAST_SEEN_MSECS')
|
|
if not last_seen:
|
|
continue
|
|
|
|
neigh = q.get_attr('BATADV_ATTR_NEIGH_ADDRESS')
|
|
if not neigh:
|
|
continue
|
|
|
|
if (neigh, hardif) in orig2tq:
|
|
tq = str(orig2tq[(neigh, hardif)])
|
|
|
|
ifname = if_indextoname(hardif)
|
|
print(" %10s %s %4i.%03is %s" % (ifname, neigh,
|
|
last_seen / 1000,
|
|
last_seen % 1000, tq))
|
|
|
|
batadv.close()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|