def tunnel_listp(devname): s = NetlinkSocket() s.bind() msg = ifinfmsg() nonce = 123 # fill the protocol-specific fields msg['index'] = 85 # index of the interface msg['family'] = 18 # address family # attach NLA -- it MUST be a list / mutable msg['attrs'] = [['CTRL_ATTR_FAMILY_NAME', "gtp0"]] # fill generic netlink fields msg['header']['sequence_number'] = nonce # an unique seq number msg['header']['pid'] = os.getpid() msg['header']['type'] = GENL_ID_CTRL msg['header']['flags'] = NLM_F_REQUEST |\ NLM_F_ACK # encode the packet msg.encode() # send the buffer s.sendto(msg.data, (0, 0)) s.get() s.close() l = 1 print("tthis is a list; {}".format(l)) return list
def release(self): ''' Shutdown IPDB instance and sync the state. Since IPDB is asyncronous, some operations continue in the background, e.g. callbacks. So, prior to exit the script, it is required to properly shutdown IPDB. The shutdown sequence is not forced in an interactive python session, since it is easier for users and there is enough time to sync the state. But for the scripts the `release()` call is required. ''' with self._shutdown_lock: if self._stop: return self._stop = True # terminate the main loop for t in range(3): try: msg = ifinfmsg() msg['index'] = 1 msg.reset() self.mnl.put(msg, RTM_GETLINK) except Exception as e: logging.warning("shotdown error: %s", e) # Just give up. # We can not handle this case if self._mthread is not None: self._mthread.join() self.nl.close() self.nl = None self.mnl.close() self.mnl = None with self.exclusive: # collect all the callbacks for cuid in tuple(self._cb_threads): for t in tuple(self._cb_threads[cuid]): t.join() # flush all the objects for (key, dev) in self.by_name.items(): try: # FIXME self.interfaces._detach(key, dev['index'], dev.nlmsg) except KeyError: pass def flush(idx): for key in tuple(idx.keys()): try: del idx[key] except KeyError: pass idx_list = [self.routes.tables[x] for x in self.routes.tables.keys()] idx_list.append(self.ipaddr) idx_list.append(self.neighbours) for idx in idx_list: flush(idx)
def convert_if_announcemsg(msg): ret = ifinfmsg() ret['header']['type'] = RTNL_DELLINK if msg['ifan_what'] else RTNL_NEWLINK ret['index'] = msg['ifan_index'] ret['attrs'] = [['IFLA_IFNAME', msg['ifan_name']]] del ret['value'] return ret
def get_links(self, *argv, **kwarg): ''' Get network interfaces. By default returns all interfaces. Arguments vector can contain interface indices or a special keyword 'all':: ip.get_links() ip.get_links('all') ip.get_links(1, 2, 3) interfaces = [1, 2, 3] ip.get_links(*interfaces) ''' result = [] links = argv or ['all'] msg_flags = NLM_F_REQUEST | NLM_F_DUMP for index in links: msg = ifinfmsg() msg['family'] = kwarg.get('family', AF_UNSPEC) if index != 'all': msg['index'] = index msg_flags = NLM_F_REQUEST result.extend(self.nlm_request(msg, RTM_GETLINK, msg_flags)) return result
def put_dellink(self, msg, *argv, **kwarg): if self.ancient: # get the interface kind kind = compat_get_type(msg.get_attr('IFLA_IFNAME')) # not covered types pass to the system if kind not in ('bridge', 'bond'): return super(IPRSocketMixin, self).put(msg, *argv, **kwarg) ## # otherwise, create a valid answer -- # NLMSG_ERROR with code 0 (no error) ## # FIXME: intercept and return valid RTM_NEWLINK ## seq = kwarg.get('msg_seq', 0) response = ifinfmsg() response['header']['type'] = NLMSG_ERROR response['header']['sequence_number'] = seq # route the request if kind == 'bridge': compat_del_bridge(msg.get_attr('IFLA_IFNAME')) elif kind == 'bond': compat_del_bond(msg.get_attr('IFLA_IFNAME')) # while RTM_NEWLINK is not intercepted -- sleep time.sleep(_ANCIENT_BARRIER) response.encode() response = response.copy() self.backlog[seq] = [response] else: # else just send the packet super(IPRSocketMixin, self).put(msg, *argv, **kwarg)
def put_setlink(self, msg, *argv, **kwarg): # is it a port setup? master = msg.get_attr('IFLA_MASTER') if self.ancient and master is not None: seq = kwarg.get('msg_seq', 0) response = ifinfmsg() response['header']['type'] = NLMSG_ERROR response['header']['sequence_number'] = seq ifname = self.name_by_id(msg['index']) if master == 0: # port delete # 1. get the current master m = self.name_by_id(compat_get_master(ifname)) # 2. get the type of the master kind = compat_get_type(m) # 3. delete the port if kind == 'bridge': compat_del_bridge_port(m, ifname) elif kind == 'bond': compat_del_bond_port(m, ifname) else: # port add # 1. get the name of the master m = self.name_by_id(master) # 2. get the type of the master kind = compat_get_type(m) # 3. add the port if kind == 'bridge': compat_add_bridge_port(m, ifname) elif kind == 'bond': compat_add_bond_port(m, ifname) response.encode() response = response.copy() self.backlog[seq] = [response] super(IPRSocketMixin, self).put(msg, *argv, **kwarg)
def put_newlink(self, msg, *argv, **kwarg): if self.ancient: # get the interface kind linkinfo = msg.get_attr('IFLA_LINKINFO') if linkinfo is not None: kind = [x[1] for x in linkinfo['attrs'] if x[0] == 'IFLA_INFO_KIND'] if kind: kind = kind[0] # not covered types, pass to the system if kind not in ('bridge', 'bond'): return NetlinkSocket.put(self, msg, *argv, **kwarg) ## # otherwise, create a valid answer -- # NLMSG_ERROR with code 0 (no error) ## # FIXME: intercept and return valid RTM_NEWLINK ## response = ifinfmsg() seq = kwarg.get('msg_seq', 0) response['header']['type'] = NLMSG_ERROR response['header']['sequence_number'] = seq # route the request if kind == 'bridge': compat_create_bridge(msg.get_attr('IFLA_IFNAME')) elif kind == 'bond': compat_create_bond(msg.get_attr('IFLA_IFNAME')) # while RTM_NEWLINK is not intercepted -- sleep time.sleep(_ANCIENT_BARRIER) response.encode() self.backlog[seq] = [response] else: # else just send the packet NetlinkSocket.put(self, msg, *argv, **kwarg)
def get_links(self, *argv, **kwarg): ret = [] data = self._ifc.run() parsed = self._ifc.parse(data) for name, spec in parsed['links'].items(): msg = ifinfmsg().load(spec) del msg['value'] ret.append(msg) return ret
def _flush_mnl(self): if self.mnl is not None: # terminate the main loop for t in range(3): try: msg = ifinfmsg() msg['index'] = 1 msg.reset() self.mnl.put(msg, RTM_GETLINK) except Exception as e: log.error("shutdown error: %s", e)
def _GetAdaptersInfo(self): ret = {'interfaces': [], 'addresses': []} # prepare buffer buf = ctypes.create_string_buffer(15000) buf_len = ctypes.c_ulong(15000) (ctypes .windll .iphlpapi .GetAdaptersInfo(ctypes.byref(buf), ctypes.byref(buf_len))) adapter = IP_ADAPTER_INFO.from_address(ctypes.addressof(buf)) while True: mac = ':'.join(['%02x' % x for x in adapter.Address][:6]) ifname = (ctypes .string_at(ctypes.addressof(adapter.AdapterName)) .decode('utf-8')) spec = {'index': adapter.Index, 'attrs': (['IFLA_ADDRESS', mac], ['IFLA_IFNAME', ifname])} msg = ifinfmsg().load(spec) del msg['value'] ret['interfaces'].append(msg) ipaddr = adapter.IpAddressList while True: addr = (ctypes .string_at(ctypes.addressof(ipaddr.IpAddress)) .decode('utf-8')) mask = (ctypes .string_at(ctypes.addressof(ipaddr.IpMask)) .decode('utf-8')) spec = {'index': adapter.Index, 'family': AF_INET, 'prefixlen': dqn2int(mask), 'attrs': (['IFA_ADDRESS', addr], ['IFA_LOCAL', addr], ['IFA_LABEL', ifname])} msg = ifaddrmsg().load(spec) del msg['value'] ret['addresses'].append(msg) if ipaddr.Next: ipaddr = ipaddr.Next.contents else: break if adapter.Next: adapter = adapter.Next.contents else: break return ret
def fake_zero_if(self): url = 'https://github.com/svinota/pyroute2/issues/737' zero_if = ifinfmsg() zero_if['index'] = 0 zero_if['state'] = 'up' zero_if['flags'] = 1 zero_if['header']['flags'] = 2 zero_if['header']['type'] = 16 zero_if['header']['target'] = self.target zero_if['event'] = 'RTM_NEWLINK' zero_if['attrs'] = [('IFLA_IFNAME', url), ('IFLA_ADDRESS', '00:00:00:00:00:00')] self.evq.put([zero_if, ])
def get_links(self, *argv, **kwarg): ret = [] data = self._ifc.run() parsed = self._ifc.parse(data) for name, spec in parsed['links'].items(): msg = ifinfmsg().load(spec) msg['header']['type'] = RTM_NEWLINK del msg['value'] flags = msg['flags'] new_flags = 0 for value, name in IFF_VALUES.items(): if value & flags and name in IFF_NAMES: new_flags |= IFF_NAMES[name] msg['flags'] = new_flags ret.append(msg) return ret
def _GetAdaptersInfo(self): ret = {'interfaces': [], 'addresses': []} # prepare buffer buf = ctypes.create_string_buffer(15000) buf_len = ctypes.c_ulong(15000) (ctypes .windll .iphlpapi .GetAdaptersInfo(ctypes.byref(buf), ctypes.byref(buf_len))) adapter = IP_ADAPTER_INFO.from_address(ctypes.addressof(buf)) while True: mac = ':'.join(['%02x' % x for x in adapter.Address][:6]) ifname = ctypes.string_at(ctypes.addressof(adapter.AdapterName)) spec = {'index': adapter.Index, 'attrs': (['IFLA_ADDRESS', mac], ['IFLA_IFNAME', ifname])} msg = ifinfmsg().load(spec) del msg['value'] ret['interfaces'].append(msg) ipaddr = adapter.IpAddressList while True: addr = ctypes.string_at(ctypes.addressof(ipaddr.IpAddress)) mask = ctypes.string_at(ctypes.addressof(ipaddr.IpMask)) spec = {'index': adapter.Index, 'family': AF_INET, 'prefixlen': dqn2int(mask), 'attrs': (['IFA_ADDRESS', addr], ['IFA_LOCAL', addr], ['IFA_LABEL', ifname])} msg = ifaddrmsg().load(spec) del msg['value'] ret['addresses'].append(msg) if ipaddr.Next: ipaddr = ipaddr.Next.contents else: break if adapter.Next: adapter = adapter.Next.contents else: break return ret
def get_links(self, links=None, family=AF_UNSPEC): """ Get network interfaces sepcifications. """ result = [] links = links or ["all"] msg_flags = NLM_F_REQUEST | NLM_F_DUMP if type(links) not in (list, tuple, set): links = [links] for index in links: msg = ifinfmsg() msg["family"] = family if index != "all": msg["index"] = index msg_flags = NLM_F_REQUEST result.extend(self.nlm_request(msg, RTM_GETLINK, msg_flags)) return result
def proxy_dellink(imsg, nl): orig_msg = ifinfmsg(imsg.data) orig_msg.decode() # get full interface description msg = nl.get_links(orig_msg['index'])[0] msg['header']['type'] = orig_msg['header']['type'] # get the interface kind kind = None li = msg.get_attr('IFLA_LINKINFO') if li is not None: kind = li.get_attr('IFLA_INFO_KIND') # team interfaces can be stopped by a normal RTM_DELLINK if kind == 'bond' and not nl.capabilities['create_bond']: return compat_del_bond(msg) elif kind == 'bridge' and not nl.capabilities['create_bridge']: return compat_del_bridge(msg) return {'verdict': 'forward', 'data': imsg.data}
def proxy_newlink(imsg, nl): msg = ifinfmsg(imsg.data) msg.decode() kind = None # get the interface kind linkinfo = msg.get_attr('IFLA_LINKINFO') if linkinfo is not None: kind = [x[1] for x in linkinfo['attrs'] if x[0] == 'IFLA_INFO_KIND'] if kind: kind = kind[0] if kind == 'tuntap': return manage_tuntap(msg) elif kind == 'team': return manage_team(msg) elif kind == 'bond' and not nl.capabilities['create_bond']: return compat_create_bond(msg) elif kind == 'bridge' and not nl.capabilities['create_bridge']: return compat_create_bridge(msg) return {'verdict': 'forward', 'data': imsg.data}
def scan_netdevs(): scan = [] nl_socket = IPRSocket() msg = ifinfmsg() msg["family"] = socket.AF_UNSPEC msg["header"]["type"] = RTM_GETLINK msg["header"]["flags"] = NLM_F_REQUEST | NLM_F_DUMP msg["header"]["pid"] = os.getpid() msg["header"]["sequence_number"] = 1 msg.encode() nl_socket.sendto(msg.buf.getvalue(), (0,0)) finished = False while not finished: parts = nl_socket.get() for part in parts: if part["header"]["type"] in [NLMSG_DONE, NLMSG_ERROR]: finished = True continue if part["header"]["sequence_number"] != 1: continue if part["header"]["type"] == RTM_NEWLINK: new_link = {} new_link["netlink_msg"] = part new_link["index"] = part["index"] new_link["name"] = part.get_attr("IFLA_IFNAME") hwaddr = part.get_attr("IFLA_ADDRESS") new_link["hwaddr"] = normalize_hwaddr(hwaddr) scan.append(new_link) nl_socket.close() return scan
def link(self, command, **kwarg): ''' Link operations. * command -- set, add or delete * index -- device index * \*\*kwarg -- keywords, NLA Example:: x = 62 # interface index ip.link("set", index=x, state="down") ip.link("set", index=x, address="00:11:22:33:44:55", name="bala") ip.link("set", index=x, mtu=1000, txqlen=2000) ip.link("set", index=x, state="up") Keywords "state", "flags" and "mask" are reserved. State can be "up" or "down", it is a shortcut:: state="up": flags=1, mask=1 state="down": flags=0, mask=0 For more flags grep IFF in the kernel code, until we write human-readable flag resolver. Other keywords are from ifinfmsg.nla_map, look into the corresponding module. You can use the form "ifname" as well as "IFLA_IFNAME" and so on, so that's equal:: ip.link("set", index=x, mtu=1000) ip.link("set", index=x, IFLA_MTU=1000) You can also delete interface with:: ip.link("delete", index=x) ''' commands = {'set': RTM_SETLINK, 'add': RTM_NEWLINK, 'del': RTM_DELLINK, 'remove': RTM_DELLINK, 'delete': RTM_DELLINK} command = commands.get(command, command) msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL assert isinstance(kwarg['index'], int) msg = ifinfmsg() # index is required msg['index'] = kwarg['index'] flags = kwarg.pop('flags', 0) or 0 mask = kwarg.pop('mask', 0) or kwarg.pop('change', 0) or 0 if 'state' in kwarg: mask = 1 # IFF_UP mask if kwarg['state'].lower() == 'up': flags = 1 # 0 (down) or 1 (up) del kwarg['state'] msg['flags'] = flags msg['change'] = mask for key in kwarg: nla = type(msg).name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) def update_caps(e): # update capabilities, if needed if e.code == errno.EOPNOTSUPP: kind = None li = msg.get_attr('IFLA_LINKINFO') if li: attrs = li.get('attrs', []) for attr in attrs: if attr[0] == 'IFLA_INFO_KIND': kind = attr[1] if kind == 'bond' and self.capabilities['create_bond']: self.capabilities['create_bond'] = False return if kind == 'bridge' and self.capabilities['create_bridge']: self.capabilities['create_bridge'] = False return # let the exception to be forwarded return True return self.nlm_request(msg, msg_type=command, msg_flags=msg_flags, exception_catch=NetlinkError, exception_handler=update_caps)
def link(self, action, interface, **kwarg): """ Link operations. * action -- set, add or delete * interface -- device index * **kwarg -- keywords, NLA Example: dev = 62 # interface index ip.link("set", dev, state="down") ip.link("set", dev, address="00:11:22:33:44:55", name="bala") ip.link("set", dev, mtu=1000, txqlen=2000) ip.link("set", dev, state="up") Keywords "state", "flags" and "mask" are reserved. State can be "up" or "down", it is a shortcut: state="up": flags=1, mask=1 state="down": flags=0, mask=0 For more flags grep IFF_ in the kernel code, until we write human-readable flag resolver. Other keywords are from ifinfmsg.nla_map, look into the corresponding module. You can use the form "ifname" as well as "IFLA_IFNAME" and so on, so that's equal: ip.link("set", dev, mtu=1000) ip.link("set", dev, IFLA_MTU=1000) You can also delete interface with: ip.link("delete", dev) """ actions = { "set": RTM_SETLINK, # almost all operations "add": RTM_NEWLINK, # no idea, how to use it :) "delete": RTM_DELLINK, } # remove interface action = actions.get(action, action) msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL msg = ifinfmsg() msg["index"] = interface flags = kwarg.pop("flags", 0) mask = kwarg.pop("mask", 0) or kwarg.pop("change", 0) if "state" in kwarg: mask = 1 # IFF_UP mask if kwarg["state"].lower() == "up": flags = 1 # 0 (down) or 1 (up) del kwarg["state"] msg["flags"] = flags msg["change"] = mask for key in kwarg: nla = key.upper() if not nla.startswith("IFLA_"): nla = "IFLA_%s" % (nla) msg["attrs"].append((nla, kwarg[key])) return self.nlm_request(msg, msg_type=action, msg_flags=msg_flags)
def proxy_setlink(imsg, nl): def get_interface(index): msg = nl.get_links(index)[0] try: kind = msg.get_attr('IFLA_LINKINFO').get_attr('IFLA_INFO_KIND') except AttributeError: kind = 'unknown' return {'ifname': msg.get_attr('IFLA_IFNAME'), 'master': msg.get_attr('IFLA_MASTER'), 'kind': kind} msg = ifinfmsg(imsg.data) msg.decode() forward = True kind = None infodata = None ifname = msg.get_attr('IFLA_IFNAME') or \ get_interface(msg['index'])['ifname'] linkinfo = msg.get_attr('IFLA_LINKINFO') if linkinfo: kind = linkinfo.get_attr('IFLA_INFO_KIND') infodata = linkinfo.get_attr('IFLA_INFO_DATA') if kind in ('bond', 'bridge') and infodata is not None: code = 0 # if kind == 'bond': func = compat_set_bond elif kind == 'bridge': func = compat_set_bridge # for (cmd, value) in infodata.get('attrs', []): cmd = infodata.nla2name(cmd) code = func(ifname, cmd, value) or code # if code: err = OSError() err.errno = code raise err # is it a port setup? master = msg.get_attr('IFLA_MASTER') if master is not None: if master == 0: # port delete # 1. get the current master iface = get_interface(msg['index']) master = get_interface(iface['master']) cmd = 'del' else: # port add # 1. get the master master = get_interface(master) cmd = 'add' # 2. manage the port forward_map = {'team': manage_team_port, 'bridge': compat_bridge_port, 'bond': compat_bond_port} if master['kind'] in forward_map: func = forward_map[master['kind']] forward = func(cmd, master['ifname'], ifname, nl) if forward is not None: return {'verdict': 'forward', 'data': imsg.data}
def link(self, command, **kwarg): ''' Link operations. * command -- set, add or delete * index -- device index * \*\*kwarg -- keywords, NLA Example:: x = 62 # interface index ip.link("set", index=x, state="down") ip.link("set", index=x, address="00:11:22:33:44:55", name="bala") ip.link("set", index=x, mtu=1000, txqlen=2000) ip.link("set", index=x, state="up") Keywords "state", "flags" and "mask" are reserved. State can be "up" or "down", it is a shortcut:: state="up": flags=1, mask=1 state="down": flags=0, mask=0 For more flags grep IFF in the kernel code, until we write human-readable flag resolver. Other keywords are from ifinfmsg.nla_map, look into the corresponding module. You can use the form "ifname" as well as "IFLA_IFNAME" and so on, so that's equal:: ip.link("set", index=x, mtu=1000) ip.link("set", index=x, IFLA_MTU=1000) You can also delete interface with:: ip.link("delete", index=x) ''' commands = {'set': RTM_SETLINK, # almost all operations 'add': RTM_NEWLINK, # no idea, how to use it :) 'delete': RTM_DELLINK} # remove interface command = commands.get(command, command) msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL msg = ifinfmsg() # index is required msg['index'] = kwarg.get('index') flags = kwarg.pop('flags', 0) or 0 mask = kwarg.pop('mask', 0) or kwarg.pop('change', 0) or 0 if 'state' in kwarg: mask = 1 # IFF_UP mask if kwarg['state'].lower() == 'up': flags = 1 # 0 (down) or 1 (up) del kwarg['state'] msg['flags'] = flags msg['change'] = mask for key in kwarg: nla = ifinfmsg.name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) return self.nlm_request(msg, msg_type=command, msg_flags=msg_flags)
def link(self, command, **kwarg): ''' Link operations. * command -- set, add or delete * index -- device index * \*\*kwarg -- keywords, NLA (see ifinfmsg.py) Examples:: x = 62 # interface index ip.link("set", index=x, state="down") ip.link("set", index=x, address="00:11:22:33:44:55", name="bala") ip.link("set", index=x, mtu=1000, txqlen=2000) ip.link("set", index=x, state="up") Keywords "state", "flags" and "mask" are reserved. State can be "up" or "down", it is a shortcut:: state="up": flags=1, mask=1 state="down": flags=0, mask=0 For more flags grep IFF in the kernel code, until we write human-readable flag resolver. Other keywords are from ifinfmsg.nla_map, look into the corresponding module. You can use the form "ifname" as well as "IFLA_IFNAME" and so on, so that's equal:: ip.link("set", index=x, mtu=1000) ip.link("set", index=x, IFLA_MTU=1000) You can also delete interface with:: ip.link("delete", index=x) It is possible to manage bridge and bond attributes as well, but it will require to use the `IPLinkRequest()`:: from pyroute2 import IPLinkRequest idx = ip.link_lookup(ifname="br0")[0] ip.link("set", **IPLinkRequest({"index": idx, "kind": "bridge", "stp_state": 1})) Please notice, that the `kind` attribute in that case is required, since `IPLinkRequest()` needs the `kind` to build the NLA structure correctly. ''' commands = { 'set': RTM_SETLINK, 'add': RTM_NEWLINK, 'del': RTM_DELLINK, 'remove': RTM_DELLINK, 'delete': RTM_DELLINK } command = commands.get(command, command) msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL if not isinstance(kwarg['index'], int): raise ValueError('index should be int') msg = ifinfmsg() # index is required msg['index'] = kwarg['index'] flags = kwarg.pop('flags', 0) or 0 mask = kwarg.pop('mask', 0) or kwarg.pop('change', 0) or 0 if 'state' in kwarg: mask = 1 # IFF_UP mask if kwarg['state'].lower() == 'up': flags = 1 # 0 (down) or 1 (up) del kwarg['state'] msg['flags'] = flags msg['change'] = mask for key in kwarg: nla = type(msg).name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) def update_caps(e): # update capabilities, if needed if e.code == errno.EOPNOTSUPP: kind = None li = msg.get_attr('IFLA_LINKINFO') if li: attrs = li.get('attrs', []) for attr in attrs: if attr[0] == 'IFLA_INFO_KIND': kind = attr[1] if kind == 'bond' and self.capabilities['create_bond']: self.capabilities['create_bond'] = False return if kind == 'bridge' and self.capabilities['create_bridge']: self.capabilities['create_bridge'] = False return # let the exception to be forwarded return True return self.nlm_request(msg, msg_type=command, msg_flags=msg_flags, exception_catch=NetlinkError, exception_handler=update_caps)
def link(self, command, **kwarg): ''' Link operations. * command -- set, add or delete * index -- device index * \*\*kwarg -- keywords, NLA Example:: x = 62 # interface index ip.link("set", index=x, state="down") ip.link("set", index=x, address="00:11:22:33:44:55", name="bala") ip.link("set", index=x, mtu=1000, txqlen=2000) ip.link("set", index=x, state="up") Keywords "state", "flags" and "mask" are reserved. State can be "up" or "down", it is a shortcut:: state="up": flags=1, mask=1 state="down": flags=0, mask=0 For more flags grep IFF in the kernel code, until we write human-readable flag resolver. Other keywords are from ifinfmsg.nla_map, look into the corresponding module. You can use the form "ifname" as well as "IFLA_IFNAME" and so on, so that's equal:: ip.link("set", index=x, mtu=1000) ip.link("set", index=x, IFLA_MTU=1000) You can also delete interface with:: ip.link("delete", index=x) ''' commands = { 'set': RTM_SETLINK, 'add': RTM_NEWLINK, 'del': RTM_DELLINK, 'remove': RTM_DELLINK, 'delete': RTM_DELLINK } command = commands.get(command, command) msg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL msg = ifinfmsg() # index is required msg['index'] = kwarg.get('index') flags = kwarg.pop('flags', 0) or 0 mask = kwarg.pop('mask', 0) or kwarg.pop('change', 0) or 0 if 'state' in kwarg: mask = 1 # IFF_UP mask if kwarg['state'].lower() == 'up': flags = 1 # 0 (down) or 1 (up) del kwarg['state'] msg['flags'] = flags msg['change'] = mask for key in kwarg: nla = type(msg).name2nla(key) if kwarg[key] is not None: msg['attrs'].append([nla, kwarg[key]]) return self.nlm_request(msg, msg_type=command, msg_flags=msg_flags)
def release(self, complete=True): ''' Shutdown IPDB instance and sync the state. Since IPDB is asyncronous, some operations continue in the background, e.g. callbacks. So, prior to exit the script, it is required to properly shutdown IPDB. The shutdown sequence is not forced in an interactive python session, since it is easier for users and there is enough time to sync the state. But for the scripts the `release()` call is required. ''' with self._shutdown_lock: if self._stop: return self._stop = True if self.mnl is not None: # terminate the main loop for t in range(3): try: msg = ifinfmsg() msg['index'] = 1 msg.reset() self.mnl.put(msg, RTM_GETLINK) except Exception as e: log.warning("shutdown error: %s", e) # Just give up. # We can not handle this case if self._mthread is not None: self._mthread.join() if self.mnl is not None: self.mnl.close() self.mnl = None if complete or self._nl_own: self.nl.close() self.nl = None with self.exclusive: # collect all the callbacks for cuid in tuple(self._cb_threads): for t in tuple(self._cb_threads[cuid]): t.join() # flush all the objects def flush(idx): for key in tuple(idx.keys()): try: del idx[key] except KeyError: pass idx_list = [] if 'interfaces' in self._loaded: for (key, dev) in self.by_name.items(): try: # FIXME self.interfaces._detach(key, dev['index'], dev.nlmsg) except KeyError: pass idx_list.append(self.ipaddr) idx_list.append(self.neighbours) if 'routes' in self._loaded: idx_list.extend( [self.routes.tables[x] for x in self.routes.tables.keys()]) if 'rules' in self._loaded: idx_list.append(self.rules) for idx in idx_list: flush(idx)