4 ORION_TABLE = 1 # from /etc/iproute2/rt_tables
5 ORION_REALMS = 1 # from /etc/iproute2/rt_realms
6 ORION_VIAS = [ "66.97.23.33", "129.97.1.46" ]
7 ORION_GW = "129.97.134.1"
8 ORION_SRC = "129.97.134.42"
11 # Don't touch anything beyond here
13 import sys, re, iplib, SubnetTree
23 sys.stderr.write("orionroutes.py: %s\n" % msg)
27 libnl = cdll.LoadLibrary("libnl.so.1")
28 nl_geterror = CFUNCTYPE(c_char_p) (("nl_geterror", libnl), None)
29 nl_handle_alloc = CFUNCTYPE(c_void_p) (("nl_handle_alloc", libnl), None)
30 nl_connect = CFUNCTYPE(c_int, c_void_p, c_int) \
31 (("nl_connect", libnl), ((1, "handle", None), (1, "type", NETLINK_ROUTE)))
32 rtnl_route_alloc = CFUNCTYPE(c_void_p) (("rtnl_route_alloc", libnl), None)
33 rtnl_link_alloc_cache = CFUNCTYPE(c_void_p, c_void_p) \
34 (("rtnl_link_alloc_cache", libnl), ((1, "handle", None), ))
35 rtnl_link_name2i = CFUNCTYPE(c_int, c_void_p, c_char_p) \
36 (("rtnl_link_name2i", libnl), ((1, "cache", None), (1, "iface", -1)))
37 rtnl_route_set_oif = CFUNCTYPE(c_void_p, c_void_p, c_int) \
38 (("rtnl_route_set_oif", libnl), ((1, "route", None), (1, "iface", -1)))
39 nl_cache_free = CFUNCTYPE(None, c_void_p) \
40 (("nl_cache_free", libnl), ((1, "cache", None), ))
41 nl_addr_parse = CFUNCTYPE(c_void_p, c_char_p, c_int) \
42 (("nl_addr_parse", libnl), ((1, "dst", None), (1, "family", AF_UNSPEC)))
43 rtnl_route_set_dst = CFUNCTYPE(c_int, c_void_p, c_void_p) \
44 (("rtnl_route_set_dst", libnl), ((1, "route", None), (1, "dst", None)))
45 rtnl_route_set_pref_src = CFUNCTYPE(c_int, c_void_p, c_void_p) \
46 (("rtnl_route_set_pref_src", libnl), ((1, "route", None), (1, "src", None)))
47 nl_addr_put = CFUNCTYPE(None, c_void_p) \
48 (("nl_addr_put", libnl), ((1, "addr", None), ))
49 rtnl_route_set_gateway = CFUNCTYPE(c_int, c_void_p, c_void_p) \
50 (("rtnl_route_set_gateway", libnl), ((1, "route", None), (1, "gw", None)))
51 rtnl_route_set_table = CFUNCTYPE(None, c_void_p, c_int) \
52 (("rtnl_route_set_table", libnl), ((1, "route", None), (1, "table", -1)))
53 rtnl_route_set_scope = CFUNCTYPE(None, c_void_p, c_int) \
54 (("rtnl_route_set_scope", libnl), ((1, "route", None), (1, "scope", -1)))
55 rtnl_route_set_protocol = CFUNCTYPE(None, c_void_p, c_int) \
56 (("rtnl_route_set_protocol", libnl), ((1, "route", None), (1, "proto", -1)))
57 rtnl_route_set_realms = CFUNCTYPE(None, c_void_p, c_int) \
58 (("rtnl_route_set_realms", libnl), ((1, "route", None), (1, "realms", -1)))
59 rtnl_route_add = CFUNCTYPE(c_int, c_void_p, c_void_p, c_int) \
60 (("rtnl_route_add", libnl), ((1, "handle", None), (1, "route", None), (1, "flags", 0)))
61 rtnl_route_put = CFUNCTYPE(None, c_void_p) \
62 (("rtnl_route_put", libnl), ((1, "route", None), ))
63 nl_handle_destroy = CFUNCTYPE(None, c_void_p) \
64 (("nl_handle_destroy", libnl), ((1, "handle", None), ))
65 rtnl_route_alloc_cache = CFUNCTYPE(c_void_p, c_void_p) \
66 (("rtnl_route_alloc_cache", libnl), ((1, "handle", None), ))
67 nl_cache_get_first = CFUNCTYPE(c_void_p, c_void_p) \
68 (("nl_cache_get_first", libnl), ((1, "cache", None), ))
69 rtnl_route_get_table = CFUNCTYPE(c_int, c_void_p) \
70 (("rtnl_route_get_table", libnl), ((1, "route", None), ))
71 rtnl_route_get_dst = CFUNCTYPE(c_void_p, c_void_p) \
72 (("rtnl_route_get_dst", libnl), ((1, "route", None), ))
73 nl_addr2str = CFUNCTYPE(c_char_p, c_void_p, c_char_p, c_int) \
74 (("nl_addr2str", libnl), ((1, "addr", None), (1, "buffer", None), (1, "size", 0)))
75 rtnl_route_del = CFUNCTYPE(c_int, c_void_p, c_void_p, c_int) \
76 (("rtnl_route_del", libnl), ((1, "handle", None), (1, "route", None), (1, "flags", 0)))
77 nl_cache_get_next = CFUNCTYPE(c_void_p, c_void_p) \
78 (("nl_cache_get_next", libnl), ((1, "object", None), ))
80 die("Failed to load libnl: %s" % e)
83 die("%s: %s" % (func, nl_geterror()))
85 cidr_re = re.compile("(B{0,1})\\s+([0-9.]+)/{0,1}(\\d*)(.*)")
86 via_re = re.compile(".*?via ([0-9.]+)")
88 ips = [[] for i in range(33)]
91 for line in sys.stdin.readlines():
92 cidr = cidr_re.match(line)
100 via = via_re.match(cidr[3])
101 if via == None or via.group(1) not in ORION_VIAS:
103 ips[int(last_bits)].append(int(iplib.IPv4Address(cidr[1])))
106 if count < 10: # we should never have less than 10 routes
107 die("Not enough routes (got %d)" % count)
110 for bits in range(32, 1, -1):
114 if ip != last_ip and (ip ^ last_ip) == (1 << (32 - bits)):
115 ips[bits - 1].append(ip & (((1 << (bits - 1)) - 1) << (32 - (bits - 1))))
118 cidrs.append((iplib.IPv4Address(last_ip), bits))
121 cidrs.append((iplib.IPv4Address(last_ip), bits))
123 nlh = nl_handle_alloc()
124 if nlh == None: nl_die("nl_handle_alloc")
125 if nl_connect(nlh, NETLINK_ROUTE) < 0: nl_die("nl_connect")
127 link_cache = rtnl_link_alloc_cache(nlh)
128 if link_cache == None: nl_die("rtnl_link_alloc")
129 iface = rtnl_link_name2i(link_cache, ORION_IFACE)
130 if iface < 0: nl_die("rtnl_link_name2i")
131 nl_cache_free(link_cache)
133 cidrs.sort(lambda (ip1, bits1), (ip2, bits2): cmp(ip1, ip2) if bits1 == bits2 else (bits1 - bits2))
134 tree = SubnetTree.SubnetTree()
135 for (ip, bits) in cidrs:
136 if str(ip) not in tree:
137 cidr = "%s/%s" % (ip, bits)
140 route = rtnl_route_alloc()
141 if route == None: nl_die("rtnl_route_alloc")
143 dstaddr = nl_addr_parse(cidr, AF_UNSPEC)
144 if dstaddr == None: nl_die("nl_addr_parse(%s)" % cidr)
145 if rtnl_route_set_dst(route, dstaddr) < 0: nl_die("rtnl_route_set_dst")
148 srcaddr = nl_addr_parse(ORION_SRC, AF_UNSPEC)
149 if srcaddr == None: nl_die("nl_addr_parse(%s)" % ORION_SRC)
150 if rtnl_route_set_pref_src(route, srcaddr) < 0: nl_die("nl_route_set_pref_src")
153 gwaddr = nl_addr_parse(ORION_GW, AF_UNSPEC)
154 if gwaddr == None: nl_die("nl_addr_parse(%s)" % ORION_GW)
155 if rtnl_route_set_gateway(route, gwaddr) < 0: nl_die("nl_route_set_gateway")
158 rtnl_route_set_oif(route, iface)
159 rtnl_route_set_table(route, ORION_TABLE)
160 rtnl_route_set_scope(route, RT_SCOPE_UNIVERSE)
161 rtnl_route_set_protocol(route, RTPROT_STATIC)
162 rtnl_route_set_realms(route, ORION_REALMS)
164 if rtnl_route_add(nlh, route, NLM_F_REPLACE) < 0: nl_die("rtnl_route_add(dst=%s)" % cidr)
165 rtnl_route_put(route)
167 route_cache = rtnl_route_alloc_cache(nlh)
168 if route_cache == None: nl_die("rtnl_route_alloc_cache")
169 dstaddr_s = create_string_buffer(100)
171 route = nl_cache_get_first(route_cache)
173 table = rtnl_route_get_table(route)
174 if table != ORION_TABLE:
175 route = nl_cache_get_next(route)
178 dstaddr = rtnl_route_get_dst(route)
181 if nl_addr2str(dstaddr, dstaddr_s, sizeof(dstaddr_s)) == None: nl_die("nl_addr2str")
182 dstaddr = str(repr(dstaddr_s.value)).strip('\'').split('/')[0]
184 if dstaddr not in tree:
185 rtnl_route_del(nlh, route, 0)
187 route = nl_cache_get_next(route)
189 nl_cache_free(route_cache)
191 nl_handle_destroy(nlh)