def convert_rt_msg(msg): ret = rtmsg() ret['header']['type'] = RTNL_NEWROUTE if \ msg['header']['type'] == RTM_ADD else \ RTNL_DELROUTE ret['family'] = msg['DST']['header']['family'] ret['attrs'] = [] if 'address' in msg['DST']: ret['attrs'].append(['RTA_DST', msg['DST']['address']]) if 'NETMASK' in msg and \ msg['NETMASK']['header']['family'] == ret['family']: ret['dst_len'] = dqn2int(msg['NETMASK']['address'], ret['family']) if 'GATEWAY' in msg: if msg['GATEWAY']['header']['family'] not in (AF_INET, AF_INET6): # interface routes, table 255 # discard for now return None ret['attrs'].append(['RTA_GATEWAY', msg['GATEWAY']['address']]) if 'IFA' in msg: ret['attrs'].append(['RTA_SRC', msg['IFA']['address']]) if 'IFP' in msg: ret['attrs'].append(['RTA_OIF', msg['IFP']['index']]) elif msg['rtm_index'] != 0: ret['attrs'].append(['RTA_OIF', msg['rtm_index']]) del ret['value'] return ret
def match_metrics(msg): if msg.get_attr('RTA_GATEWAY') != gateway1: return False mtu = (msg .get_attr('RTA_METRICS', rtmsg()) .get_attr('RTAX_MTU', 0)) return mtu == target
def get_routes(self, *argv, **kwarg): ifc = self._ifc.parse(self._ifc.run()) rta = self._route.parse(self._route.run()) ret = [] for spec in rta: idx = ifc['links'][spec['ifname']]['index'] spec['attrs'].append(['RTA_OIF', idx]) msg = rtmsg().load(spec) del msg['value'] ret.append(msg) return ret
def get_routes(self, *argv, **kwarg): ifc = self._ifc.parse(self._ifc.run()) rta = self._route.parse(self._route.run()) ret = [] for spec in rta: if spec['ifname'] not in ifc['links']: continue idx = ifc['links'][spec['ifname']]['index'] spec['attrs'].append(['RTA_OIF', idx]) msg = rtmsg().load(spec) msg['header']['type'] = RTM_NEWROUTE del msg['value'] ret.append(msg) return ret
def route( self, action, prefix, mask, table=254, rtype="RTN_UNICAST", rtproto="RTPROT_STATIC", rtscope="RT_SCOPE_UNIVERSE", interface=None, gateway=None, family=AF_INET, ): """ Route operations * action -- add, delete * prefix -- route prefix * mask -- route prefix mask * table -- routing table to use (default: 254) * rtype -- route type (default: "RTN_UNICAST") * rtproto -- routing protocol (default: "RTPROT_STATIC") * rtscope -- routing scope (default: "RT_SCOPE_UNIVERSE") * interface -- via device * gateway -- via address * family -- socket.AF_INET (default) or socket.AF_INET6 Example: ip.route("add", prefix="10.0.0.0", mask=24, gateway="192.168.0.1") """ actions = {"add": RTM_NEWROUTE, "delete": RTM_DELROUTE} action = actions.get(action, action) flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL msg = rtmsg() msg["table"] = table msg["family"] = family msg["proto"] = rtprotos[rtproto] msg["type"] = rtypes[rtype] msg["scope"] = rtscopes[rtscope] msg["dst_len"] = mask msg["attrs"] = [("RTA_DST", prefix), ("RTA_TABLE", table)] if interface is not None: msg["attrs"].append(("RTA_OIF", interface)) if gateway is not None: msg["attrs"].append(("RTA_GATEWAY", gateway)) return self.nlm_request(msg, msg_type=action, msg_flags=flags)
def get_routes(self, family=AF_INET, **kwarg): ''' Get all routes. You can specify the table. There are 255 routing classes (tables), and the kernel returns all the routes on each request. So the routine filters routes from full output. Example:: ip.get_routes() # get all the routes for all families ip.get_routes(family=AF_INET6) # get only IPv6 routes ip.get_routes(table=254) # get routes from 254 table ''' msg_flags = NLM_F_DUMP | NLM_F_REQUEST msg = rtmsg() # you can specify the table here, but the kernel # will ignore this setting table = kwarg.get('table', DEFAULT_TABLE) msg['table'] = table if table <= 255 else 252 # explicitly look for IPv6 if any([ kwarg.get(x, '').find(':') >= 0 for x in ('dst', 'src', 'gateway', 'prefsrc') ]): family = AF_INET6 msg['family'] = family # get a particular route if kwarg.get('dst', None) is not None: dlen = 32 if family == AF_INET else \ 128 if family == AF_INET6 else 0 msg_flags = NLM_F_REQUEST msg['dst_len'] = kwarg.get('dst_len', dlen) for key in kwarg: nla = rtmsg.name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) routes = self.nlm_request(msg, RTM_GETROUTE, msg_flags) return [ x for x in routes if x.get_attr('RTA_TABLE') == table or kwarg.get('table', None) is None ]
def get_routes(self, family=AF_INET, **kwarg): """ Get all routes. You can specify the table. There are 255 routing classes (tables), and the kernel returns all the routes on each request. So the routine filters routes from full output. Example:: ip.get_routes() # get all the routes for all families ip.get_routes(family=AF_INET6) # get only IPv6 routes ip.get_routes(table=254) # get routes from 254 table """ msg_flags = NLM_F_DUMP | NLM_F_REQUEST msg = rtmsg() # you can specify the table here, but the kernel # will ignore this setting table = kwarg.get("table", DEFAULT_TABLE) msg["table"] = table if table <= 255 else 252 # explicitly look for IPv6 if any([kwarg.get(x, "").find(":") >= 0 for x in ("dst", "src", "gateway", "prefsrc")]): family = AF_INET6 msg["family"] = family # get a particular route if kwarg.get("dst", None) is not None: dlen = 32 if family == AF_INET else 128 if family == AF_INET6 else 0 msg_flags = NLM_F_REQUEST msg["dst_len"] = kwarg.get("dst_len", dlen) for key in kwarg: nla = rtmsg.name2nla(key) if kwarg[key] is not None: msg["attrs"].append([nla, kwarg[key]]) routes = self.nlm_request(msg, RTM_GETROUTE, msg_flags) return [x for x in routes if x.get_attr("RTA_TABLE") == table or kwarg.get("table", None) is None]
def get_routes(self, family=AF_UNSPEC, **kwarg): ''' Get all routes. You can specify the table. There are 255 routing classes (tables), and the kernel returns all the routes on each request. So the routine filters routes from full output. Example:: ip.get_routes() # get all the routes for all families ip.get_routes(family=AF_INET6) # get only IPv6 routes ip.get_routes(table=254) # get routes from 254 table ''' msg_flags = NLM_F_DUMP | NLM_F_REQUEST msg = rtmsg() msg['family'] = family # you can specify the table here, but the kernel # will ignore this setting table = kwarg.get('table', 0) msg['table'] = table if table <= 255 else 252 # get a particular route if kwarg.get('dst', None) is not None: dlen = 32 if family == AF_INET else \ 128 if family == AF_INET6 else 0 msg_flags = NLM_F_REQUEST msg['dst_len'] = kwarg.get('dst_len', dlen) for key in kwarg: nla = rtmsg.name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) routes = self.nlm_request(msg, RTM_GETROUTE, msg_flags) return [x for x in routes if x.get_attr('RTA_TABLE') == table or kwarg.get('table', None) is None]
def get_routes(self, family=AF_UNSPEC, table=-1): """ Get all routes. You can specify the table. There are 255 routing classes (tables), and the kernel returns all the routes on each request. So the routine filters routes from full output. By default, table == -1, which means that one should get all tables. """ # moreover, the kernel returns records without # RTA_DST, which I don't know how to interpret :) msg = rtmsg() msg["family"] = family # msg['table'] = table # you can specify the table # here, but the kernel will # ignore this setting routes = self.nlm_request(msg, RTM_GETROUTE) return [ k for k in [i for i in routes if "attrs" in i] if [l for l in k["attrs"] if l[0] == "RTA_DST"] and (k["table"] == table or table == -1) ]
def route(self, command, rtype='RTN_UNICAST', rtproto='RTPROT_STATIC', rtscope='RT_SCOPE_UNIVERSE', **kwarg): ''' Route operations * command -- add, delete, change, replace * prefix -- route prefix * mask -- route prefix mask * rtype -- route type (default: "RTN_UNICAST") * rtproto -- routing protocol (default: "RTPROT_STATIC") * rtscope -- routing scope (default: "RT_SCOPE_UNIVERSE") * family -- socket.AF_INET (default) or socket.AF_INET6 `pyroute2/netlink/rtnl/rtmsg.py` rtmsg.nla_map: * table -- routing table to use (default: 254) * gateway -- via address * prefsrc -- preferred source IP address * dst -- the same as `prefix` * src -- source address * iif -- incoming traffic interface * oif -- outgoing traffic interface etc. Example:: ip.route("add", dst="10.0.0.0", mask=24, gateway="192.168.0.1") Commands `change` and `replace` have the same meanings, as in ip-route(8): `change` modifies only existing route, while `replace` creates a new one, if there is no such route yet. ''' # 8<---------------------------------------------------- # FIXME # flags should be moved to some more general place flags_base = NLM_F_REQUEST | NLM_F_ACK flags_make = flags_base | NLM_F_CREATE | NLM_F_EXCL flags_change = flags_base | NLM_F_REPLACE flags_replace = flags_change | NLM_F_CREATE # 8<---------------------------------------------------- commands = { 'add': (RTM_NEWROUTE, flags_make), 'set': (RTM_NEWROUTE, flags_replace), 'replace': (RTM_NEWROUTE, flags_replace), 'change': (RTM_NEWROUTE, flags_change), 'del': (RTM_DELROUTE, flags_make), 'remove': (RTM_DELROUTE, flags_make), 'delete': (RTM_DELROUTE, flags_make) } (command, flags) = commands.get(command, command) msg = rtmsg() # table is mandatory; by default == 254 # if table is not defined in kwarg, save it there # also for nla_attr: table = kwarg.get('table', 254) msg['table'] = table if table <= 255 else 252 msg['family'] = kwarg.get('family', AF_INET) msg['proto'] = rtprotos[rtproto] msg['type'] = rtypes[rtype] msg['scope'] = rtscopes[rtscope] msg['dst_len'] = kwarg.get('dst_len', None) or \ kwarg.get('mask', 0) msg['attrs'] = [] # FIXME # deprecated "prefix" support: if 'prefix' in kwarg: kwarg['dst'] = kwarg['prefix'] for key in kwarg: nla = rtmsg.name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) return self.nlm_request(msg, msg_type=command, msg_flags=flags)
def route(self, command, rtype='RTN_UNICAST', rtproto='RTPROT_STATIC', rtscope='RT_SCOPE_UNIVERSE', **kwarg): ''' Route operations * command -- add, delete * prefix -- route prefix * mask -- route prefix mask * rtype -- route type (default: "RTN_UNICAST") * rtproto -- routing protocol (default: "RTPROT_STATIC") * rtscope -- routing scope (default: "RT_SCOPE_UNIVERSE") * index -- via device index * family -- socket.AF_INET (default) or socket.AF_INET6 `pyroute2/netlink/rtnl/rtmsg.py` rtmsg.nla_map: * table -- routing table to use (default: 254) * gateway -- via address * prefsrc -- preferred source IP address etc. Example:: ip.route("add", dst="10.0.0.0", mask=24, gateway="192.168.0.1") ''' # 8<---------------------------------------------------- # FIXME # flags should be moved to some more general place flags_base = NLM_F_REQUEST | NLM_F_ACK flags_make = flags_base | NLM_F_CREATE | NLM_F_EXCL flags_replace = flags_base | NLM_F_REPLACE # 8<---------------------------------------------------- commands = {'add': (RTM_NEWROUTE, flags_make), 'set': (RTM_NEWROUTE, flags_replace), 'delete': (RTM_DELROUTE, flags_make)} (command, flags) = commands.get(command, command) msg = rtmsg() # table is mandatory; by default == 254 # if table is not defined in kwarg, save it there # also for nla_attr: table = kwarg.get('table', 254) msg['table'] = table if table <= 255 else 252 msg['family'] = kwarg.get('family', AF_INET) msg['proto'] = rtprotos[rtproto] msg['type'] = rtypes[rtype] msg['scope'] = rtscopes[rtscope] msg['dst_len'] = kwarg.get('dst_len', None) or \ kwarg.get('mask', 0) msg['attrs'] = [] # FIXME # deprecated "prefix" support: if 'prefix' in kwarg: kwarg['dst'] = kwarg['prefix'] for key in kwarg: nla = rtmsg.name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) return self.nlm_request(msg, msg_type=command, msg_flags=flags)
def rule(self, command, table, priority=32000, rtype='RTN_UNICAST', rtscope='RT_SCOPE_UNIVERSE', family=AF_INET, src=None): ''' Rule operations * command - add, delete * table - 0 < table id < 253 * priority - 0 < rule's priority < 32766 * rtype - type of rule, default 'RTN_UNICAST' * rtscope - routing scope, default RT_SCOPE_UNIVERSE (RT_SCOPE_UNIVERSE|RT_SCOPE_SITE|\ RT_SCOPE_LINK|RT_SCOPE_HOST|RT_SCOPE_NOWHERE) * family - rule's family (socket.AF_INET (default) or socket.AF_INET6) * src - IP source for Source Based (Policy Based) routing's rule Example:: ip.rule('add', 10, 32000) Will create:: #ip ru sh ... 32000: from all lookup 10 .... Example:: iproute.rule('add', 11, 32001, 'RTN_UNREACHABLE') Will create:: #ip ru sh ... 32001: from all lookup 11 unreachable .... Example:: iproute.rule('add', 14, 32004, src='10.64.75.141') Will create:: #ip ru sh ... 32004: from 10.64.75.141 lookup 14 ... ''' if table < 0 or table > 254: raise 'unsupported table number' commands = {'add': RTM_NEWRULE, 'delete': RTM_DELRULE} command = commands.get(command, command) msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL msg = rtmsg() msg['table'] = table msg['family'] = family msg['type'] = rtypes[rtype] msg['scope'] = rtscopes[rtscope] msg['attrs'] = [['RTA_TABLE', table]] msg['attrs'].append(['RTA_PRIORITY', priority]) msg['dst_len'] = 0 msg['src_len'] = 0 if src is not None: msg['attrs'].append(['RTA_SRC', src]) addr_len = { AF_INET6: 128, AF_INET: 32}[family] msg['src_len'] = addr_len return self.nlm_request(msg, msg_type=command, msg_flags=msg_flags)
def rule(self, command, table, priority=32000, rtype='RTN_UNICAST', rtscope='RT_SCOPE_UNIVERSE', family=AF_INET, src=None): ''' Rule operations * command - add, delete * table - 0 < table id < 253 * priority - 0 < rule's priority < 32766 * rtype - type of rule, default 'RTN_UNICAST' * rtscope - routing scope, default RT_SCOPE_UNIVERSE (RT_SCOPE_UNIVERSE|RT_SCOPE_SITE|\ RT_SCOPE_LINK|RT_SCOPE_HOST|RT_SCOPE_NOWHERE) * family - rule's family (socket.AF_INET (default) or socket.AF_INET6) * src - IP source for Source Based (Policy Based) routing's rule Example:: ip.rule('add', 10, 32000) Will create:: #ip ru sh ... 32000: from all lookup 10 .... Example:: iproute.rule('add', 11, 32001, 'RTN_UNREACHABLE') Will create:: #ip ru sh ... 32001: from all lookup 11 unreachable .... Example:: iproute.rule('add', 14, 32004, src='10.64.75.141') Will create:: #ip ru sh ... 32004: from 10.64.75.141 lookup 14 ... ''' if table < 0 or table > 254: raise 'unsupported table number' commands = {'add': RTM_NEWRULE, 'delete': RTM_DELRULE} command = commands.get(command, command) msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL msg = rtmsg() msg['table'] = table msg['family'] = family msg['type'] = rtypes[rtype] msg['scope'] = rtscopes[rtscope] msg['attrs'] = [['RTA_TABLE', table]] msg['attrs'].append(['RTA_PRIORITY', priority]) msg['dst_len'] = 0 msg['src_len'] = 0 if src is not None: msg['attrs'].append(['RTA_SRC', src]) addr_len = {AF_INET6: 128, AF_INET: 32}[family] msg['src_len'] = addr_len return self.nlm_request(msg, msg_type=command, msg_flags=msg_flags)
def route(self, command, **kwarg): ''' Route operations. * command -- add, delete, change, replace * rtype -- route type (default: "RTN_UNICAST") * rtproto -- routing protocol (default: "RTPROT_STATIC") * rtscope -- routing scope (default: "RT_SCOPE_UNIVERSE") * family -- socket.AF_INET (default) or socket.AF_INET6 * mask -- route prefix mask `pyroute2/netlink/rtnl/rtmsg.py` rtmsg.nla_map: * table -- routing table to use (default: 254) * gateway -- via address * prefsrc -- preferred source IP address * dst -- the same as `prefix` * src -- source address * iif -- incoming traffic interface * oif -- outgoing traffic interface etc. Example:: ip.route("add", dst="10.0.0.0", mask=24, gateway="192.168.0.1") Commands `change` and `replace` have the same meanings, as in ip-route(8): `change` modifies only existing route, while `replace` creates a new one, if there is no such route yet. It is possible to set also route metrics. There are two ways to do so. The first is to use 'raw' NLA notation:: ip.route("add", dst="10.0.0.0", mask=24, gateway="192.168.0.1", metrics={"attrs": [["RTAX_MTU", 1400], ["RTAX_HOPLIMIT", 16]]}) The second way is to use `IPRouteRequest` helper:: from pyroute2.netlink.rtnl.req import IPRouteRequest ... ip.route("add", **IPRouteRequest({"dst": "10.0.0.0/24", "gateway": "192.168.0.1", "metrics": {"mtu": 1400, "hoplimit": 16}})) The `IPRouteRequest` helper is useful also to manage mulptipath routes:: from pyroute2.netlink.rtnl.req import IPRouteRequest ... request = {"dst": "10.0.0.0/24", "multipath": [{"gateway": "192.168.0.1", "hops": 2}, {"gateway": "192.168.0.2", "hops": 1}, {"gateway": "192.168.0.3"}]} ip.route("add", **IPRouteRequest(request)) ''' # 8<---------------------------------------------------- # FIXME # flags should be moved to some more general place flags_base = NLM_F_REQUEST | NLM_F_ACK flags_make = flags_base | NLM_F_CREATE | NLM_F_EXCL flags_change = flags_base | NLM_F_REPLACE flags_replace = flags_change | NLM_F_CREATE # 8<---------------------------------------------------- commands = { 'add': (RTM_NEWROUTE, flags_make), 'set': (RTM_NEWROUTE, flags_replace), 'replace': (RTM_NEWROUTE, flags_replace), 'change': (RTM_NEWROUTE, flags_change), 'del': (RTM_DELROUTE, flags_make), 'remove': (RTM_DELROUTE, flags_make), 'delete': (RTM_DELROUTE, flags_make) } (command, flags) = commands.get(command, command) msg = rtmsg() # table is mandatory; by default == 254 # if table is not defined in kwarg, save it there # also for nla_attr: table = kwarg.get('table', 254) msg['table'] = table if table <= 255 else 252 msg['family'] = kwarg.pop('family', AF_INET) msg['proto'] = rtprotos[kwarg.pop('rtproto', 'RTPROT_STATIC')] msg['type'] = rtypes[kwarg.pop('rtype', 'RTN_UNICAST')] msg['scope'] = rtscopes[kwarg.pop('rtscope', 'RT_SCOPE_UNIVERSE')] msg['dst_len'] = kwarg.pop('dst_len', None) or kwarg.pop('mask', 0) msg['src_len'] = kwarg.pop('src_len', 0) msg['tos'] = kwarg.pop('tos', 0) msg['flags'] = kwarg.pop('flags', 0) msg['attrs'] = [] # FIXME # deprecated "prefix" support: if 'prefix' in kwarg: logging.warning('`prefix` argument is deprecated, use `dst`') kwarg['dst'] = kwarg['prefix'] for key in kwarg: nla = rtmsg.name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) # fix IP family, if needed if msg['family'] == AF_UNSPEC: if key in ('dst', 'src', 'gateway', 'prefsrc', 'newdst') \ and isinstance(kwarg[key], basestring): msg['family'] = AF_INET6 if kwarg[key].find(':') >= 0 \ else AF_INET elif key == 'multipath' and len(kwarg[key]) > 0: hop = kwarg[key][0] attrs = hop.get('attrs', []) for attr in attrs: if attr[0] == 'RTA_GATEWAY': msg['family'] = AF_INET6 if \ attr[1].find(':') >= 0 else AF_INET break ret = self.nlm_request(msg, msg_type=command, msg_flags=flags) if 'match' in kwarg: return self._match(kwarg['match'], ret) else: return ret
def rule( self, command, table, priority=32000, rtype="RTN_UNICAST", rtscope="RT_SCOPE_UNIVERSE", family=AF_INET, src=None, src_len=None, dst=None, dst_len=None, fwmark=None, ): """ Rule operations * command - add, delete * table - 0 < table id < 253 * priority - 0 < rule's priority < 32766 * rtype - type of rule, default 'RTN_UNICAST' * rtscope - routing scope, default RT_SCOPE_UNIVERSE (RT_SCOPE_UNIVERSE|RT_SCOPE_SITE|\ RT_SCOPE_LINK|RT_SCOPE_HOST|RT_SCOPE_NOWHERE) * family - rule's family (socket.AF_INET (default) or socket.AF_INET6) * src - IP source for Source Based (Policy Based) routing's rule * dst - IP for Destination Based (Policy Based) routing's rule * src_len - Mask for Source Based (Policy Based) routing's rule * dst_len - Mask for Destination Based (Policy Based) routing's rule Example:: ip.rule('add', 10, 32000) Will create:: #ip ru sh ... 32000: from all lookup 10 .... Example:: iproute.rule('add', 11, 32001, 'RTN_UNREACHABLE') Will create:: #ip ru sh ... 32001: from all lookup 11 unreachable .... Example:: iproute.rule('add', 14, 32004, src='10.64.75.141') Will create:: #ip ru sh ... 32004: from 10.64.75.141 lookup 14 ... Example:: iproute.rule('add', 15, 32005, dst='10.64.75.141', dst_len=24) Will create:: #ip ru sh ... 32005: from 10.64.75.141/24 lookup 15 ... Example:: iproute.rule('add', 15, 32006, dst='10.64.75.141', fwmark=10) Will create:: #ip ru sh ... 32006: from 10.64.75.141 fwmark 0xa lookup 15 ... """ if table < 1: raise ValueError("unsupported table number") commands = {"add": RTM_NEWRULE, "del": RTM_DELRULE, "remove": RTM_DELRULE, "delete": RTM_DELRULE} command = commands.get(command, command) msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL msg = rtmsg() msg["table"] = table if table <= 255 else 252 msg["family"] = family msg["type"] = rtypes[rtype] msg["scope"] = rtscopes[rtscope] msg["attrs"] = [["RTA_TABLE", table]] msg["attrs"].append(["RTA_PRIORITY", priority]) if fwmark is not None: msg["attrs"].append(["RTA_PROTOINFO", fwmark]) addr_len = {AF_INET6: 128, AF_INET: 32}[family] if dst_len is not None and dst_len >= 0 and dst_len <= addr_len: msg["dst_len"] = dst_len else: msg["dst_len"] = 0 if src_len is not None and src_len >= 0 and src_len <= addr_len: msg["src_len"] = src_len else: msg["src_len"] = 0 if src is not None: msg["attrs"].append(["RTA_SRC", src]) if src_len is None: msg["src_len"] = addr_len if dst is not None: msg["attrs"].append(["RTA_DST", dst]) if dst_len is None: msg["dst_len"] = addr_len return self.nlm_request(msg, msg_type=command, msg_flags=msg_flags)
def route(self, command, rtype="RTN_UNICAST", rtproto="RTPROT_STATIC", rtscope="RT_SCOPE_UNIVERSE", **kwarg): """ Route operations * command -- add, delete, change, replace * prefix -- route prefix * mask -- route prefix mask * rtype -- route type (default: "RTN_UNICAST") * rtproto -- routing protocol (default: "RTPROT_STATIC") * rtscope -- routing scope (default: "RT_SCOPE_UNIVERSE") * family -- socket.AF_INET (default) or socket.AF_INET6 `pyroute2/netlink/rtnl/rtmsg.py` rtmsg.nla_map: * table -- routing table to use (default: 254) * gateway -- via address * prefsrc -- preferred source IP address * dst -- the same as `prefix` * src -- source address * iif -- incoming traffic interface * oif -- outgoing traffic interface etc. Example:: ip.route("add", dst="10.0.0.0", mask=24, gateway="192.168.0.1") Commands `change` and `replace` have the same meanings, as in ip-route(8): `change` modifies only existing route, while `replace` creates a new one, if there is no such route yet. """ # 8<---------------------------------------------------- # FIXME # flags should be moved to some more general place flags_base = NLM_F_REQUEST | NLM_F_ACK flags_make = flags_base | NLM_F_CREATE | NLM_F_EXCL flags_change = flags_base | NLM_F_REPLACE flags_replace = flags_change | NLM_F_CREATE # 8<---------------------------------------------------- commands = { "add": (RTM_NEWROUTE, flags_make), "set": (RTM_NEWROUTE, flags_replace), "replace": (RTM_NEWROUTE, flags_replace), "change": (RTM_NEWROUTE, flags_change), "del": (RTM_DELROUTE, flags_make), "remove": (RTM_DELROUTE, flags_make), "delete": (RTM_DELROUTE, flags_make), } (command, flags) = commands.get(command, command) msg = rtmsg() # table is mandatory; by default == 254 # if table is not defined in kwarg, save it there # also for nla_attr: table = kwarg.get("table", 254) msg["table"] = table if table <= 255 else 252 msg["family"] = kwarg.get("family", AF_INET) msg["proto"] = rtprotos[rtproto] msg["type"] = rtypes[rtype] msg["scope"] = rtscopes[rtscope] msg["dst_len"] = kwarg.get("dst_len", None) or kwarg.get("mask", 0) msg["attrs"] = [] # FIXME # deprecated "prefix" support: if "prefix" in kwarg: kwarg["dst"] = kwarg["prefix"] for key in kwarg: nla = rtmsg.name2nla(key) if kwarg[key] is not None: msg["attrs"].append([nla, kwarg[key]]) return self.nlm_request(msg, msg_type=command, msg_flags=flags)
def route(self, command, **kwarg): ''' Route operations. * command -- add, delete, change, replace * rtype -- route type (default: "RTN_UNICAST") * rtproto -- routing protocol (default: "RTPROT_STATIC") * rtscope -- routing scope (default: "RT_SCOPE_UNIVERSE") * family -- socket.AF_INET (default) or socket.AF_INET6 * mask -- route prefix mask `pyroute2/netlink/rtnl/rtmsg.py` rtmsg.nla_map: * table -- routing table to use (default: 254) * gateway -- via address * prefsrc -- preferred source IP address * dst -- the same as `prefix` * src -- source address * iif -- incoming traffic interface * oif -- outgoing traffic interface etc. Example:: ip.route("add", dst="10.0.0.0", mask=24, gateway="192.168.0.1") Commands `change` and `replace` have the same meanings, as in ip-route(8): `change` modifies only existing route, while `replace` creates a new one, if there is no such route yet. It is possible to set also route metrics. There are two ways to do so. The first is to use 'raw' NLA notation:: ip.route("add", dst="10.0.0.0", mask=24, gateway="192.168.0.1", metrics={"attrs": [["RTAX_MTU", 1400], ["RTAX_HOPLIMIT", 16]]}) The second way is to use `IPRouteRequest` helper:: from pyroute2.netlink.rtnl.req import IPRouteRequest ... ip.route("add", **IPRouteRequest({"dst": "10.0.0.0/24", "gateway": "192.168.0.1", "metrics": {"mtu": 1400, "hoplimit": 16}})) The `IPRouteRequest` helper is useful also to manage mulptipath routes:: from pyroute2.netlink.rtnl.req import IPRouteRequest ... request = {"dst": "10.0.0.0/24", "multipath": [{"gateway": "192.168.0.1", "hops": 2}, {"gateway": "192.168.0.2", "hops": 1}, {"gateway": "192.168.0.3"}]} ip.route("add", **IPRouteRequest(request)) ''' # 8<---------------------------------------------------- # FIXME # flags should be moved to some more general place flags_base = NLM_F_REQUEST | NLM_F_ACK flags_make = flags_base | NLM_F_CREATE | NLM_F_EXCL flags_change = flags_base | NLM_F_REPLACE flags_replace = flags_change | NLM_F_CREATE # 8<---------------------------------------------------- commands = {'add': (RTM_NEWROUTE, flags_make), 'set': (RTM_NEWROUTE, flags_replace), 'replace': (RTM_NEWROUTE, flags_replace), 'change': (RTM_NEWROUTE, flags_change), 'del': (RTM_DELROUTE, flags_make), 'remove': (RTM_DELROUTE, flags_make), 'delete': (RTM_DELROUTE, flags_make)} (command, flags) = commands.get(command, command) msg = rtmsg() # table is mandatory; by default == 254 # if table is not defined in kwarg, save it there # also for nla_attr: table = kwarg.get('table', 254) msg['table'] = table if table <= 255 else 252 msg['family'] = kwarg.pop('family', AF_INET) msg['proto'] = rtprotos[kwarg.pop('rtproto', 'RTPROT_STATIC')] msg['type'] = rtypes[kwarg.pop('rtype', 'RTN_UNICAST')] msg['scope'] = rtscopes[kwarg.pop('rtscope', 'RT_SCOPE_UNIVERSE')] msg['dst_len'] = kwarg.pop('dst_len', None) or kwarg.pop('mask', 0) msg['src_len'] = kwarg.pop('src_len', 0) msg['tos'] = kwarg.pop('tos', 0) msg['flags'] = kwarg.pop('flags', 0) msg['attrs'] = [] # FIXME # deprecated "prefix" support: if 'prefix' in kwarg: logging.warning('`prefix` argument is deprecated, use `dst`') kwarg['dst'] = kwarg['prefix'] for key in kwarg: nla = rtmsg.name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) # fix IP family, if needed if msg['family'] == AF_UNSPEC: if key in ('dst', 'src', 'gateway', 'prefsrc', 'newdst') \ and isinstance(kwarg[key], basestring): msg['family'] = AF_INET6 if kwarg[key].find(':') >= 0 \ else AF_INET elif key == 'multipath' and len(kwarg[key]) > 0: hop = kwarg[key][0] attrs = hop.get('attrs', []) for attr in attrs: if attr[0] == 'RTA_GATEWAY': msg['family'] = AF_INET6 if \ attr[1].find(':') >= 0 else AF_INET break ret = self.nlm_request(msg, msg_type=command, msg_flags=flags) if 'match' in kwarg: return self._match(kwarg['match'], ret) else: return ret
def route(self, command, **kwarg): ''' Route operations. * command -- add, delete, change, replace * rtype -- route type (default: "RTN_UNICAST") * rtproto -- routing protocol (default: "RTPROT_STATIC") * rtscope -- routing scope (default: "RT_SCOPE_UNIVERSE") * family -- socket.AF_INET (default) or socket.AF_INET6 * mask -- route prefix mask `pyroute2/netlink/rtnl/rtmsg.py` rtmsg.nla_map: * table -- routing table to use (default: 254) * gateway -- via address * prefsrc -- preferred source IP address * dst -- the same as `prefix` * src -- source address * iif -- incoming traffic interface * oif -- outgoing traffic interface etc. Example:: ip.route("add", dst="10.0.0.0", mask=24, gateway="192.168.0.1") Commands `change` and `replace` have the same meanings, as in ip-route(8): `change` modifies only existing route, while `replace` creates a new one, if there is no such route yet. ''' # 8<---------------------------------------------------- # FIXME # flags should be moved to some more general place flags_base = NLM_F_REQUEST | NLM_F_ACK flags_make = flags_base | NLM_F_CREATE | NLM_F_EXCL flags_change = flags_base | NLM_F_REPLACE flags_replace = flags_change | NLM_F_CREATE # 8<---------------------------------------------------- commands = {'add': (RTM_NEWROUTE, flags_make), 'set': (RTM_NEWROUTE, flags_replace), 'replace': (RTM_NEWROUTE, flags_replace), 'change': (RTM_NEWROUTE, flags_change), 'del': (RTM_DELROUTE, flags_make), 'remove': (RTM_DELROUTE, flags_make), 'delete': (RTM_DELROUTE, flags_make)} (command, flags) = commands.get(command, command) msg = rtmsg() # table is mandatory; by default == 254 # if table is not defined in kwarg, save it there # also for nla_attr: table = kwarg.get('table', 254) msg['table'] = table if table <= 255 else 252 msg['family'] = kwarg.pop('family', AF_INET) msg['proto'] = rtprotos[kwarg.pop('rtproto', 'RTPROT_STATIC')] msg['type'] = rtypes[kwarg.pop('rtype', 'RTN_UNICAST')] msg['scope'] = rtscopes[kwarg.pop('rtscope', 'RT_SCOPE_UNIVERSE')] msg['dst_len'] = kwarg.pop('dst_len', None) or kwarg.pop('mask', 0) msg['attrs'] = [] # FIXME # deprecated "prefix" support: if 'prefix' in kwarg: logging.warning('`prefix` argument is deprecated, use `dst`') kwarg['dst'] = kwarg['prefix'] for key in kwarg: nla = rtmsg.name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) ret = self.nlm_request(msg, msg_type=command, msg_flags=flags) if 'match' in kwarg: return self._match(kwarg['match'], ret) else: return ret
def rule(self, command, table, priority=32000, rtype='RTN_UNICAST', rtscope='RT_SCOPE_UNIVERSE', family=AF_INET, src=None, src_len=None, dst=None, dst_len=None, fwmark=None): ''' Rule operations * command - add, delete * table - 0 < table id < 253 * priority - 0 < rule's priority < 32766 * rtype - type of rule, default 'RTN_UNICAST' * rtscope - routing scope, default RT_SCOPE_UNIVERSE (RT_SCOPE_UNIVERSE|RT_SCOPE_SITE|\ RT_SCOPE_LINK|RT_SCOPE_HOST|RT_SCOPE_NOWHERE) * family - rule's family (socket.AF_INET (default) or socket.AF_INET6) * src - IP source for Source Based (Policy Based) routing's rule * dst - IP for Destination Based (Policy Based) routing's rule * src_len - Mask for Source Based (Policy Based) routing's rule * dst_len - Mask for Destination Based (Policy Based) routing's rule Example:: ip.rule('add', 10, 32000) Will create:: #ip ru sh ... 32000: from all lookup 10 .... Example:: iproute.rule('add', 11, 32001, 'RTN_UNREACHABLE') Will create:: #ip ru sh ... 32001: from all lookup 11 unreachable .... Example:: iproute.rule('add', 14, 32004, src='10.64.75.141') Will create:: #ip ru sh ... 32004: from 10.64.75.141 lookup 14 ... Example:: iproute.rule('add', 15, 32005, dst='10.64.75.141', dst_len=24) Will create:: #ip ru sh ... 32005: from 10.64.75.141/24 lookup 15 ... Example:: iproute.rule('add', 15, 32006, dst='10.64.75.141', fwmark=10) Will create:: #ip ru sh ... 32006: from 10.64.75.141 fwmark 0xa lookup 15 ... ''' if table < 1: raise ValueError('unsupported table number') commands = { 'add': RTM_NEWRULE, 'del': RTM_DELRULE, 'remove': RTM_DELRULE, 'delete': RTM_DELRULE } command = commands.get(command, command) msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL msg = rtmsg() msg['table'] = table if table <= 255 else 252 msg['family'] = family msg['type'] = rtypes[rtype] msg['scope'] = rtscopes[rtscope] msg['attrs'] = [['RTA_TABLE', table]] msg['attrs'].append(['RTA_PRIORITY', priority]) if fwmark is not None: msg['attrs'].append(['RTA_PROTOINFO', fwmark]) addr_len = {AF_INET6: 128, AF_INET: 32}[family] if (dst_len is not None and dst_len >= 0 and dst_len <= addr_len): msg['dst_len'] = dst_len else: msg['dst_len'] = 0 if (src_len is not None and src_len >= 0 and src_len <= addr_len): msg['src_len'] = src_len else: msg['src_len'] = 0 if src is not None: msg['attrs'].append(['RTA_SRC', src]) if src_len is None: msg['src_len'] = addr_len if dst is not None: msg['attrs'].append(['RTA_DST', dst]) if dst_len is None: msg['dst_len'] = addr_len return self.nlm_request(msg, msg_type=command, msg_flags=msg_flags)