Example #1
0
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
Example #2
0
    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)
Example #3
0
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
Example #4
0
    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
Example #5
0
    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)
Example #6
0
 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)
Example #7
0
    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
Example #8
0
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
Example #9
0
 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)
Example #10
0
 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
Example #11
0
 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)
Example #12
0
 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)
Example #13
0
    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
Example #14
0
 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, ])
Example #15
0
 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
Example #16
0
 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
Example #17
0
    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
Example #18
0
 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
Example #19
0
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}
Example #20
0
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}
Example #21
0
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}
Example #22
0
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
Example #23
0
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}
Example #24
0
    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)
Example #25
0
    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)
Example #26
0
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}
Example #27
0
    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)
Example #28
0
    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)
Example #29
0
    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)
Example #30
0
    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)
Example #31
0
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}