Ejemplo n.º 1
0
 def bind(self, groups=RTNL_GROUPS):
     '''
     It is required to call *IPRSocket.bind()* after creation.
     The call subscribes the NetlinkSocket to default RTNL
     groups (`RTNL_GROUPS`) or to a requested group set.
     '''
     NetlinkSocket.bind(self, groups)
Ejemplo n.º 2
0
 def bind(self, groups=RTNL_GROUPS):
     '''
     It is required to call *IPRSocket.bind()* after creation.
     The call subscribes the NetlinkSocket to default RTNL
     groups (`RTNL_GROUPS`) or to a requested group set.
     '''
     NetlinkSocket.bind(self, groups)
Ejemplo n.º 3
0
    def test_ports_auto(self):
        # create two sockets
        s1 = NetlinkSocket()
        s2 = NetlinkSocket()

        # both bind() should succeed
        s1.bind()
        s2.bind()

        # check that ports are different
        assert s1.port != s2.port

        s1.close()
        s2.close()
Ejemplo n.º 4
0
    def test_no_free_ports(self):
        require_user('root')
        # create and bind 1024 sockets
        ports = [NetlinkSocket() for x in range(1024)]
        for port in ports:
            port.bind()

        # create an extra socket
        fail = NetlinkSocket()
        try:
            # bind must fail with KeyError: no free ports available
            fail.bind()
        except KeyError:
            pass

        # cleanup
        for port in ports:
            port.close()

        try:
            # failed socket shouldn't permit close()
            fail.close()
        except AssertionError:
            pass
Ejemplo n.º 5
0
    def test_ports_fail(self):
        s1 = NetlinkSocket(port=0x10)
        s2 = NetlinkSocket(port=0x10)

        # check if ports are set
        assert s1.port == s2.port

        # bind the first socket, must succeed
        s1.bind()

        # bind the second, must fail
        try:
            s2.bind()
        except socket.error as e:
            # but it must fail only with errno == 98
            if e.errno == 98:
                pass

        # check the first socket is bound
        assert s1.getsockname()[0] != 0
        # check the second socket is not bound
        assert s2.getsockname()[0] == 0

        s1.close()
Ejemplo n.º 6
0
    def route_control(self, sock, data):
        # open envelope
        envelope = self.parse_envelope(data)
        pid = envelope['header']['pid']
        nonce = envelope['header']['sequence_number']
        src = envelope['src']
        dst = envelope['dst']
        data = io.BytesIO(envelope.get_attr('IPR_ATTR_CDATA'))
        cmd = self.parse_control(data)
        rsp = mgmtmsg()
        rsp['header']['type'] = NLMSG_CONTROL
        rsp['header']['sequence_number'] = nonce
        rsp['cmd'] = IPRCMD_ERR
        rsp['attrs'] = []

        if sock in self.controls:
            if cmd['cmd'] == IPRCMD_STOP:
                # Last 'hello'
                rsp['cmd'] = IPRCMD_ACK
                rsp.encode()
                ne = envmsg()
                ne['header']['sequence_number'] = nonce
                ne['header']['pid'] = pid
                ne['header']['type'] = NLMSG_TRANSPORT
                ne['header']['flags'] = 1
                ne['dst'] = src
                ne['src'] = dst
                ne['attrs'] = [['IPR_ATTR_CDATA', rsp.buf.getvalue()]]
                ne.encode()
                sock.send(ne.buf.getvalue())
                # Stop iothread -- shutdown sequence
                self._stop_event.set()
                self.queue.put(None)
                self.control.send(struct.pack('I', 4))
                return

            elif cmd['cmd'] == IPRCMD_RELOAD:
                # Reload io cycle
                self._reload_event.set()
                rsp['cmd'] = IPRCMD_ACK

            elif cmd['cmd'] == IPRCMD_SERVE:
                url = cmd.get_attr('IPR_ATTR_HOST')
                key = cmd.get_attr('IPR_ATTR_SSL_KEY')
                cert = cmd.get_attr('IPR_ATTR_SSL_CERT')
                ca = cmd.get_attr('IPR_ATTR_SSL_CA')
                (new_sock, addr) = _get_socket(url, server_side=True,
                                               key=key,
                                               cert=cert,
                                               ca=ca)
                new_sock.bind(addr)
                if new_sock.type == socket.SOCK_STREAM:
                    new_sock.listen(16)
                    self.servers.add(new_sock)
                self._rlist.add(new_sock)
                self.noop()
                rsp['cmd'] = IPRCMD_ACK

            elif cmd['cmd'] == IPRCMD_SHUTDOWN:
                url = cmd.get_attr('IPR_ATTR_HOST')
                for old_sock in tuple(self.servers):
                    if _repr_sockets([old_sock], 'local') == [url]:
                        self._rlist.remove(old_sock)
                        self.servers.remove(old_sock)
                        self.noop()
                        rsp['cmd'] = IPRCMD_ACK

            elif cmd['cmd'] == IPRCMD_DISCONNECT:
                # drop a connection, identified by an addr
                try:
                    addr = cmd.get_attr('IPR_ATTR_ADDR')
                    self.deregister_link(addr)
                    rsp['cmd'] = IPRCMD_ACK
                    self.noop()
                except Exception as e:
                    rsp['attrs'] = [['IPR_ATTR_ERROR', str(e)]]

            elif cmd['cmd'] == IPRCMD_CONNECT:
                # connect to a system
                try:
                    url = cmd.get_attr('IPR_ATTR_HOST')
                    key = cmd.get_attr('IPR_ATTR_SSL_KEY')
                    cert = cmd.get_attr('IPR_ATTR_SSL_CERT')
                    ca = cmd.get_attr('IPR_ATTR_SSL_CA')
                    target = urlparse.urlparse(url)
                    if target.scheme == 'netlink':
                        new_sock = NetlinkSocket(int(target.hostname))
                        new_sock.bind(int(target.port))
                        sys = cmd.get_attr('IPR_ATTR_SYS',
                                           self.default_sys[target.scheme])
                        send = lambda d, s:\
                            new_sock.sendto(self.gate_untag(d, s), (0, 0))
                        realm = self.alloc_addr(sys)
                        rsp['attrs'].append(['IPR_ATTR_ADDR', realm])
                        self.register_link(realm, new_sock, send)
                        rsp['cmd'] = IPRCMD_ACK
                        self.noop()
                    elif target.scheme == 'udp':
                        (new_sock, addr) = _get_socket(url,
                                                       server_side=False)
                        sys = cmd.get_attr('IPR_ATTR_SYS',
                                           self.default_sys[target.scheme])
                        send = lambda d, s:\
                            new_sock.sendto(self.gate_forward(d, s), addr)
                        realm = self.alloc_addr(sys)
                        rsp['attrs'].append(['IPR_ATTR_ADDR', realm])
                        self.register_link(realm, new_sock, send)
                        rsp['cmd'] = IPRCMD_ACK
                        self.noop()
                    else:
                        (new_sock, addr) = _get_socket(url,
                                                       server_side=False,
                                                       key=key,
                                                       cert=cert,
                                                       ca=ca)
                        new_sock.connect(addr)
                        sys = cmd.get_attr('IPR_ATTR_SYS',

                                           self.default_sys[target.scheme])
                        send = lambda d, s:\
                            new_sock.send(self.gate_forward(d, s))
                        realm = self.alloc_addr(sys)
                        rsp['attrs'].append(['IPR_ATTR_ADDR', realm])
                        self.register_link(realm, new_sock, send)
                        rsp['cmd'] = IPRCMD_ACK
                        self.noop()
                except Exception:
                    rsp['attrs'].append(['IPR_ATTR_ERROR',
                                         traceback.format_exc()])
        if sock in self.clients:
            if cmd['cmd'] == IPRCMD_SUBSCRIBE:
                try:
                    cid = self._cid.pop()
                    self.subscribe[cid] = {'socket': sock,
                                           'keys': []}
                    for key in cmd.get_attrs('IPR_ATTR_KEY'):
                        target = (key['offset'],
                                  key['key'],
                                  key['mask'])
                        self.subscribe[cid]['keys'].append(target)
                    rsp['cmd'] = IPRCMD_ACK
                    rsp['attrs'].append(['IPR_ATTR_CID', cid])
                except Exception:
                    rsp['attrs'].append(['IPR_ATTR_ERROR',
                                         traceback.format_exc()])

            elif cmd['cmd'] == IPRCMD_UNSUBSCRIBE:
                cid = cmd.get_attr('IPR_ATTR_CID')
                if cid in self.subscribe:
                    del self.subscribe[cid]
                    self._cid.append(cid)
                    rsp['cmd'] = IPRCMD_ACK

            elif cmd['cmd'] == IPRCMD_REGISTER:
                # auth request
                secret = cmd.get_attr('IPR_ATTR_SECRET')
                if secret == self.secret:
                    self.controls.add(sock)
                    rsp['cmd'] = IPRCMD_ACK

        rsp.encode()
        ne = envmsg()
        ne['header']['sequence_number'] = nonce
        ne['header']['pid'] = pid
        ne['header']['type'] = NLMSG_TRANSPORT
        ne['header']['flags'] = 1
        ne['dst'] = src
        ne['src'] = dst
        ne['attrs'] = [['IPR_ATTR_CDATA', rsp.buf.getvalue()]]
        ne.encode()
        sock.send(ne.buf.getvalue())
Ejemplo n.º 7
0
def command(broker, sock, env, cmd, rsp):
    url = cmd.get_attr('IPR_ATTR_HOST')
    key = cmd.get_attr('IPR_ATTR_SSL_KEY')
    cert = cmd.get_attr('IPR_ATTR_SSL_CERT')
    ca = cmd.get_attr('IPR_ATTR_SSL_CA')

    target = urlparse.urlparse(url)
    peer = broker.addr
    remote = False
    established = False
    uid = str(uuid.uuid4())

    route = broker.route

    if url in broker.providers:
        new_sock = broker.providers[url]
        established = True
        gate = lambda d, s:\
            new_sock.send(broker.gate_forward(d, s))

    elif target.scheme == 'netlink':
        res = target.path.split("/")
        new_sock = NetlinkSocket(int(res[1]))
        new_sock.bind(int(res[2]))
        gate = lambda d, s:\
            new_sock.sendto(broker.gate_untag(d, s), (0, 0))
        route = broker.route_netlink

    elif target.scheme == 'udp':
        (new_sock, addr) = get_socket(url, server=False)
        gate = lambda d, s:\
            new_sock.sendto(broker.gate_forward(d, s), addr)
        remote = True

    else:
        (new_sock, addr) = get_socket(url,
                                      server=False,
                                      key=key,
                                      cert=cert,
                                      ca=ca)
        try:
            new_sock.connect(addr)
        except Exception:
            new_sock.close()
            raise
        remote = True
        # stream sockets provide the peer announce
        buf = io.BytesIO()
        buf.length = buf.write(new_sock.recv(16384))
        buf.seek(0)
        msg = envmsg(buf)
        msg.decode()
        buf = io.BytesIO()
        buf.length = buf.write(msg.get_attr('IPR_ATTR_CDATA'))
        buf.seek(0)
        msg = mgmtmsg(buf)
        msg.decode()
        peer = msg.get_attr('IPR_ATTR_ADDR')

        gate = lambda d, s:\
            new_sock.send(broker.gate_forward(d, s))

    port = broker.alloc_addr()
    link = broker.register_link(uid=uid,
                                port=port,
                                sock=new_sock,
                                established=established,
                                remote=remote)
    link.gate = gate
    broker.discover[target.path] = port
    rsp['attrs'].append(['IPR_ATTR_UUID', uid])
    rsp['attrs'].append(['IPR_ATTR_ADDR', peer])
    try:
        broker.ioloop.register(new_sock, route,
                               defer=True)
    except Exception as e:
        if e.errno != errno.EEXIST:
            raise e
Ejemplo n.º 8
0
def command(broker, sock, env, cmd, rsp):
    url = cmd.get_attr('IPR_ATTR_HOST')
    key = cmd.get_attr('IPR_ATTR_SSL_KEY')
    cert = cmd.get_attr('IPR_ATTR_SSL_CERT')
    ca = cmd.get_attr('IPR_ATTR_SSL_CA')

    target = urlparse.urlparse(url)
    peer = broker.addr
    remote = False
    established = False
    uid = str(uuid.uuid4())

    route = broker.route

    if url in broker.providers:
        new_sock = broker.providers[url]
        established = True
        gate = lambda d, s:\
            new_sock.send(broker.gate_forward(d, s))

    elif target.scheme == 'netlink':
        res = target.path.split("/")
        new_sock = NetlinkSocket(int(res[1]))
        new_sock.bind(int(res[2]))
        gate = lambda d, s:\
            new_sock.sendto(broker.gate_untag(d, s), (0, 0))
        route = broker.route_netlink

    elif target.scheme == 'udp':
        (new_sock, addr) = get_socket(url, server=False)
        gate = lambda d, s:\
            new_sock.sendto(broker.gate_forward(d, s), addr)
        remote = True

    else:
        (new_sock, addr) = get_socket(url,
                                      server=False,
                                      key=key,
                                      cert=cert,
                                      ca=ca)
        try:
            new_sock.connect(addr)
        except Exception:
            new_sock.close()
            raise
        remote = True
        # stream sockets provide the peer announce
        buf = io.BytesIO()
        buf.length = buf.write(new_sock.recv(16384))
        buf.seek(0)
        msg = envmsg(buf)
        msg.decode()
        buf = io.BytesIO()
        buf.length = buf.write(msg.get_attr('IPR_ATTR_CDATA'))
        buf.seek(0)
        msg = mgmtmsg(buf)
        msg.decode()
        peer = msg.get_attr('IPR_ATTR_ADDR')

        gate = lambda d, s:\
            new_sock.send(broker.gate_forward(d, s))

    port = broker.alloc_addr()
    link = broker.register_link(uid=uid,
                                port=port,
                                sock=new_sock,
                                established=established,
                                remote=remote)
    link.gate = gate
    broker.discover[target.path] = port
    rsp['attrs'].append(['IPR_ATTR_UUID', uid])
    rsp['attrs'].append(['IPR_ATTR_ADDR', peer])
    try:
        broker.ioloop.register(new_sock, route, defer=True)
    except Exception as e:
        if e.errno != errno.EEXIST:
            raise e