1#!/usr/bin/python
2
3from __future__ import print_function
4
5import sys
6import socket
7
8from exabgp.netlink import NetMask
9from exabgp.netlink.attributes import Attributes
10
11from exabgp.netlink.route.link import Link
12from exabgp.netlink.route.neighbor import Neighbor
13from exabgp.netlink.route.address import Address
14from exabgp.netlink.route.network import Network
15
16
17def usage():
18    print('%s' % sys.argv[0])
19    print('  addr  : show the ip address on the interface')
20    print('  route : show the ip routing')
21
22
23def addresses():
24    links = {}
25    for ifi in Link.getLinks():
26        links[ifi.index] = ifi
27
28    addrs = {}
29    for ifa in Address.getAddresses():
30        addrs.setdefault(ifa.index, []).append(ifa)
31
32    neighbors = {}
33    for neighbor in Neighbor.getNeighbors():
34        neighbors.setdefault(neighbor.index, []).append(neighbor)
35
36    for index, ifi in links.items():
37        hwaddr = '<no addr>'
38        if Address.Type.Attribute.IFLA_ADDRESS in ifi.attributes:
39            hwaddr = ':'.join(x.encode('hex') for x in ifi.attributes[Address.Type.Attribute.IFLA_ADDRESS])
40        print("%d: %s %s" % (ifi.index, ifi.attributes[Address.Type.Attribute.IFLA_IFNAME][:-1], hwaddr))
41
42        for ifa in addrs.get(ifi.index, {}):
43            address = ifa.attributes.get(Attributes.Type.IFA_ADDRESS)
44            if not address:
45                continue
46
47            if ifa.family == socket.AF_INET:
48                print('  %s %s' % ('inet ', socket.inet_ntop(ifa.family, address)))
49            elif ifa.family == socket.AF_INET6:
50                print('  %s %s' % ('inet6', socket.inet_ntop(ifa.family, address)))
51            else:
52                print('  %d %s' % (ifa.family, address.encode('hex')))
53
54        for neighbor in neighbors.get(ifi.index, {}):
55            if neighbor.state == Neighbor.Type.State.NUD_REACHABLE:
56                address = neighbor.attributes.get(Neighbor.Type.Flag.NTF_USE, '\0\0\0\0')
57                if ifa.family == socket.AF_INET:
58                    print('  %s %s' % ('inet ', socket.inet_ntop(neighbor.family, address)), end=' ')
59                elif ifa.family == socket.AF_INET6:
60                    print('  %s %s' % ('inet ', socket.inet_ntop(neighbor.family, address)), end=' ')
61                else:
62                    print('  %d %s' % (ifa.family, address.encode('hex')))
63                print('mac', ':'.join(_.encode('hex') for _ in neighbor.attributes[Neighbor.Type.State.NUD_REACHABLE]))
64
65
66def routes():
67    links = {}
68    for ifi in Link.getLinks():
69        links[ifi.index] = ifi.attributes.get(Link.Type.Attribute.IFLA_IFNAME).strip('\0')
70
71    print('Kernel IP routing table')
72    print('%-18s %-18s %-18s %-7s %s' % ('Destination', 'Genmask', 'Gateway', 'Metric', 'Iface'))
73
74    for route in Network.getRoutes():
75        if route.family != socket.AF_INET:
76            continue
77
78        if route.type not in (Network.Type.Type.RTN_LOCAL, Network.Type.Type.RTN_UNICAST):
79            continue
80
81        if route.src_len == 32:
82            continue
83
84        destination = route.attributes.get(Network.Type.Attribute.RTA_DST)
85        gateway = route.attributes.get(Network.Type.Attribute.RTA_GATEWAY)
86
87        oif = ord(route.attributes.get(Network.Type.Attribute.RTA_OIF)[0])
88        metric = ord(route.attributes.get(Network.Type.Attribute.RTA_PRIORITY, '\0')[0])
89
90        dst = '%s' % socket.inet_ntop(route.family, destination) if destination else ''
91        gw = '%s' % socket.inet_ntop(route.family, gateway) if gateway else '0.0.0.0'
92        mask = NetMask.CIDR[route.src_len]
93        iface = links[oif]
94
95        print('%-18s %-18s %-18s %-7d %-s' % (dst or '0.0.0.0', mask, gw, metric, iface))
96        # if gateway: print route
97
98
99def new():
100    links = {}
101    for ifi in Link.getLinks():
102        links[ifi.index] = ifi.attributes.get(Link.Type.Attribute.IFLA_IFNAME).strip('\0')
103
104    for route in Network.newRoute():
105        print(route)
106
107        # if route.family != socket.AF_INET:
108        # 	continue
109        #
110        # if route.type not in (Network.Type.Type.RTN_LOCAL,Network.Type.Type.RTN_UNICAST):
111        # 	continue
112        #
113        # if route.src_len == 32:
114        # 	continue
115        #
116        # destination = route.attributes.get(Network.Type.Attribute.RTA_DST)
117        # gateway = route.attributes.get(Network.Type.Attribute.RTA_GATEWAY)
118        #
119        # oif = ord(route.attributes.get(Network.Type.Attribute.RTA_OIF)[0])
120        # metric = ord(route.attributes.get(Network.Type.Attribute.RTA_PRIORITY,'\0')[0])
121        #
122        # dst = '%s' % socket.inet_ntop(route.family, destination) if destination else ''
123        # gw  = '%s' % socket.inet_ntop(route.family, gateway) if gateway else '0.0.0.0'
124        # mask = NetMask.CIDR[route.src_len]
125        # iface = links[oif]
126        #
127        # print '%-18s %-18s %-18s %-7d %-s' % (dst or '0.0.0.0',mask,gw,metric,iface)
128
129
130def main():
131    if len(sys.argv) < 2:
132        usage()
133        sys.exit(1)
134    if 'addr'.startswith(sys.argv[1]):
135        if len(sys.argv) == 2:
136            addresses()
137            sys.exit(0)
138        if sys.argv[2] in 'show':
139            addresses()
140            sys.exit(0)
141    if 'route'.startswith(sys.argv[1]):
142        if len(sys.argv) == 2:
143            routes()
144            sys.exit(0)
145        if 'show'.startswith(sys.argv[2]):
146            routes()
147            sys.exit(0)
148        if 'add'.startswith(sys.argv[2]):
149            new()
150            sys.exit(0)
151        if 'delete'.startswith(sys.argv[2]):
152            print('adding')
153
154    usage()
155    sys.exit(0)
156
157
158if __name__ == '__main__':
159    main()
160