示例#1
0
def main():
    """Main function called upon script execution."""
    # First open a socket to the kernel. Same one used for sending and receiving.
    sk = nl_socket_alloc()  # Creates an `nl_sock` instance.
    ret = nl_connect(sk,
                     NETLINK_ROUTE)  # Create file descriptor and bind socket.
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('nl_connect() returned {0} ({1})'.format(ret, reason))

    # Next we send the request to the kernel.
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    ret = nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, rt_hdr,
                         rt_hdr.SIZEOF)
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('nl_send_simple() returned {0} ({1})'.format(ret, reason))
    print('Sent {0} bytes to the kernel.'.format(ret))

    # Finally we'll retrieve the kernel's answer, process it, and call any callbacks attached to the `nl_sock` instance.
    nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, callback,
                        None)  # Add callback to the `nl_sock` instance.
    ret = nl_recvmsgs_default(
        sk)  # Get kernel's answer, and call attached callbacks.
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('nl_recvmsgs_default() returned {0} ({1})'.format(
            ret, reason))
示例#2
0
def ncsi_set_interface(ifindex, package, channel):

    sk = nl_socket_alloc()
    ret = genl_connect(sk)
    if ret < 0:
        return ret

    driver_id = genl_ctrl_resolve(sk, b'NCSI')
    if driver_id < 0:
        return driver_id

    msg = nlmsg_alloc()
    if package or package and channel:
        genlmsg_put(msg, 0, 0, driver_id, 0, 0, NCSI_CMD_SET_INTERFACE, 0)
        ret = nla_put_u32(msg, NCSI_ATTR_PACKAGE_ID, int(package))
        if channel:
            ret = nla_put_u32(msg, NCSI_ATTR_CHANNEL_ID, int(channel))
    else:
        genlmsg_put(msg, 0, 0, driver_id, 0, 0, NCSI_CMD_CLEAR_INTERFACE, 0)
    ret = nla_put_u32(msg, NCSI_ATTR_IFINDEX, ifindex)

    nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, dump_callback, None)

    ret = nl_send_auto(sk, msg)
    if ret < 0:
        print("Failed to send message: {}".format(ret))
        return ret

    ret = nl_recvmsgs_default(sk)  # blocks
    if ret < 0:
        reason = errmsg[abs(ret)]
        print("recvmsg returned {}, {}".format(ret, reason))
示例#3
0
def test_s_proto():
    """Test socket protocol."""
    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    msg = nlmsg_alloc_simple(0, 0)
    assert -1 == msg.nm_protocol

    nl_complete_msg(sk, msg)
    assert NETLINK_ROUTE == msg.nm_protocol
    nl_socket_free(sk)
示例#4
0
def test_nm_protocol():
    """Test protocol."""
    sk = nl_socket_alloc()
    msg = nlmsg_alloc_simple(0, 0)
    assert -1 == msg.nm_protocol

    msg.nm_protocol = 10
    nl_complete_msg(sk, msg)
    assert 10 == msg.nm_protocol
    nl_socket_free(sk)
示例#5
0
def test_nlmsg_pid():
    """Test pid."""
    sk = nl_socket_alloc()
    msg = nlmsg_alloc_simple(0, 0)
    assert 0 == msg.nm_nlh.nlmsg_pid

    msg.nm_nlh.nlmsg_pid = 10
    nl_complete_msg(sk, msg)
    assert 10 == msg.nm_nlh.nlmsg_pid
    nl_socket_free(sk)
示例#6
0
def scan_for_wifi_networks(interface):
    def db_to_percent(db):
        return 2.0 * (db + 100)

    pack = struct.pack('16sI', interface, 0)
    sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        info = struct.unpack('16sI', fcntl.ioctl(sk.fileno(), 0x8933, pack))
    except OSError:
        raise RuntimeError(
            'Wireless interface {0} does not exist.'.format(interface))
    finally:
        sk.close()
    if_index = int(info[1])

    # Next open a socket to the kernel and bind to it. Same one used for sending and receiving.
    sk = nl_socket_alloc()  # Creates an `nl_sock` instance.
    if not genl_connect(sk) == 0:  # Create file descriptor and bind socket.
        raise RuntimeError('Could not communicate with kernel via nl80211')
    driver_id = genl_ctrl_resolve(sk, b'nl80211')
    mcid = genl_ctrl_resolve_grp(sk, b'nl80211', b'scan')

    results = dict()
    for i in range(2, -1, -1):  # Three tries on errors.
        ret = do_scan_trigger(sk, if_index, driver_id, mcid)
        if ret < 0:
            #timeout
            time.sleep(5)
            continue
        ret = do_scan_results(sk, if_index, driver_id, results)
        if ret < 0:
            time.sleep(5)
            continue
        break
    if not results:
        return {}

    ap_list = []
    for _, f in results.items():
        ssid = str(f['information_elements']['SSID']).encode("ascii", "ignore")
        if len(ssid) == 0:
            continue
        if u"\x00".encode("ascii", "ignore") in ssid:
            continue
        print(ssid, len(ssid))
        # pp.pprint(f['information_elements'])
        security = 0
        if 'RSN' in f['information_elements']:
            security = 1
        signal_strength = db_to_percent(f['signal'])
        if signal_strength <= 25:
            continue
        network_tuple = [ssid, security, signal_strength]
        ap_list.append(network_tuple)
    return ap_list
    def scan_all_access_points(self):
        # Scan for access points within reach

        # First get the wireless interface index.
        pack = struct.pack('16sI', self.interface_name.encode('ascii'), 0)
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            info = struct.unpack('16sI',
                                 fcntl.ioctl(sock.fileno(), 0x8933, pack))
        except OSError:
            return logger.warning('Wireless interface {0}\
                    does not exist.'.format(self.interface_name))
        finally:
            sock.close()
        if_index = int(info[1])

        # Next open a socket to the kernel and bind to it. Same one used for
        # sending and receiving.
        self._nl_sock = nl_socket_alloc()  # Creates an `nl_sock` instance.
        genl_connect(self._nl_sock)  # Create file descriptor and bind socket.
        logger.debug('Finding the nl80211 driver ID...')
        driver_id = genl_ctrl_resolve(self._nl_sock, b'nl80211')
        logger.debug('Finding the nl80211 scanning group ID...')
        mcid = genl_ctrl_resolve_grp(self._nl_sock, b'nl80211', b'scan')

        # Scan for access points 1 or more (if requested) times.
        results = dict()
        for i in range(2, -1, -1):  # Three tries on errors.
            ret = self._do_scan_trigger(if_index, driver_id, mcid)
            if ret < 0:
                logger.debug('do_scan_trigger() returned {0},'
                             'retrying in 5 seconds({1}).'.format(ret, i))
                time.sleep(5)
            ret = self._do_scan_results(if_index, driver_id, results)
            if ret < 0:
                logger.debug('do_scan_results() returned {0},'
                             'retrying in 5 seconds ({1}).'.format(ret, i))
                time.sleep(5)
                continue
            break
        if not results:
            logger.debug('No access points detected.')
            return []

        logger.debug('Found {0} access points:'.format(len(results)))

        # Convert timedelta to integer to avoid
        #    TypeError: Object of type timedelta is not JSON serializable
        for ap in results:
            for prop in results[ap]:
                if isinstance(results[ap][prop], datetime.timedelta):
                    results[ap][prop] = int(
                        results[ap][prop].microseconds) / 1000

        return results
示例#8
0
def test_nl_recv():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        // Send data to the kernel.
        struct nl_sock *sk = nl_socket_alloc();
        sk->s_seq_next = 0;
        nl_connect(sk, NETLINK_ROUTE);
        int ret = nl_send_simple(sk, 0, NLM_F_REQUEST, NULL, 0);
        printf("Bytes Sent: %d\n", ret);

        // Retrieve kernel's response.
        // nl_recvmsgs_default(sk);
        // return 0;
        unsigned char *buf = NULL;
        struct sockaddr_nl nla = {0};
        printf("%d == nla.nl_family\n", nla.nl_family);
        int n = nl_recv(sk, &nla, &buf, NULL);
        printf("Bytes Recv: %d\n", n);

        int i = 0; for (i = 0; i<n; i++) printf("%02x", buf[i]); printf("\n");
        printf("%d == nla.nl_family\n", nla.nl_family);
        return 0;
    }
    // Expected output:
    // Bytes Sent: 16
    // 0 == nla.nl_family
    // Bytes Recv: 36
    // 240000000200000000000000844c000000000000100000000000050000000000844c0000
    // 16 == nla.nl_family
    // Output delta:
    // 240000000200000000000000ac4e000000000000100000000000050000000000ac4e0000
    """
    sk = nl_socket_alloc()
    sk.s_seq_next = 0
    nl_connect(sk, NETLINK_ROUTE)
    assert 16 == nl_send_simple(sk, 0, NLM_F_REQUEST, None)

    buf = bytearray()
    nla = sockaddr_nl()
    assert 0 == nla.nl_family
    assert 36 == nl_recv(sk, nla, buf, None)
    nl_socket_free(sk)

    buf_hex = binascii.hexlify(buffer(buf)).decode('ascii')
    assert re.match(
        r'240000000200000000000000....000000000000100000000000050000000000....0000',
        buf_hex)
    assert 16 == nla.nl_family
def main():
    """Main function called upon script execution."""
    # First get the wireless interface index.
    pack = struct.pack('16sI', OPTIONS['<interface>'].encode('ascii'), 0)
    sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        info = struct.unpack('16sI', fcntl.ioctl(sk.fileno(), 0x8933, pack))
    except OSError:
        return error('Wireless interface {0} does not exist.'.format(OPTIONS['<interface>']))
    finally:
        sk.close()
    if_index = int(info[1])

    # Next open a socket to the kernel and bind to it. Same one used for sending and receiving.
    sk = nl_socket_alloc()  # Creates an `nl_sock` instance.
    ok(0, genl_connect, sk)  # Create file descriptor and bind socket.
    _LOGGER.debug('Finding the nl80211 driver ID...')
    driver_id = ok(0, genl_ctrl_resolve, sk, b'nl80211')
    _LOGGER.debug('Finding the nl80211 scanning group ID...')
    mcid = ok(0, genl_ctrl_resolve_grp, sk, b'nl80211', b'scan')

    # Scan for access points 1 or more (if requested) times.
    if not OPTIONS['--no-sudo']:
        print('Scanning for access points, may take about 8 seconds...')
    else:
        print("Attempting to read results of previous scan.")
    results = dict()
    for i in range(2, -1, -1):  # Three tries on errors.
        if not OPTIONS['--no-sudo']:
            ret = ok(i, do_scan_trigger, sk, if_index, driver_id, mcid)
            if ret < 0:
                _LOGGER.warning('do_scan_trigger() returned %d, retrying in 5 seconds.', ret)
                time.sleep(5)
                continue
        ret = ok(i, do_scan_results, sk, if_index, driver_id, results)
        if ret < 0:
            _LOGGER.warning('do_scan_results() returned %d, retrying in 5 seconds.', ret)
            time.sleep(5)
            continue
        break
    if not results:
        print('No access points detected.')
        return

    # Print results.
    print('Found {0} access points:'.format(len(results)))
    print_table(results.values())
    best_channel = get_best_channel(results)
    print("Best Channel: {}".format(best_channel))
    if best_channel:
        build_hostapd_config(best_channel)
        sys.exit(0)
    else:
        sys.exit(1)
示例#10
0
    def update_iface_details(self, cmd):
        # Send a command specified by CMD to the kernel and attach a callback to
        # process the returned values into our own datastructure

        self._nl_sock = nl_socket_alloc()  # Creates an `nl_sock` instance.
        # Create file descriptor and bind socket.
        ret = genl_connect(self._nl_sock)
        if ret < 0:
            reason = errmsg[abs(ret)]
            logger.error('genl_connect() returned {0} ({1})'.format(
                ret, reason))
            return {}

        # Now get the nl80211 driver ID. Handle errors here.
        # Find the nl80211 driver ID.
        driver_id = genl_ctrl_resolve(self._nl_sock, b'nl80211')
        if driver_id < 0:
            reason = errmsg[abs(driver_id)]
            logger.error('genl_ctrl_resolve() returned {0} ({1})'.format(
                driver_id, reason))
            return {}

        # Setup the Generic Netlink message.
        msg = nlmsg_alloc()  # Allocate a message.
        if self.if_idx == None:
            # Ask kernel to send info for all wireless interfaces.
            genlmsg_put(msg, 0, 0, driver_id, 0, NLM_F_DUMP,
                        nl80211.NL80211_CMD_GET_INTERFACE, 0)
        else:
            genlmsg_put(msg, 0, 0, driver_id, 0, NLM_F_DUMP, cmd, 0)
            # This is the interface we care about.
            nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX, self.if_idx)
            #nla_put_u32(msg, nl80211.NL80211_ATTR_MAC, 2199023255552)

        # Add the callback function to the self._nl_sock.
        nl_socket_modify_cb(self._nl_sock, NL_CB_VALID, NL_CB_CUSTOM,
                            self._iface_callback, False)

        # Now send the message to the kernel, and get its response,
        # automatically calling the callback.
        ret = nl_send_auto(self._nl_sock, msg)
        if ret < 0:
            reason = errmsg[abs(ret)]
            logger.error('nl_send_auto() returned {0} ({1})'.format(
                ret, reason))
            return {}
        logger.debug('Sent {0} bytes to the kernel.'.format(ret))
        # Blocks until the kernel replies. Usually it's instant.
        ret = nl_recvmsgs_default(self._nl_sock)
        if ret < 0:
            reason = errmsg[abs(ret)]
            logger.error('nl_recvmsgs_default() returned {0} ({1})'.format(
                ret, reason))
            return {}
示例#11
0
def test_nl_recv():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        // Send data to the kernel.
        struct nl_sock *sk = nl_socket_alloc();
        sk->s_seq_next = 0;
        nl_connect(sk, NETLINK_ROUTE);
        int ret = nl_send_simple(sk, 0, NLM_F_REQUEST, NULL, 0);
        printf("Bytes Sent: %d\n", ret);

        // Retrieve kernel's response.
        // nl_recvmsgs_default(sk);
        // return 0;
        unsigned char *buf = NULL;
        struct sockaddr_nl nla = {0};
        printf("%d == nla.nl_family\n", nla.nl_family);
        int n = nl_recv(sk, &nla, &buf, NULL);
        printf("Bytes Recv: %d\n", n);

        int i = 0; for (i = 0; i<n; i++) printf("%02x", buf[i]); printf("\n");
        printf("%d == nla.nl_family\n", nla.nl_family);
        return 0;
    }
    // Expected output:
    // Bytes Sent: 16
    // 0 == nla.nl_family
    // Bytes Recv: 36
    // 240000000200000000000000844c000000000000100000000000050000000000844c0000
    // 16 == nla.nl_family
    // Output delta:
    // 240000000200000000000000ac4e000000000000100000000000050000000000ac4e0000
    """
    sk = nl_socket_alloc()
    sk.s_seq_next = 0
    nl_connect(sk, NETLINK_ROUTE)
    assert 16 == nl_send_simple(sk, 0, NLM_F_REQUEST, None)

    buf = bytearray()
    nla = sockaddr_nl()
    assert 0 == nla.nl_family
    assert 36 == nl_recv(sk, nla, buf, None)
    nl_socket_free(sk)

    buf_hex = binascii.hexlify(buffer(buf)).decode('ascii')
    assert re.match(r'240000000200000000000000....000000000000100000000000050000000000....0000', buf_hex)
    assert 16 == nla.nl_family
示例#12
0
def test_dissect(monkeypatch):
    r"""Diff of C code (from test_bare()) to test against.

    --- test_bare.c	2015-02-08 12:43:15.543135855 -0800
    +++ test_dissect.c	2015-02-08 13:25:31.375715668 -0800
    @@ -16,8 +16,22 @@
             sk->s_local.nl_pid = 0;
             sk->s_seq_next = 0;

    -        int ret = nl_send_simple(sk, RTM_GETLINK, 0, NULL, 0);
    +        struct rtgenmsg rt_hdr = { .rtgen_family = AF_PACKET, };
    +        struct nl_msg *msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP);
    +        nlmsg_append(msg, &rt_hdr, sizeof(rt_hdr), NLMSG_ALIGNTO);
    +        nl_complete_msg(sk, msg);
    +        struct nlmsghdr *nlh = nlmsg_hdr(msg);

    +        printf("%d == nlh->nlmsg_len\n", nlh->nlmsg_len);
    +        printf("%d == nlh->nlmsg_type\n", nlh->nlmsg_type);
    +        printf("%d == nlh->nlmsg_flags\n", nlh->nlmsg_flags);
    +        printf("%d == nlh->nlmsg_seq\n", nlh->nlmsg_seq);
    +        printf("%d == nlh->nlmsg_pid\n", nlh->nlmsg_pid);
    +
    +        struct iovec iov = { .iov_base = nlh, .iov_len = nlh->nlmsg_len };
    +        struct msghdr hdr = { .msg_iov = &iov, .msg_iovlen = 1, };
    +
    +        int ret = nl_sendmsg(sk, msg, &hdr);
             printf("Bytes: %d\n", ret);
             return 0;
         }
    """
    monkeypatch.setattr(libnl.socket_, 'generate_local_port', lambda: 0)

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.s_local.nl_pid = 0
    sk.s_seq_next = 0

    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP)
    nlmsg_append(msg, rt_hdr, rt_hdr.SIZEOF, NLMSG_ALIGNTO)
    nl_complete_msg(sk, msg)
    nlh = nlmsg_hdr(msg)

    assert 20 == nlh.nlmsg_len
    assert 18 == nlh.nlmsg_type
    assert 773 == nlh.nlmsg_flags
    assert 0 == nlh.nlmsg_seq
    assert 0 == nlh.nlmsg_pid

    assert b'FAAAABIABQMAAAAAAAAAABEAAAA=' == base64.b64encode(
        buffer(nlh.bytearray[:nlh.nlmsg_len]))
    nl_socket_free(sk)
示例#13
0
def test_dissect(monkeypatch):
    r"""Diff of C code (from test_bare()) to test against.

    --- test_bare.c	2015-02-08 12:43:15.543135855 -0800
    +++ test_dissect.c	2015-02-08 13:25:31.375715668 -0800
    @@ -16,8 +16,22 @@
             sk->s_local.nl_pid = 0;
             sk->s_seq_next = 0;

    -        int ret = nl_send_simple(sk, RTM_GETLINK, 0, NULL, 0);
    +        struct rtgenmsg rt_hdr = { .rtgen_family = AF_PACKET, };
    +        struct nl_msg *msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP);
    +        nlmsg_append(msg, &rt_hdr, sizeof(rt_hdr), NLMSG_ALIGNTO);
    +        nl_complete_msg(sk, msg);
    +        struct nlmsghdr *nlh = nlmsg_hdr(msg);

    +        printf("%d == nlh->nlmsg_len\n", nlh->nlmsg_len);
    +        printf("%d == nlh->nlmsg_type\n", nlh->nlmsg_type);
    +        printf("%d == nlh->nlmsg_flags\n", nlh->nlmsg_flags);
    +        printf("%d == nlh->nlmsg_seq\n", nlh->nlmsg_seq);
    +        printf("%d == nlh->nlmsg_pid\n", nlh->nlmsg_pid);
    +
    +        struct iovec iov = { .iov_base = nlh, .iov_len = nlh->nlmsg_len };
    +        struct msghdr hdr = { .msg_iov = &iov, .msg_iovlen = 1, };
    +
    +        int ret = nl_sendmsg(sk, msg, &hdr);
             printf("Bytes: %d\n", ret);
             return 0;
         }
    """
    monkeypatch.setattr(libnl.socket_, 'generate_local_port', lambda: 0)

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.s_local.nl_pid = 0
    sk.s_seq_next = 0

    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP)
    nlmsg_append(msg, rt_hdr, rt_hdr.SIZEOF, NLMSG_ALIGNTO)
    nl_complete_msg(sk, msg)
    nlh = nlmsg_hdr(msg)

    assert 20 == nlh.nlmsg_len
    assert 18 == nlh.nlmsg_type
    assert 773 == nlh.nlmsg_flags
    assert 0 == nlh.nlmsg_seq
    assert 0 == nlh.nlmsg_pid

    assert b'FAAAABIABQMAAAAAAAAAABEAAAA=' == base64.b64encode(buffer(nlh.bytearray[:nlh.nlmsg_len]))
    nl_socket_free(sk)
示例#14
0
def main():
    """Main function called upon script execution."""
    # First get the wireless interface index.
    if OPTIONS['<interface>']:
        pack = struct.pack('16sI', OPTIONS['<interface>'].encode('ascii'), 0)
        sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            info = struct.unpack('16sI', fcntl.ioctl(sk.fileno(), 0x8933, pack))
        except OSError:
            return error('Wireless interface {0} does not exist.'.format(OPTIONS['<interface>']))
        finally:
            sk.close()
        if_index = int(info[1])
    else:
        if_index = -1

    # Then open a socket to the kernel. Same one used for sending and receiving.
    sk = nl_socket_alloc()  # Creates an `nl_sock` instance.
    ret = genl_connect(sk)  # Create file descriptor and bind socket.
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('genl_connect() returned {0} ({1})'.format(ret, reason))

    # Now get the nl80211 driver ID. Handle errors here.
    driver_id = genl_ctrl_resolve(sk, b'nl80211')  # Find the nl80211 driver ID.
    if driver_id < 0:
        reason = errmsg[abs(driver_id)]
        return error('genl_ctrl_resolve() returned {0} ({1})'.format(driver_id, reason))

    # Setup the Generic Netlink message.
    msg = nlmsg_alloc()  # Allocate a message.
    if OPTIONS['<interface>']:
        genlmsg_put(msg, 0, 0, driver_id, 0, 0, nl80211.NL80211_CMD_GET_INTERFACE, 0)  # Tell kernel: send iface info.
        nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX, if_index)  # This is the interface we care about.
    else:
        # Ask kernel to send info for all wireless interfaces.
        genlmsg_put(msg, 0, 0, driver_id, 0, NLM_F_DUMP, nl80211.NL80211_CMD_GET_INTERFACE, 0)

    # Add the callback function to the nl_sock.
    has_printed = list()
    nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, callback, has_printed)

    # Now send the message to the kernel, and get its response, automatically calling the callback.
    ret = nl_send_auto(sk, msg)
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('nl_send_auto() returned {0} ({1})'.format(ret, reason))
    print('Sent {0} bytes to the kernel.'.format(ret))
    ret = nl_recvmsgs_default(sk)  # Blocks until the kernel replies. Usually it's instant.
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('nl_recvmsgs_default() returned {0} ({1})'.format(ret, reason))
示例#15
0
def test_error_nle_bad_sock():
    """Test for NLE_BAD_SOCK."""
    sk = nl_socket_alloc()
    msg = nlmsg_alloc_simple(0, 0)
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    nl_complete_msg(sk, msg)

    message = 'Hello World!\n'
    iov = bytes(message.encode('ascii'))
    hdr = msghdr(msg_iov=iov)

    assert -3 == nl_sendmsg(sk, msg, hdr)
示例#16
0
def test_default(tcp_server):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0)
    // (nc -l 2000 &); sleep 0.1; ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        struct sockaddr_in sin = { .sin_port = htons(2000), .sin_family = AF_INET, };
        sin.sin_addr.s_addr = inet_addr("127.0.0.1");
        int fd = socket(AF_INET, SOCK_STREAM, 0);
        connect(fd, (struct sockaddr *) &sin, sizeof(sin));

        struct nl_sock *sk = nl_socket_alloc();
        struct nl_msg *msg = nlmsg_alloc_simple(0, 0);
        nl_connect(sk, NETLINK_ROUTE);
        sk->s_fd = fd;
        sk->s_local.nl_pid = 0;
        nl_complete_msg(sk, msg);

        char message[] = "Hello World!\n";
        struct iovec iov = { .iov_base = message, .iov_len = sizeof(message), };
        struct msghdr hdr = { .msg_iov = &iov, .msg_iovlen = 1, };

        int ret = nl_sendmsg(sk, msg, &hdr);
        printf("Bytes: %d\n", ret);  // 14
        return 0;
    }
    // Expected bash output:
    // Hello World!
    // Bytes: 14
    """
    sk = nl_socket_alloc()
    msg = nlmsg_alloc_simple(0, 0)
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.socket_instance.connect(tcp_server.server.server_address)
    sk.s_local.nl_pid = 0
    nl_complete_msg(sk, msg)

    message = 'Hello World!\n\0'
    iov = bytes(message.encode('ascii'))
    hdr = msghdr(msg_iov=iov)

    assert 14 == nl_sendmsg(sk, msg, hdr)
    assert [iov] == tcp_server.data
    nl_socket_free(sk)
示例#17
0
def config_function(config):
    # Global variables storing conf and shared ressources
    global INTERFACE
    global CLIENTS
    global INTERFACEINDEX
    global VALUES
    global DRIVER_ID
    global SOCKET
    for node in config.children:
        key = node.key.lower()
        value = node.values[0]
        # Save Wi-Fi interface name
        if key == 'interface':
            INTERFACE = value
            collectd.info("Collecting stats for interface %s" % value)
        # Save a client MAC address
        elif key == 'client':
            CLIENTS.append(value)
        else:
            collectd.info("Unknown configuration key %s" % key)
    # No clients configured ? Store everything
    if len(CLIENTS) == 0:
        collectd.info("Collecting detailed stats for all clients")
    else:
        str_clients = ""
        for client in CLIENTS:
            str_clients = str_clients + " " + client
        collectd.info("Collecting stats for clients%s" % str_clients)

    # No Wi-FI interface configured
    if INTERFACE == "":
        collectd.error("No interface set in configuration")
        exit(1)
    else:
        # Get the interface index from the interface name
        pack = struct.pack('16sI', INTERFACE, 0)
        sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            info = struct.unpack('16sI', fcntl.ioctl(sk.fileno(), 0x8933,
                                                     pack))
            INTERFACEINDEX = int(info[1])
        except IOError:
            collectd.error("Unknown network interface !")
            exit(1)
    # Create the netlink socket and resolve the driver id of extension nl80211
    SOCKET = nl_socket_alloc()
    genl_connect(SOCKET)
    DRIVER_ID = genl_ctrl_resolve(SOCKET, b'nl80211')
示例#18
0
def main():
    """Main function called upon script execution."""
    # First get the wireless interface index.
    pack = struct.pack('16sI', OPTIONS['<interface>'].encode('ascii'), 0)
    sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        info = struct.unpack('16sI', fcntl.ioctl(sk.fileno(), 0x8933, pack))
    except OSError:
        return error('Wireless interface {0} does not exist.'.format(OPTIONS['<interface>']))
    finally:
        sk.close()
    if_index = int(info[1])

    # Next open a socket to the kernel and bind to it. Same one used for sending and receiving.
    sk = nl_socket_alloc()  # Creates an `nl_sock` instance.
    ok(0, genl_connect, sk)  # Create file descriptor and bind socket.
    _LOGGER.debug('Finding the nl80211 driver ID...')
    driver_id = ok(0, genl_ctrl_resolve, sk, b'nl80211')
    _LOGGER.debug('Finding the nl80211 scanning group ID...')
    mcid = ok(0, genl_ctrl_resolve_grp, sk, b'nl80211', b'scan')

    # Scan for access points 1 or more (if requested) times.
    if not OPTIONS['--no-sudo']:
        print('Scanning for access points, may take about 8 seconds...')
    else:
        print("Attempting to read results of previous scan.")
    results = dict()
    for i in range(2, -1, -1):  # Three tries on errors.
        if not OPTIONS['--no-sudo']:
            ret = ok(i, do_scan_trigger, sk, if_index, driver_id, mcid)
            if ret < 0:
                _LOGGER.warning('do_scan_trigger() returned %d, retrying in 5 seconds.', ret)
                time.sleep(5)
                continue
        ret = ok(i, do_scan_results, sk, if_index, driver_id, results)
        if ret < 0:
            _LOGGER.warning('do_scan_results() returned %d, retrying in 5 seconds.', ret)
            time.sleep(5)
            continue
        break
    if not results:
        print('No access points detected.')
        return

    # Print results.
    print('Found {0} access points:'.format(len(results)))
    print_table(results.values())
示例#19
0
def test_bare(tcp_server, monkeypatch):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && (nc -l 2000 |base64 &) && sleep 0.1 && ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        struct sockaddr_in sin = { .sin_port = htons(2000), .sin_family = AF_INET, };
        sin.sin_addr.s_addr = inet_addr("127.0.0.1");
        int fd = socket(AF_INET, SOCK_STREAM, 0);
        connect(fd, (struct sockaddr *) &sin, sizeof(sin));

        struct nl_sock *sk = nl_socket_alloc();
        nl_connect(sk, NETLINK_ROUTE);
        sk->s_fd = fd;
        sk->s_local.nl_pid = 0;
        sk->s_seq_next = 0;

        int ret = nl_send_simple(sk, RTM_GETLINK, 0, NULL, 0);

        printf("Bytes: %d\n", ret);
        return 0;
    }
    // Expected bash output:
    // Bytes: 16
    // EAAAABIABQAAAAAAAAAAAA==
    """
    monkeypatch.setattr(libnl.socket_, 'generate_local_port', lambda: 0)

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.socket_instance.connect(tcp_server.server.server_address)
    sk.s_local.nl_pid = 0
    sk.s_seq_next = 0

    assert 16 == nl_send_simple(sk, RTM_GETLINK, 0, None)
    assert 1 == len(tcp_server.data)
    assert b'EAAAABIABQAAAAAAAAAAAA==' == base64.b64encode(
        buffer(tcp_server.data[0]))
    nl_socket_free(sk)
示例#20
0
def test_bare(tcp_server, monkeypatch):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && (nc -l 2000 |base64 &) && sleep 0.1 && ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        struct sockaddr_in sin = { .sin_port = htons(2000), .sin_family = AF_INET, };
        sin.sin_addr.s_addr = inet_addr("127.0.0.1");
        int fd = socket(AF_INET, SOCK_STREAM, 0);
        connect(fd, (struct sockaddr *) &sin, sizeof(sin));

        struct nl_sock *sk = nl_socket_alloc();
        nl_connect(sk, NETLINK_ROUTE);
        sk->s_fd = fd;
        sk->s_local.nl_pid = 0;
        sk->s_seq_next = 0;

        int ret = nl_send_simple(sk, RTM_GETLINK, 0, NULL, 0);

        printf("Bytes: %d\n", ret);
        return 0;
    }
    // Expected bash output:
    // Bytes: 16
    // EAAAABIABQAAAAAAAAAAAA==
    """
    monkeypatch.setattr(libnl.socket_, 'generate_local_port', lambda: 0)

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.socket_instance.connect(tcp_server.server.server_address)
    sk.s_local.nl_pid = 0
    sk.s_seq_next = 0

    assert 16 == nl_send_simple(sk, RTM_GETLINK, 0, None)
    assert 1 == len(tcp_server.data)
    assert b'EAAAABIABQAAAAAAAAAAAA==' == base64.b64encode(buffer(tcp_server.data[0]))
    nl_socket_free(sk)
示例#21
0
def ncsi_get_info(ifindex, package):

    # Open socket to kernel
    sk = nl_socket_alloc()
    ret = genl_connect(sk)
    if ret < 0:
        print("Failed to open socket")
        return -1

    # Find NCSI
    driver_id = genl_ctrl_resolve(sk, b'NCSI')
    if driver_id < 0:
        print("Could not resolve NCSI")
        return -1

    # Setup up a Generic Netlink message
    msg = nlmsg_alloc()
    if package is None:
        ret = genlmsg_put(msg, 0, 0, driver_id, 0, NLM_F_DUMP,
                          NCSI_CMD_PKG_INFO, 0)
    else:
        ret = genlmsg_put(msg, 0, 0, driver_id, 0, 0, NCSI_CMD_PKG_INFO, 0)
        nla_put_u32(msg, NCSI_ATTR_PACKAGE_ID, int(package))

    if ret < 0:
        reason = errmsg[abs(ret)]
        print("genlmsg_put returned {}, {}".format(ret, reason))
        return -1

    nla_put_u32(msg, NCSI_ATTR_IFINDEX, ifindex)

    # Add a callback function to the socket
    nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, info_callback, None)

    ret = nl_send_auto(sk, msg)
    if ret < 0:
        print("Failed to send message: {}".format(ret))
        return ret
    ret = nl_recvmsgs_default(sk)  # blocks
    if ret < 0:
        reason = errmsg[abs(ret)]
        print("recvmsg returned {}, {}".format(ret, reason))
示例#22
0
def test_seq():
    """Test sequences."""
    msg = nlmsg_alloc()
    nlh = nlmsg_hdr(msg)
    assert 16 == nlh.nlmsg_len
    assert 0 == nlh.nlmsg_type
    assert 0 == nlh.nlmsg_flags
    assert 0 == nlh.nlmsg_seq
    assert 0 == nlh.nlmsg_pid

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.s_local.nl_pid = 0
    nl_complete_msg(sk, msg)
    assert 1423351063 <= nlh.nlmsg_seq
    nlh.nlmsg_seq = 1423350947
    assert 1423350947 == nlh.nlmsg_seq
    nlh.nlmsg_pid = 0  # sk.s_local.nl_pid is read-only in Python.

    assert b'EAAAAAAABQCjnNZUAAAAAA==' == base64.b64encode(buffer(nlh.bytearray[:nlh.nlmsg_len]))
示例#23
0
def test_seq():
    """Test sequences."""
    msg = nlmsg_alloc()
    nlh = nlmsg_hdr(msg)
    assert 16 == nlh.nlmsg_len
    assert 0 == nlh.nlmsg_type
    assert 0 == nlh.nlmsg_flags
    assert 0 == nlh.nlmsg_seq
    assert 0 == nlh.nlmsg_pid

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.s_local.nl_pid = 0
    nl_complete_msg(sk, msg)
    assert 1423351063 <= nlh.nlmsg_seq
    nlh.nlmsg_seq = 1423350947
    assert 1423350947 == nlh.nlmsg_seq
    nlh.nlmsg_pid = 0  # sk.s_local.nl_pid is read-only in Python.

    assert b'EAAAAAAABQCjnNZUAAAAAA==' == base64.b64encode(
        buffer(nlh.bytearray[:nlh.nlmsg_len]))
示例#24
0
def test_full(tcp_server, monkeypatch):
    r"""Diff of C code (from test_bare()) to test against.

    --- test_bare.c	2015-02-08 12:43:15.543135855 -0800
    +++ test_full.c	2015-02-08 12:43:08.533183752 -0800
    @@ -13,10 +13,11 @@
             struct nl_sock *sk = nl_socket_alloc();
             nl_connect(sk, NETLINK_ROUTE);
             sk->s_fd = fd;
    -        sk->s_local.nl_pid = 0;
    -        sk->s_seq_next = 0;
    +        sk->s_local.nl_pid = 1234;
    +        sk->s_seq_next = 10;

    -        int ret = nl_send_simple(sk, RTM_GETLINK, 0, NULL, 0);
    +        struct rtgenmsg rt_hdr = { .rtgen_family = AF_PACKET, };
    +        int ret = nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));

             printf("Bytes: %d\n", ret);
             return 0;
    """
    monkeypatch.setattr(libnl.socket_, 'generate_local_port', lambda: 1234)

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.socket_instance.connect(tcp_server.server.server_address)
    sk.s_local.nl_pid = 1234
    sk.s_seq_next = 10
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)

    assert 20 == nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP,
                                rt_hdr, rt_hdr.SIZEOF)
    assert 1 == len(tcp_server.data)
    assert b'FAAAABIABQMKAAAA0gQAABEAAAA=' == base64.b64encode(
        buffer(tcp_server.data[0]))
    nl_socket_free(sk)
def main():
    """Main function called upon script execution."""
    # First open a socket to the kernel. Same one used for sending and receiving.
    sk = nl_socket_alloc()  # Creates an `nl_sock` instance.
    ret = nl_connect(sk, NETLINK_ROUTE)  # Create file descriptor and bind socket.
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('nl_connect() returned {0} ({1})'.format(ret, reason))

    # Next we send the request to the kernel.
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    ret = nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, rt_hdr, rt_hdr.SIZEOF)
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('nl_send_simple() returned {0} ({1})'.format(ret, reason))
    print('Sent {0} bytes to the kernel.'.format(ret))

    # Finally we'll retrieve the kernel's answer, process it, and call any callbacks attached to the `nl_sock` instance.
    nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, callback, None)  # Add callback to the `nl_sock` instance.
    ret = nl_recvmsgs_default(sk)  # Get kernel's answer, and call attached callbacks.
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('nl_recvmsgs_default() returned {0} ({1})'.format(ret, reason))
示例#26
0
def test_two_attrs():
    """Test with two attributes."""
    msg = nlmsg_alloc()
    assert 0 == nla_put_u32(msg, 4, 8)
    nlh = nlmsg_hdr(msg)
    assert 24 == nlh.nlmsg_len
    assert 0 == nlh.nlmsg_type
    assert 0 == nlh.nlmsg_flags
    assert 0 == nlh.nlmsg_seq
    assert 0 == nlh.nlmsg_pid
    assert 0 == nla_put_u64(msg, 5, 17)
    assert 36 == nlh.nlmsg_len

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.s_local.nl_pid = 0
    sk.s_seq_next = 0
    nl_complete_msg(sk, msg)
    assert 0 == nlh.nlmsg_seq
    nlh.nlmsg_pid = 0  # sk.s_local.nl_pid is read-only in Python.

    expected = b'JAAAAAAABQAAAAAAAAAAAAgABAAIAAAADAAFABEAAAAAAAAA'
    assert expected == base64.b64encode(buffer(nlh.bytearray[:nlh.nlmsg_len]))
示例#27
0
def test_two_attrs():
    """Test with two attributes."""
    msg = nlmsg_alloc()
    assert 0 == nla_put_u32(msg, 4, 8)
    nlh = nlmsg_hdr(msg)
    assert 24 == nlh.nlmsg_len
    assert 0 == nlh.nlmsg_type
    assert 0 == nlh.nlmsg_flags
    assert 0 == nlh.nlmsg_seq
    assert 0 == nlh.nlmsg_pid
    assert 0 == nla_put_u64(msg, 5, 17)
    assert 36 == nlh.nlmsg_len

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.s_local.nl_pid = 0
    sk.s_seq_next = 0
    nl_complete_msg(sk, msg)
    assert 0 == nlh.nlmsg_seq
    nlh.nlmsg_pid = 0  # sk.s_local.nl_pid is read-only in Python.

    expected = b'JAAAAAAABQAAAAAAAAAAAAgABAAIAAAADAAFABEAAAAAAAAA'
    assert expected == base64.b64encode(buffer(nlh.bytearray[:nlh.nlmsg_len]))
示例#28
0
def test_full(tcp_server, monkeypatch):
    r"""Diff of C code (from test_bare()) to test against.

    --- test_bare.c	2015-02-08 12:43:15.543135855 -0800
    +++ test_full.c	2015-02-08 12:43:08.533183752 -0800
    @@ -13,10 +13,11 @@
             struct nl_sock *sk = nl_socket_alloc();
             nl_connect(sk, NETLINK_ROUTE);
             sk->s_fd = fd;
    -        sk->s_local.nl_pid = 0;
    -        sk->s_seq_next = 0;
    +        sk->s_local.nl_pid = 1234;
    +        sk->s_seq_next = 10;

    -        int ret = nl_send_simple(sk, RTM_GETLINK, 0, NULL, 0);
    +        struct rtgenmsg rt_hdr = { .rtgen_family = AF_PACKET, };
    +        int ret = nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));

             printf("Bytes: %d\n", ret);
             return 0;
    """
    monkeypatch.setattr(libnl.socket_, 'generate_local_port', lambda: 1234)

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.socket_instance.connect(tcp_server.server.server_address)
    sk.s_local.nl_pid = 1234
    sk.s_seq_next = 10
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)

    assert 20 == nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, rt_hdr, rt_hdr.SIZEOF)
    assert 1 == len(tcp_server.data)
    assert b'FAAAABIABQMKAAAA0gQAABEAAAA=' == base64.b64encode(buffer(tcp_server.data[0]))
    nl_socket_free(sk)
示例#29
0
def test_nl_socket_modify_cb_error_verbose(log):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 NLCB=verbose ./a.out
    #include <netlink/msg.h>
    static int callback(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) {
        int *ret = arg;
        *ret = err->error;
        printf("Got something.\n");
        return NL_STOP;
    }
    int main() {
        // Send data to the kernel.
        struct nl_sock *sk = nl_socket_alloc();
        printf("%d == nl_connect(sk, NETLINK_ROUTE)\n", nl_connect(sk, NETLINK_ROUTE));
        struct rtgenmsg rt_hdr = { .rtgen_family = AF_PACKET, };
        int ret = nl_send_simple(sk, RTM_GETLINK, 0, &rt_hdr, sizeof(rt_hdr));
        printf("Bytes Sent: %d\n", ret);

        // Retrieve kernel's response.
        int err = 0;
        nl_socket_modify_err_cb(sk, NL_CB_CUSTOM, callback, &err);
        printf("%d == err\n", err);
        printf("%d == nl_recvmsgs_default(sk)\n", nl_recvmsgs_default(sk));
        printf("%d == err\n", err);

        nl_socket_free(sk);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // 0 == nl_connect(sk, NETLINK_ROUTE)
    // __nlmsg_alloc: msg 0x124e0b8: Allocated new message, maxlen=4096
    // nlmsg_alloc_simple: msg 0x124e0b8: Allocated new simple message
    // nlmsg_reserve: msg 0x124e0b8: Reserved 4 (1) bytes, pad=4, nlmsg_len=20
    // nlmsg_append: msg 0x124e0b8: Appended 1 bytes with padding 4
    // nl_sendmsg: sent 20 bytes
    // nlmsg_free: Returned message reference 0x124e0b8, 0 remaining
    // nlmsg_free: msg 0x124e0b8: Freed
    // Bytes Sent: 20
    // 0 == err
    // recvmsgs: Attempting to read from 0x124e080
    // recvmsgs: recvmsgs(0x124e080): Read 40 bytes
    // recvmsgs: recvmsgs(0x124e080): Processing valid message...
    // __nlmsg_alloc: msg 0x12520c0: Allocated new message, maxlen=40
    // recvmsgs: recvmsgs(0x124e080): Increased expected sequence number to 1424136270
    // Got something.
    // nlmsg_free: Returned message reference 0x12520c0, 0 remaining
    // nlmsg_free: msg 0x12520c0: Freed
    // -7 == nl_recvmsgs_default(sk)
    // -22 == err
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    got_something = list()

    def callback(_, err, arg):
        arg.append(err.error)
        return NL_STOP

    del log[:]
    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    assert 20 == nl_send_simple(sk, RTM_GETLINK, 0, rt_hdr, rt_hdr.SIZEOF)

    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096', log, True)
    assert match('nlmsg_alloc_simple: msg 0x[a-f0-9]+: Allocated new simple message', log, True)
    assert match('nlmsg_reserve: msg 0x[a-f0-9]+: Reserved 4 \(1\) bytes, pad=4, nlmsg_len=20', log, True)
    assert match('nlmsg_append: msg 0x[a-f0-9]+: Appended 1 bytes with padding 4', log, True)
    assert match('nl_sendmsg: sent 20 bytes', log)
    assert not log

    assert 0 == nl_socket_modify_err_cb(sk, NL_CB_CUSTOM, callback, got_something)
    assert -7 == nl_recvmsgs_default(sk)
    assert [-22] == got_something

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read 40 bytes', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=40', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Increased expected sequence number to \d{4,}', log, True)

    nl_socket_free(sk)
    assert not log
示例#30
0
def test_nl_socket_alloc():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    struct nl_cb {
        nl_recvmsg_msg_cb_t cb_set[NL_CB_TYPE_MAX+1]; void * cb_args[NL_CB_TYPE_MAX+1]; nl_recvmsg_err_cb_t cb_err;
        void * cb_err_arg; int (*cb_recvmsgs_ow)(struct nl_sock *, struct nl_cb *);
        int (*cb_recv_ow)(struct nl_sock *, struct sockaddr_nl *, unsigned char **, struct ucred **);
        int (*cb_send_ow)(struct nl_sock *, struct nl_msg *); int cb_refcnt; enum nl_cb_type cb_active;
    };
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    void print(struct nl_sock *sk) {
        printf("sk.s_local.nl_family = %d\n", sk->s_local.nl_family);
        printf("sk.s_local.nl_pid = %d  # changes every process, remains same throughout proc.\n", sk->s_local.nl_pid);
        printf("sk.s_local.nl_groups = %d\n", sk->s_local.nl_groups);
        printf("sk.s_peer.nl_family = %d\n", sk->s_peer.nl_family);
        printf("sk.s_peer.nl_pid = %d\n", sk->s_peer.nl_pid);
        printf("sk.s_peer.nl_groups = %d\n", sk->s_peer.nl_groups);
        printf("sk.s_fd = %d\n", sk->s_fd);
        printf("sk.s_proto = %d\n", sk->s_proto);
        printf("sk.s_flags = %d\n", sk->s_flags);
        printf("sk.s_cb.cb_active = %d\n", sk->s_cb->cb_active);
        printf("addr: sk.s_cb.cb_err = %p\n", sk->s_cb->cb_err);
    }
    int main() {
        struct nl_sock *sk = nl_socket_alloc();
        print(sk);
        nl_socket_free(sk);
        printf("\n");
        struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE);
        sk = nl_socket_alloc_cb(cb);
        nl_cb_put(cb);
        print(sk);
        nl_socket_free(sk);
        return 0;
    }
    // Expected output:
    // sk.s_local.nl_family = 16
    // sk.s_local.nl_pid = 12309  # changes every process, remains same throughout proc.
    // sk.s_local.nl_groups = 0
    // sk.s_peer.nl_family = 16
    // sk.s_peer.nl_pid = 0
    // sk.s_peer.nl_groups = 0
    // sk.s_fd = -1
    // sk.s_proto = 0
    // sk.s_flags = 0
    // sk.s_cb.cb_active = 11
    // addr: sk.s_cb.cb_err = (nil)
    //
    // sk.s_local.nl_family = 16
    // sk.s_local.nl_pid = 12309  # changes every process, remains same throughout proc.
    // sk.s_local.nl_groups = 0
    // sk.s_peer.nl_family = 16
    // sk.s_peer.nl_pid = 0
    // sk.s_peer.nl_groups = 0
    // sk.s_fd = -1
    // sk.s_proto = 0
    // sk.s_flags = 0
    // sk.s_cb.cb_active = 11
    // addr: sk.s_cb.cb_err = 0xb6f6eb40
    """
    sk = nl_socket_alloc()
    assert 16 == sk.s_local.nl_family
    assert 0 < sk.s_local.nl_pid
    assert 0 == sk.s_local.nl_groups
    assert 16 == sk.s_peer.nl_family
    assert 0 == sk.s_peer.nl_pid
    assert 0 == sk.s_peer.nl_groups
    assert -1 == sk.s_fd
    assert 0 == sk.s_proto
    assert 0 == sk.s_flags
    assert 11 == sk.s_cb.cb_active
    assert sk.s_cb.cb_err is None
    nl_socket_free(sk)

    first_pid = int(sk.s_local.nl_pid)
    sk = nl_socket_alloc(nl_cb_alloc(NL_CB_VERBOSE))
    assert 16 == sk.s_local.nl_family
    assert first_pid == sk.s_local.nl_pid
    assert 0 == sk.s_local.nl_groups
    assert 16 == sk.s_peer.nl_family
    assert 0 == sk.s_peer.nl_pid
    assert 0 == sk.s_peer.nl_groups
    assert -1 == sk.s_fd
    assert 0 == sk.s_proto
    assert 0 == sk.s_flags
    assert 11 == sk.s_cb.cb_active
    assert sk.s_cb.cb_err is not None
    nl_socket_free(sk)
示例#31
0
def test_nl_socket_modify_cb(log, ifaces):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 ./a.out
    #include <netlink/msg.h>
    static int callback(struct nl_msg *msg, void *arg) {
        printf("Got something.\n");
        nl_msg_dump(msg, stdout);
        return NL_OK;
    }
    int main() {
        // Send data to the kernel.
        struct nl_sock *sk = nl_socket_alloc();
        printf("%d == nl_connect(sk, NETLINK_ROUTE)\n", nl_connect(sk, NETLINK_ROUTE));
        struct rtgenmsg rt_hdr = { .rtgen_family = AF_PACKET, };
        int ret = nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
        printf("Bytes Sent: %d\n", ret);

        // Retrieve kernel's response.
        nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, callback, NULL);
        printf("%d == nl_recvmsgs_default(sk)\n", nl_recvmsgs_default(sk));

        nl_socket_free(sk);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // 0 == nl_connect(sk, NETLINK_ROUTE)
    // __nlmsg_alloc: msg 0x1b840b8: Allocated new message, maxlen=4096
    // nlmsg_alloc_simple: msg 0x1b840b8: Allocated new simple message
    // nlmsg_reserve: msg 0x1b840b8: Reserved 4 (1) bytes, pad=4, nlmsg_len=20
    // nlmsg_append: msg 0x1b840b8: Appended 1 bytes with padding 4
    // nl_sendmsg: sent 20 bytes
    // nlmsg_free: Returned message reference 0x1b840b8, 0 remaining
    // nlmsg_free: msg 0x1b840b8: Freed
    // Bytes Sent: 20
    // recvmsgs: Attempting to read from 0x1b84080
    // recvmsgs: recvmsgs(0x1b84080): Read 3364 bytes
    // recvmsgs: recvmsgs(0x1b84080): Processing valid message...
    // __nlmsg_alloc: msg 0x1b880c0: Allocated new message, maxlen=1116
    // Got something.
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1116
    //     .type = 16 <0x10>
    //     .flags = 2 <MULTI>
    //     .seq = 1424133909
    //     .port = 6192
    //   [PAYLOAD] 1100 octets
    //     00 00 04 03 01 00 00 00 49 00 01 00 00 00 00 00 ........I.......
    //     07 00 03 00 6c 6f 00 00 08 00 0d 00 00 00 00 00 ....lo..........
    //     <trimmed>
    //     00 00 00 00 00 00 00 00 00 00 00 00             ............
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // recvmsgs: recvmsgs(0x1b84080): Processing valid message...
    // nlmsg_free: Returned message reference 0x1b880c0, 0 remaining
    // nlmsg_free: msg 0x1b880c0: Freed
    // __nlmsg_alloc: msg 0x1b880c0: Allocated new message, maxlen=1124
    // Got something.
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1124
    //     .type = 16 <0x10>
    //     .flags = 2 <MULTI>
    //     .seq = 1424133909
    //     .port = 6192
    //   [PAYLOAD] 1108 octets
    //     00 00 01 00 02 00 00 00 43 10 01 00 00 00 00 00 ........C.......
    //     09 00 03 00 65 74 68 30 00 00 00 00 08 00 0d 00 ....eth0........
    //     <trimmed>
    //     00 00 00 00                                     ....
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // recvmsgs: recvmsgs(0x1b84080): Processing valid message...
    // nlmsg_free: Returned message reference 0x1b880c0, 0 remaining
    // nlmsg_free: msg 0x1b880c0: Freed
    // __nlmsg_alloc: msg 0x1b880c0: Allocated new message, maxlen=1124
    // Got something.
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1124
    //     .type = 16 <0x10>
    //     .flags = 2 <MULTI>
    //     .seq = 1424133909
    //     .port = 6192
    //   [PAYLOAD] 1108 octets
    //     00 00 01 00 04 00 00 00 03 10 00 00 00 00 00 00 ................
    //     0a 00 03 00 77 6c 61 6e 30 00 00 00 08 00 0d 00 ....wlan0.......
    //     <trimmed>
    //     00 00 00 00                                     ....
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // nlmsg_free: Returned message reference 0x1b880c0, 0 remaining
    // nlmsg_free: msg 0x1b880c0: Freed
    // recvmsgs: Attempting to read from 0x1b84080
    // recvmsgs: recvmsgs(0x1b84080): Read 20 bytes
    // recvmsgs: recvmsgs(0x1b84080): Processing valid message...
    // __nlmsg_alloc: msg 0x1b880c0: Allocated new message, maxlen=20
    // recvmsgs: recvmsgs(0x1b84080): Increased expected sequence number to 1424133910
    // nlmsg_free: Returned message reference 0x1b880c0, 0 remaining
    // nlmsg_free: msg 0x1b880c0: Freed
    // 0 == nl_recvmsgs_default(sk)
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    got_something = list()

    def callback(msg, arg):
        got_something.append(arg)
        nl_msg_dump(msg)
        return NL_OK

    del log[:]
    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    assert 20 == nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, rt_hdr, rt_hdr.SIZEOF)

    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096', log, True)
    assert match('nlmsg_alloc_simple: msg 0x[a-f0-9]+: Allocated new simple message', log, True)
    assert match('nlmsg_reserve: msg 0x[a-f0-9]+: Reserved 4 \(1\) bytes, pad=4, nlmsg_len=20', log, True)
    assert match('nlmsg_append: msg 0x[a-f0-9]+: Appended 1 bytes with padding 4', log, True)
    assert match('nl_sendmsg: sent 20 bytes', log)
    assert not log

    assert 0 == nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, callback, 95)
    assert 0 == nl_recvmsgs_default(sk)
    assert [95] * len(ifaces) == got_something

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{4,} bytes', log, True)

    for _ in ifaces:
        if 'Attempting to read' in log[0]:
            # Lots of network interfaces on this host.
            assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
            assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{4,} bytes', log, True)
        assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
        assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=\d{3,}', log, True)
        assert match('nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------', log)
        assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
        assert match('print_hdr:     .nlmsg_len = \d{3,}', log, True)
        assert match('print_hdr:     .type = 16 <0x10>', log)
        assert match('print_hdr:     .flags = 2 <MULTI>', log)
        assert match('print_hdr:     .seq = \d{10}', log, True)
        assert match('print_hdr:     .port = \d{3,}', log, True)
        assert match('print_msg:   \[PAYLOAD\] \d{3,} octets', log, True)

        rem = log.index('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------')
        assert 20 < rem  # At least check that there were a lot of log statements skipped.
        log = log[rem:]
        assert match('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------', log)

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read 20 bytes', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=20', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Increased expected sequence number to \d{4,}', log, True)

    nl_socket_free(sk)
    assert not log
示例#32
0
def test_genl_ctrl_resolve(log):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 NLCB=debug ./a.out
    #include <netlink/msg.h>
    int main() {
        struct nl_sock *sk = nl_socket_alloc();
        printf("%d == genl_connect(sk)\n", genl_connect(sk));
        int driver_id = genl_ctrl_resolve(sk, "nl80211");
        printf("%d == driver_id\n", driver_id);
        nl_socket_free(sk);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // 0 == genl_connect(sk)
    //  nl_object_alloc: Allocated new object 0x6f90b8
    // __nlmsg_alloc: msg 0x6f9110: Allocated new message, maxlen=4096
    // nlmsg_put: msg 0x6f9110: Added netlink header type=16, flags=0, pid=0, seq=0
    // nlmsg_reserve: msg 0x6f9110: Reserved 4 (4) bytes, pad=4, nlmsg_len=20
    // genlmsg_put: msg 0x6f9110: Added generic netlink header cmd=3 version=1
    // nla_reserve: msg 0x6f9110: attr <0x6f9164> 2: Reserved 12 (8) bytes at offset +4 nlmsg_len=32
    // nla_put: msg 0x6f9110: attr <0x6f9164> 2: Wrote 8 bytes at offset +4
    // -- Debug: Sent Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 32
    //     .type = 16 <genl/family::nlctrl>
    //     .flags = 5 <REQUEST,ACK>
    //     .seq = 1425769691
    //     .port = 2568
    //   [GENERIC NETLINK HEADER] 4 octets
    //     .cmd = 3
    //     .version = 1
    //     .unused = 0
    //   [ATTR 02] 8 octets
    //     6e 6c 38 30 32 31 31 00                         nl80211.
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // nl_sendmsg: sent 32 bytes
    // recvmsgs: Attempting to read from 0x6f9080
    // recvmsgs: recvmsgs(0x6f9080): Read 1836 bytes
    // recvmsgs: recvmsgs(0x6f9080): Processing valid message...
    // __nlmsg_alloc: msg 0x6fe1d8: Allocated new message, maxlen=1836
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1836
    //     .type = 16 <genl/family::nlctrl>
    //     .flags = 0 <>
    //     .seq = 1425769691
    //     .port = 2568
    //   [GENERIC NETLINK HEADER] 4 octets
    //     .cmd = 1
    //     .version = 2
    //     .unused = 0
    //   [ATTR 02] 8 octets
    //     6e 6c 38 30 32 31 31 00                         nl80211.
    //   [ATTR 01] 2 octets
    //     16 00                                           ..
    //   [PADDING] 2 octets
    //     00 00                                           ..
    //   [ATTR 03] 4 octets
    //     01 00 00 00                                     ....
    //   [ATTR 04] 4 octets
    //     00 00 00 00                                     ....
    //   [ATTR 05] 4 octets
    //     d5 00 00 00                                     ....
    //   [ATTR 06] 1640 octets
    //     14 00 01 00 08 00 01 00 01 00 00 00 08 00 02 00 ................
    //     <trimmed>
    //     08 00 02 00 0b 00 00 00                         ........
    //   [ATTR 07] 124 octets
    //     18 00 01 00 08 00 02 00 03 00 00 00 0b 00 01 00 ................
    //     63 6f 6e 66 69 67 00 00 18 00 02 00 08 00 02 00 config..........
    //     04 00 00 00 09 00 01 00 73 63 61 6e 00 00 00 00 ........scan....
    //     1c 00 03 00 08 00 02 00 05 00 00 00 0f 00 01 00 ................
    //     72 65 67 75 6c 61 74 6f 72 79 00 00 18 00 04 00 regulatory......
    //     08 00 02 00 06 00 00 00 09 00 01 00 6d 6c 6d 65 ............mlme
    //     00 00 00 00 18 00 05 00 08 00 02 00 07 00 00 00 ................
    //     0b 00 01 00 76 65 6e 64 6f 72 00 00             ....vendor..
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // nlmsg_free: Returned message reference 0x6fe1d8, 0 remaining
    // nlmsg_free: msg 0x6fe1d8: Freed
    // recvmsgs: Attempting to read from 0x6f9080
    // recvmsgs: recvmsgs(0x6f9080): Read 36 bytes
    // recvmsgs: recvmsgs(0x6f9080): Processing valid message...
    // __nlmsg_alloc: msg 0x6fe1d8: Allocated new message, maxlen=36
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 36
    //     .type = 2 <ERROR>
    //     .flags = 0 <>
    //     .seq = 1425769691
    //     .port = 2568
    //   [ERRORMSG] 20 octets
    //     .error = 0 "Success"
    //   [ORIGINAL MESSAGE] 16 octets
    // __nlmsg_alloc: msg 0x6fe2b8: Allocated new message, maxlen=4096
    //     .nlmsg_len = 16
    //     .type = 16 <0x10>
    //     .flags = 5 <REQUEST,ACK>
    //     .seq = 1425769691
    //     .port = 2568
    // nlmsg_free: Returned message reference 0x6fe2b8, 0 remaining
    // nlmsg_free: msg 0x6fe2b8: Freed
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // recvmsgs: recvmsgs(0x6f9080): Increased expected sequence number to 1425769692
    // nlmsg_free: Returned message reference 0x6fe1d8, 0 remaining
    // nlmsg_free: msg 0x6fe1d8: Freed
    // nlmsg_free: Returned message reference 0x6f9110, 0 remaining
    // nlmsg_free: msg 0x6f9110: Freed
    // nl_object_put: Returned object reference 0x6f90b8, 0 remaining
    // nl_object_free: Freed object 0x6f90b8
    // 22 == driver_id
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    del log[:]

    sk = nl_socket_alloc()
    assert 0 == genl_connect(sk)
    assert not log
    assert 20 <= genl_ctrl_resolve(sk, b'nl80211')
    nl_socket_free(sk)

    assert match('nl_object_alloc: Allocated new object 0x[a-f0-9]+', log,
                 True)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096',
        log, True)
    assert match(
        'nlmsg_put: msg 0x[a-f0-9]+: Added netlink header type=16, flags=0, pid=0, seq=0',
        log, True)
    assert match(
        'nlmsg_reserve: msg 0x[a-f0-9]+: Reserved 4 \(4\) bytes, pad=4, nlmsg_len=20',
        log, True)
    assert match(
        'genlmsg_put: msg 0x[a-f0-9]+: Added generic netlink header cmd=3 version=1',
        log, True)
    assert match(
        'nla_reserve: msg 0x[a-f0-9]+: attr <0x[a-f0-9]+> 2: Reserved 12 \(8\) bytes at offset \+4 nlmsg_len=32',
        log, True)
    assert match(
        'nla_put: msg 0x[a-f0-9]+: attr <0x[a-f0-9]+> 2: Wrote 8 bytes at offset \+4',
        log, True)
    assert match('nl_msg_out_handler_debug: -- Debug: Sent Message:', log)
    assert match(
        'nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------',
        log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 32', log)
    assert match('print_hdr:     .type = 16 <genl/family::nlctrl>', log)
    assert match('print_hdr:     .flags = 5 <REQUEST,ACK>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('print_genl_hdr:   [GENERIC NETLINK HEADER] 4 octets', log)
    assert match('print_genl_hdr:     .cmd = 3', log)
    assert match('print_genl_hdr:     .version = 1', log)
    assert match('print_genl_hdr:     .unused = 0', log)
    assert match('dump_attrs:   [ATTR 02] 8 octets', log)
    assert match(
        'dump_hex:     6e 6c 38 30 32 31 31 00                         nl80211.',
        log)
    assert match(
        'nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------',
        log)
    assert match('nl_sendmsg: sent 32 bytes', log)

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{3,} bytes', log,
                 True)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log,
        True)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=\d{3,}',
        log, True)
    assert match('nl_msg_in_handler_debug: -- Debug: Received Message:', log)
    assert match(
        'nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------',
        log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = \d{3,}', log, True)
    assert match('print_hdr:     .type = 16 <genl/family::nlctrl>', log)
    assert match('print_hdr:     .flags = 0 <>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('print_genl_hdr:   [GENERIC NETLINK HEADER] 4 octets', log)
    assert match('print_genl_hdr:     .cmd = 1', log)
    assert match('print_genl_hdr:     .version = 2', log)
    assert match('print_genl_hdr:     .unused = 0', log)
    assert match('dump_attrs:   [ATTR 02] 8 octets', log)
    assert match(
        'dump_hex:     6e 6c 38 30 32 31 31 00                         nl80211.',
        log)
    assert match('dump_attrs:   [ATTR 01] 2 octets', log)
    assert match(
        'dump_hex:     .. 00                                           ..',
        log, True)
    assert match('dump_attrs:   [PADDING] 2 octets', log)
    assert match(
        'dump_hex:     00 00                                           ..',
        log)
    assert match('dump_attrs:   [ATTR 03] 4 octets', log)
    assert match(
        'dump_hex:     01 00 00 00                                     ....',
        log)
    assert match('dump_attrs:   [ATTR 04] 4 octets', log)
    assert match(
        'dump_hex:     00 00 00 00                                     ....',
        log)
    assert match('dump_attrs:   [ATTR 05] 4 octets', log)
    assert match(
        'dump_hex:     .. 00 00 00                                     ....',
        log, True)
    assert match('dump_attrs:   \[ATTR 06\] \d{4,} octets', log, True)
    assert match(
        'dump_hex:     14 00 01 00 08 00 01 00 01 00 00 00 08 00 02 00 ................',
        log)

    # Done testing this payload. Too big.
    for line in log:
        if line.startswith('dump_hex'):
            continue
        rem = log.index(line)
        assert 20 < rem  # At least check that there were a lot of log statements skipped.
        log = log[rem:]
        break

    assert match('dump_attrs:   \[ATTR 07\] \d{3,} octets', log, True)
    assert match(
        'dump_hex:     18 00 01 00 08 00 02 00 .. 00 00 00 0b 00 01 00 ................',
        log, True)
    assert match(
        'dump_hex:     63 6f 6e 66 69 67 00 00 18 00 02 00 08 00 02 00 config..........',
        log)
    assert match(
        'dump_hex:     .. 00 00 00 09 00 01 00 73 63 61 6e 00 00 00 00 ........scan....',
        log, True)
    assert match(
        'dump_hex:     1c 00 03 00 08 00 02 00 .. 00 00 00 0f 00 01 00 ................',
        log, True)
    assert match(
        'dump_hex:     72 65 67 75 6c 61 74 6f 72 79 00 00 18 00 04 00 regulatory......',
        log)
    assert match(
        'dump_hex:     08 00 02 00 .. 00 00 00 09 00 01 00 6d 6c 6d 65 ............mlme',
        log, True)
    rem = log.index(
        'nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------'
    )
    log = log[rem:]
    assert match(
        'nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------',
        log)

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read 36 bytes', log, True)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log,
        True)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=36', log,
        True)
    assert match('nl_msg_in_handler_debug: -- Debug: Received Message:', log)
    assert match(
        'nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------',
        log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 36', log)
    assert match('print_hdr:     .type = 2 <ERROR>', log)
    assert match('print_hdr:     .flags = 0 <>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('dump_error_msg:   [ERRORMSG] 20 octets', log)
    assert match('dump_error_msg:     .error = 0 "Success"', log)
    assert match('dump_error_msg:   [ORIGINAL MESSAGE] 16 octets', log)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096',
        log, True)
    assert match('print_hdr:     .nlmsg_len = 16', log)
    assert match('print_hdr:     .type = 16 <0x[a-f0-9]+>', log, True)
    assert match('print_hdr:     .flags = 5 <REQUEST,ACK>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match(
        'nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------',
        log)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Increased expected sequence number to \d{10}',
        log, True)

    assert not log
def main():
    """Main function called upon script execution."""
    # First get the wireless interface index.
    if OPTIONS['<interface>']:
        pack = struct.pack('16sI', OPTIONS['<interface>'].encode('ascii'), 0)
        sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            info = struct.unpack('16sI', fcntl.ioctl(sk.fileno(), 0x8933,
                                                     pack))
        except OSError:
            return error('Wireless interface {0} does not exist.'.format(
                OPTIONS['<interface>']))
        finally:
            sk.close()
        if_index = int(info[1])
    else:
        if_index = -1

    # Then open a socket to the kernel. Same one used for sending and receiving.
    sk = nl_socket_alloc()  # Creates an `nl_sock` instance.
    ret = genl_connect(sk)  # Create file descriptor and bind socket.
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('genl_connect() returned {0} ({1})'.format(ret, reason))

    # Now get the nl80211 driver ID. Handle errors here.
    driver_id = genl_ctrl_resolve(sk,
                                  b'nl80211')  # Find the nl80211 driver ID.
    if driver_id < 0:
        reason = errmsg[abs(driver_id)]
        return error('genl_ctrl_resolve() returned {0} ({1})'.format(
            driver_id, reason))

    # Setup the Generic Netlink message.
    msg = nlmsg_alloc()  # Allocate a message.
    if OPTIONS['<interface>']:
        genlmsg_put(msg, 0, 0, driver_id, 0, 0,
                    nl80211.NL80211_CMD_GET_INTERFACE,
                    0)  # Tell kernel: send iface info.
        nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX,
                    if_index)  # This is the interface we care about.
    else:
        # Ask kernel to send info for all wireless interfaces.
        genlmsg_put(msg, 0, 0, driver_id, 0, NLM_F_DUMP,
                    nl80211.NL80211_CMD_GET_INTERFACE, 0)

    # Add the callback function to the nl_sock.
    has_printed = list()
    nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, callback, has_printed)

    # Now send the message to the kernel, and get its response, automatically calling the callback.
    ret = nl_send_auto(sk, msg)
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('nl_send_auto() returned {0} ({1})'.format(ret, reason))
    print('Sent {0} bytes to the kernel.'.format(ret))
    ret = nl_recvmsgs_default(
        sk)  # Blocks until the kernel replies. Usually it's instant.
    if ret < 0:
        reason = errmsg[abs(ret)]
        return error('nl_recvmsgs_default() returned {0} ({1})'.format(
            ret, reason))
示例#34
0
def test_nl_cache_ops_associate_safe():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/genl/family.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    struct nl_cache_ops {
        char *co_name; int co_hdrsize; int co_protocol; int co_hash_size; unsigned int co_flags; unsigned int co_refcnt;
        struct nl_af_group *co_groups; int (*co_request_update)(struct nl_cache*, struct nl_sock*);
        int (*co_msg_parser)(struct nl_cache_ops*, struct sockaddr_nl*, struct nlmsghdr*, struct nl_parser_param*);
        int (*co_event_filter)(struct nl_cache*, struct nl_object *obj);
        int (*co_include_event)(struct nl_cache *cache, struct nl_object *obj, change_func_t change_cb, void *data);
        void (*reserved_1)(void); void (*reserved_2)(void); void (*reserved_3)(void); void (*reserved_4)(void);
        void (*reserved_5)(void); void (*reserved_6)(void); void (*reserved_7)(void); void (*reserved_8)(void);
        struct nl_object_ops *co_obj_ops;
    };
    struct nl_object_ops { char *oo_name; size_t oo_size; uint32_t oo_id_attrs; };
    struct nl_msgtype { int mt_id; int mt_act; char *mt_name; };
    static int callback(struct nl_sock *sk, struct nl_msg *msg) {
        struct nlmsghdr *nlh = nlmsg_hdr(msg);
        printf("%d == nlh.nlmsg_len\n", nlh->nlmsg_len);
        printf("%d == nlh.nlmsg_type\n", nlh->nlmsg_type);
        printf("%d == nlh.nlmsg_flags\n", nlh->nlmsg_flags);
        struct nl_cache_ops *ops = nl_cache_ops_associate_safe(NETLINK_GENERIC, nlh->nlmsg_type);
        printf("'%s' == ops.co_name\n", ops->co_name);
        printf("%d == ops.co_hdrsize\n", ops->co_hdrsize);
        printf("%d == ops.co_protocol\n", ops->co_protocol);
        printf("%d == ops.co_hash_size\n", ops->co_hash_size);
        printf("%d == ops.co_flags\n", ops->co_flags);
        printf("'%s' == ops.co_obj_ops.oo_name\n", ops->co_obj_ops->oo_name);
        printf("%d == ops.co_obj_ops.oo_size\n", ops->co_obj_ops->oo_size);
        printf("%d == ops.co_obj_ops.oo_id_attrs\n", ops->co_obj_ops->oo_id_attrs);
        printf("%d == nlmsg_attrlen(nlh, ops.co_hdrsize)\n", nlmsg_attrlen(nlh, ops->co_hdrsize));
        struct nl_msgtype *mt = nl_msgtype_lookup(ops, nlh->nlmsg_type);
        printf("%d == mt.mt_id\n", mt->mt_id);
        printf("%d == mt.mt_act\n", mt->mt_act);
        printf("'%s' == mt.mt_name\n", mt->mt_name);
        return NL_STOP;
    }
    int main() {
        struct nl_sock *sk = nl_socket_alloc();
        nl_cb_overwrite_send(sk->s_cb, callback);

        struct genl_family *ret = genl_family_alloc();
        genl_family_set_name(ret, "nl80211");
        struct nl_msg *msg = nlmsg_alloc();
        genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1);
        printf("%d == nl_send_auto(sk, msg)\n", nl_send_auto(sk, msg));
        return 0;
    }
    // Expected output:
    // 20 == nlh.nlmsg_len
    // 16 == nlh.nlmsg_type
    // 5 == nlh.nlmsg_flags
    // 'genl/family' == ops.co_name
    // 4 == ops.co_hdrsize
    // 16 == ops.co_protocol
    // 0 == ops.co_hash_size
    // 0 == ops.co_flags
    // 'genl/family' == ops.co_obj_ops.oo_name
    // 80 == ops.co_obj_ops.oo_size
    // 1 == ops.co_obj_ops.oo_id_attrs
    // 0 == nlmsg_attrlen(nlh, ops.co_hdrsize)
    // 16 == mt.mt_id
    // 0 == mt.mt_act
    // 'nlctrl' == mt.mt_name
    // 2 == nl_send_auto(sk, msg)
    """
    called = list()

    def callback(_, msg_):
        nlh = nlmsg_hdr(msg_)
        assert 20 == nlh.nlmsg_len
        assert 16 == nlh.nlmsg_type
        assert 5 == nlh.nlmsg_flags
        ops = nl_cache_ops_associate_safe(NETLINK_GENERIC, nlh.nlmsg_type)
        assert 'genl/family' == ops.co_name
        assert 4 == ops.co_hdrsize
        assert 16 == ops.co_protocol
        assert 0 == ops.co_hash_size
        assert 0 == ops.co_flags
        assert 'genl/family' == ops.co_obj_ops.oo_name
        assert 80 == ops.co_obj_ops.oo_size
        assert 1 == ops.co_obj_ops.oo_id_attrs
        assert 0 == nlmsg_attrlen(nlh, ops.co_hdrsize)
        mt = nl_msgtype_lookup(ops, nlh.nlmsg_type)
        assert 16 == mt.mt_id
        assert 0 == mt.mt_act
        assert 'nlctrl' == mt.mt_name
        called.append(True)
        return NL_STOP

    sk = nl_socket_alloc()
    nl_cb_overwrite_send(sk.s_cb, callback)
    ret = genl_family_alloc()
    genl_family_set_name(ret, 'nl80211')
    msg = nlmsg_alloc()
    genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1)
    assert 2 == nl_send_auto(sk, msg)
    assert [True] == called
示例#35
0
def test_socket(tcp_server):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && (nc -l 2000 |base64 &) && sleep 0.1 && ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        struct nl_msg *msg = nlmsg_alloc();
        struct nlmsghdr *nlh = nlmsg_hdr(msg);
        printf("%d == nlh->nlmsg_len\n", nlh->nlmsg_len);
        printf("%d == nlh->nlmsg_type\n", nlh->nlmsg_type);
        printf("%d == nlh->nlmsg_flags\n", nlh->nlmsg_flags);
        printf("%d == nlh->nlmsg_seq\n", nlh->nlmsg_seq);
        printf("%d == nlh->nlmsg_pid\n", nlh->nlmsg_pid);

        struct sockaddr_in sin = { .sin_port = htons(2000), .sin_family = AF_INET, };
        sin.sin_addr.s_addr = inet_addr("127.0.0.1");
        int fd = socket(AF_INET, SOCK_STREAM, 0);
        connect(fd, (struct sockaddr *) &sin, sizeof(sin));

        struct nl_sock *sk = nl_socket_alloc();
        nl_connect(sk, NETLINK_ROUTE);
        sk->s_fd = fd;
        sk->s_local.nl_pid = 0;
        sk->s_seq_next = 0;
        nl_complete_msg(sk, msg);
        printf("%d == nlh->nlmsg_seq\n", nlh->nlmsg_seq);

        struct iovec iov = { .iov_base = nlh, .iov_len = nlh->nlmsg_len };
        struct msghdr hdr = { .msg_iov = &iov, .msg_iovlen = 1, };

        int ret = nl_sendmsg(sk, msg, &hdr);
        printf("Bytes: %d\n", ret);
        return 0;
    }
    // Expected bash output:
    // 16 == nlh->nlmsg_len
    // 0 == nlh->nlmsg_type
    // 0 == nlh->nlmsg_flags
    // 0 == nlh->nlmsg_seq
    // 0 == nlh->nlmsg_pid
    // 0 == nlh->nlmsg_seq
    // Bytes: 16
    // EAAAAAAABQAAAAAAAAAAAA==
    """
    msg = nlmsg_alloc()
    nlh = nlmsg_hdr(msg)
    assert 16 == nlh.nlmsg_len
    assert 0 == nlh.nlmsg_type
    assert 0 == nlh.nlmsg_flags
    assert 0 == nlh.nlmsg_seq
    assert 0 == nlh.nlmsg_pid

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.socket_instance.connect(tcp_server.server.server_address)
    sk.s_local.nl_pid = 0
    sk.s_seq_next = 0
    nl_complete_msg(sk, msg)
    assert 0 == nlh.nlmsg_seq
    nlh.nlmsg_pid = 0  # sk.s_local.nl_pid is read-only in Python.

    iov = nlh.bytearray[:nlh.nlmsg_len]
    hdr = msghdr(msg_iov=iov)

    assert 16 == nl_sendmsg(sk, msg, hdr)
    assert 1 == len(tcp_server.data)
    assert b'EAAAAAAABQAAAAAAAAAAAA==' == base64.b64encode(buffer(iov))
    assert b'EAAAAAAABQAAAAAAAAAAAA==' == base64.b64encode(buffer(tcp_server.data[0]))
    nl_socket_free(sk)
示例#36
0
def test_multipart(log, ifaces):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 NLCB=debug ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        // Send data to the kernel.
        printf("Begin main()\n");
        struct nl_sock *sk = nl_socket_alloc();
        printf("Allocated socket.\n");
        printf("%d == nl_connect(sk, NETLINK_ROUTE)\n", nl_connect(sk, NETLINK_ROUTE));
        struct rtgenmsg rt_hdr = { .rtgen_family = AF_PACKET, };
        int ret = nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
        printf("Bytes Sent: %d\n", ret);

        // Retrieve kernel's response.
        printf("%d == nl_recvmsgs_default(sk)\n", nl_recvmsgs_default(sk));

        nl_socket_free(sk);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // Begin main()
    // Allocated socket.
    // 0 == nl_connect(sk, NETLINK_ROUTE)
    // __nlmsg_alloc: msg 0x1bbe0b8: Allocated new message, maxlen=4096
    // nlmsg_alloc_simple: msg 0x1bbe0b8: Allocated new simple message
    // nlmsg_reserve: msg 0x1bbe0b8: Reserved 4 (1) bytes, pad=4, nlmsg_len=20
    // nlmsg_append: msg 0x1bbe0b8: Appended 1 bytes with padding 4
    // -- Debug: Sent Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 20
    //     .type = 18 <0x12>
    //     .flags = 773 <REQUEST,ACK,ROOT,MATCH>
    //     .seq = 1424053819
    //     .port = 18409
    //   [PAYLOAD] 4 octets
    //     11 00 00 00                                     ....
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // nl_sendmsg: sent 20 bytes
    // nlmsg_free: Returned message reference 0x1bbe0b8, 0 remaining
    // nlmsg_free: msg 0x1bbe0b8: Freed
    // Bytes Sent: 20
    // recvmsgs: Attempting to read from 0x1bbe080
    // recvmsgs: recvmsgs(0x1bbe080): Read 3364 bytes
    // recvmsgs: recvmsgs(0x1bbe080): Processing valid message...
    // __nlmsg_alloc: msg 0x1bc20c0: Allocated new message, maxlen=1116
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1116
    //     .type = 16 <0x10>
    //     .flags = 2 <MULTI>
    //     .seq = 1424053819
    //     .port = 18409
    //   [PAYLOAD] 1100 octets
    //     00 00 04 03 01 00 00 00 49 00 01 00 00 00 00 00 ........I.......
    //     <trimmed>
    //     00 00 00 00 00 00 00 00 00 00 00 00             ............
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // -- Debug: Unhandled Valid message: type=0x10 length=1116 flags=<MULTI> sequence-nr=1424053819 pid=18409
    // recvmsgs: recvmsgs(0x1bbe080): Processing valid message...
    // nlmsg_free: Returned message reference 0x1bc20c0, 0 remaining
    // nlmsg_free: msg 0x1bc20c0: Freed
    // __nlmsg_alloc: msg 0x1bc20c0: Allocated new message, maxlen=1124
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1124
    //     .type = 16 <0x10>
    //     .flags = 2 <MULTI>
    //     .seq = 1424053819
    //     .port = 18409
    //   [PAYLOAD] 1108 octets
    //     00 00 01 00 02 00 00 00 43 10 01 00 00 00 00 00 ........C.......
    //     <trimmed>
    //     00 00 00 00                                     ....
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // -- Debug: Unhandled Valid message: type=0x10 length=1124 flags=<MULTI> sequence-nr=1424053819 pid=18409
    // recvmsgs: recvmsgs(0x1bbe080): Processing valid message...
    // nlmsg_free: Returned message reference 0x1bc20c0, 0 remaining
    // nlmsg_free: msg 0x1bc20c0: Freed
    // __nlmsg_alloc: msg 0x1bc20c0: Allocated new message, maxlen=1124
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1124
    //     .type = 16 <0x10>
    //     .flags = 2 <MULTI>
    //     .seq = 1424053819
    //     .port = 18409
    //   [PAYLOAD] 1108 octets
    //     00 00 01 00 03 00 00 00 03 10 00 00 00 00 00 00 ................
    //     <trimmed>
    //     00 00 00 00                                     ....
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // -- Debug: Unhandled Valid message: type=0x10 length=1124 flags=<MULTI> sequence-nr=1424053819 pid=18409
    // nlmsg_free: Returned message reference 0x1bc20c0, 0 remaining
    // nlmsg_free: msg 0x1bc20c0: Freed
    // recvmsgs: Attempting to read from 0x1bbe080
    // recvmsgs: recvmsgs(0x1bbe080): Read 20 bytes
    // recvmsgs: recvmsgs(0x1bbe080): Processing valid message...
    // __nlmsg_alloc: msg 0x1bc20c0: Allocated new message, maxlen=20
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 20
    //     .type = 3 <DONE>
    //     .flags = 2 <MULTI>
    //     .seq = 1424053819
    //     .port = 18409
    //   [PAYLOAD] 4 octets
    //     00 00 00 00                                     ....
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // recvmsgs: recvmsgs(0x1bbe080): Increased expected sequence number to 1424053820
    // -- Debug: End of multipart message block: type=DONE length=20 flags=<MULTI> sequence-nr=1424053819 pid=18409
    // nlmsg_free: Returned message reference 0x1bc20c0, 0 remaining
    // nlmsg_free: msg 0x1bc20c0: Freed
    // 0 == nl_recvmsgs_default(sk)
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    del log[:]
    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    assert 20 == nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, rt_hdr, rt_hdr.SIZEOF)

    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096', log, True)
    assert match('nlmsg_alloc_simple: msg 0x[a-f0-9]+: Allocated new simple message', log, True)
    assert match('nlmsg_reserve: msg 0x[a-f0-9]+: Reserved 4 \(1\) bytes, pad=4, nlmsg_len=20', log, True)
    assert match('nlmsg_append: msg 0x[a-f0-9]+: Appended 1 bytes with padding 4', log, True)
    assert match('nl_msg_out_handler_debug: -- Debug: Sent Message:', log)
    assert match('nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------', log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 20', log)
    assert match('print_hdr:     .type = 18 <0x12>', log)
    assert match('print_hdr:     .flags = 773 <REQUEST,ACK,ROOT,MATCH>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('print_msg:   [PAYLOAD] 4 octets', log)
    assert match('dump_hex:     11 00 00 00                                     ....', log)
    assert match('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------', log)
    assert match('nl_sendmsg: sent 20 bytes', log)
    assert not log

    assert 0 == nl_recvmsgs_default(sk)
    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{4,} bytes', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=\d{3,}', log, True)
    assert match('nl_msg_in_handler_debug: -- Debug: Received Message:', log)
    assert match('nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------', log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = \d{3,}', log, True)
    assert match('print_hdr:     .type = 16 <0x10>', log)
    assert match('print_hdr:     .flags = 2 <MULTI>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('print_msg:   \[PAYLOAD\] \d{3,} octets', log, True)
    assert match('dump_hex:     00 00 04 03 01 00 00 00 49 00 01 00 00 00 00 00 ........I.......', log)
    assert match('dump_hex:     07 00 03 00 6c 6f 00 00 08 00 0d 00 00 00 00 00 ....lo..........', log)
    assert match('dump_hex:     05 00 10 00 00 00 00 00 05 00 11 00 00 00 00 00 ................', log)

    for _ in ifaces:
        # Done testing this payload. Differs too much between Travis and Raspbian, and probably others.
        rem = log.index('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------')
        assert 20 < rem  # At least check that there were a lot of log statements skipped.
        log = log[rem:]
        assert match('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------', log)
        assert match('nl_valid_handler_debug: -- Debug: Unhandled Valid message: type=0x10 length=\d{3,} flags=<MULTI> '
                     'sequence-nr=\d{10,} pid=\d{3,}', log, True)

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read 20 bytes', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=20', log, True)
    assert match('nl_msg_in_handler_debug: -- Debug: Received Message:', log)
    assert match('nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------', log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 20', log)
    assert match('print_hdr:     .type = 3 <DONE>', log)
    assert match('print_hdr:     .flags = 2 <MULTI>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('print_msg:   [PAYLOAD] 4 octets', log)
    assert match('dump_hex:     00 00 00 00                                     ....', log)
    assert match('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------', log)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Increased expected sequence number to \d{4,}', log, True)
    assert match('nl_finish_handler_debug: -- Debug: End of multipart message block: type=DONE length=20 flags=<MULTI> '
                 'sequence-nr=\d{10,} pid=\d{3,}', log, True)

    nl_socket_free(sk)
    assert not log
示例#37
0
文件: test_attr.py 项目: ewa/libnl
def test_socket(tcp_server):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && (nc -l 2000 |base64 &) && sleep 0.1 && ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        struct nl_msg *msg = nlmsg_alloc();
        printf("%d == nla_put_u32()\n", nla_put_u32(msg, 4, 8));
        struct nlmsghdr *nlh = nlmsg_hdr(msg);
        struct nlattr *attr = nlmsg_find_attr(nlh, 0, 4);
        printf("%d == nla_type(attr)\n", nla_type(attr));
        printf("%d == nla_get_u32(attr)\n", nla_get_u32(attr));
        printf("%d == attr->nla_len\n", attr->nla_len);

        struct sockaddr_in sin = { .sin_port = htons(2000), .sin_family = AF_INET, };
        sin.sin_addr.s_addr = inet_addr("127.0.0.1");
        int fd = socket(AF_INET, SOCK_STREAM, 0);
        connect(fd, (struct sockaddr *) &sin, sizeof(sin));

        struct nl_sock *sk = nl_socket_alloc();
        nl_connect(sk, NETLINK_ROUTE);
        sk->s_fd = fd;
        sk->s_local.nl_pid = 0;
        nl_complete_msg(sk, msg);

        struct iovec iov = { .iov_base = attr, .iov_len = attr->nla_len };
        struct msghdr hdr = { .msg_iov = &iov, .msg_iovlen = 1, };

        int ret = nl_sendmsg(sk, msg, &hdr);
        printf("Bytes: %d\n", ret);  // 14
        return 0;
    }
    // Expected bash output:
    // 0 == nla_put_u32()
    // 4 == nla_type(attr)
    // 8 == nla_get_u32(attr)
    // 8 == attr->nla_len
    // Bytes: 8
    // CAAEAAgAAAA=
    """
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_u32(msg, 4, 8)
    nlh = nlmsg_hdr(msg)
    attr = nlmsg_find_attr(nlh, 0, 4)
    assert 4 == libnl.attr.nla_type(attr)
    assert 8 == libnl.attr.nla_get_u32(attr)
    assert 8 == attr.nla_len

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.socket_instance.connect(tcp_server.server.server_address)
    sk.s_local.nl_pid = 0
    nl_complete_msg(sk, msg)

    iov = attr.bytearray[: attr.nla_len]
    hdr = msghdr(msg_iov=iov)

    assert 8 == nl_sendmsg(sk, msg, hdr)
    assert 1 == len(tcp_server.data)
    assert b"CAAEAAgAAAA=" == base64.b64encode(buffer(iov))
    assert b"CAAEAAgAAAA=" == base64.b64encode(buffer(tcp_server.data[0]))
    nl_socket_free(sk)
示例#38
0
def test_socket(tcp_server):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && (nc -l 2000 |base64 &) && sleep 0.1 && ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        struct nl_msg *msg = nlmsg_alloc();
        printf("%d == nla_put_u32()\n", nla_put_u32(msg, 4, 8));
        struct nlmsghdr *nlh = nlmsg_hdr(msg);
        struct nlattr *attr = nlmsg_find_attr(nlh, 0, 4);
        printf("%d == nla_type(attr)\n", nla_type(attr));
        printf("%d == nla_get_u32(attr)\n", nla_get_u32(attr));
        printf("%d == attr->nla_len\n", attr->nla_len);

        struct sockaddr_in sin = { .sin_port = htons(2000), .sin_family = AF_INET, };
        sin.sin_addr.s_addr = inet_addr("127.0.0.1");
        int fd = socket(AF_INET, SOCK_STREAM, 0);
        connect(fd, (struct sockaddr *) &sin, sizeof(sin));

        struct nl_sock *sk = nl_socket_alloc();
        nl_connect(sk, NETLINK_ROUTE);
        sk->s_fd = fd;
        sk->s_local.nl_pid = 0;
        nl_complete_msg(sk, msg);

        struct iovec iov = { .iov_base = attr, .iov_len = attr->nla_len };
        struct msghdr hdr = { .msg_iov = &iov, .msg_iovlen = 1, };

        int ret = nl_sendmsg(sk, msg, &hdr);
        printf("Bytes: %d\n", ret);  // 14
        return 0;
    }
    // Expected bash output:
    // 0 == nla_put_u32()
    // 4 == nla_type(attr)
    // 8 == nla_get_u32(attr)
    // 8 == attr->nla_len
    // Bytes: 8
    // CAAEAAgAAAA=
    """
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_u32(msg, 4, 8)
    nlh = nlmsg_hdr(msg)
    attr = nlmsg_find_attr(nlh, 0, 4)
    assert 4 == libnl.attr.nla_type(attr)
    assert 8 == libnl.attr.nla_get_u32(attr)
    assert 8 == attr.nla_len

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    sk.socket_instance.close()
    sk.socket_instance = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sk.socket_instance.connect(tcp_server.server.server_address)
    sk.s_local.nl_pid = 0
    nl_complete_msg(sk, msg)

    iov = attr.bytearray[:attr.nla_len]
    hdr = msghdr(msg_iov=iov)

    assert 8 == nl_sendmsg(sk, msg, hdr)
    assert 1 == len(tcp_server.data)
    assert b'CAAEAAgAAAA=' == base64.b64encode(buffer(iov))
    assert b'CAAEAAgAAAA=' == base64.b64encode(buffer(tcp_server.data[0]))
    nl_socket_free(sk)
示例#39
0
def test_error(log):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 NLCB=debug ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        // Send data to the kernel.
        printf("Begin main()\n");
        struct nl_sock *sk = nl_socket_alloc();
        printf("Allocated socket.\n");
        printf("%d == nl_connect(sk, NETLINK_ROUTE)\n", nl_connect(sk, NETLINK_ROUTE));
        int ret = nl_send_simple(sk, 0, NLM_F_REQUEST, NULL, 0);
        printf("Bytes Sent: %d\n", ret);

        // Retrieve kernel's response.
        printf("%d == nl_recvmsgs_default(sk)\n", nl_recvmsgs_default(sk));

        nl_socket_free(sk);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // Begin main()
    // Allocated socket.
    // 0 == nl_connect(sk, NETLINK_ROUTE)
    // __nlmsg_alloc: msg 0x3df0b8: Allocated new message, maxlen=4096
    // nlmsg_alloc_simple: msg 0x3df0b8: Allocated new simple message
    // -- Debug: Sent Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 16
    //     .type = 0 <0x0>
    //     .flags = 5 <REQUEST,ACK>
    //     .seq = 1423967746
    //     .port = 29930
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // nl_sendmsg: sent 16 bytes
    // nlmsg_free: Returned message reference 0x3df0b8, 0 remaining
    // nlmsg_free: msg 0x3df0b8: Freed
    // Bytes Sent: 16
    // recvmsgs: Attempting to read from 0x3df080
    // recvmsgs: recvmsgs(0x3df080): Read 36 bytes
    // recvmsgs: recvmsgs(0x3df080): Processing valid message...
    // __nlmsg_alloc: msg 0x3e30c0: Allocated new message, maxlen=36
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 36
    //     .type = 2 <ERROR>
    //     .flags = 0 <>
    //     .seq = 1423967746
    //     .port = 29930
    //   [ERRORMSG] 20 octets
    //     .error = 0 "Success"
    //   [ORIGINAL MESSAGE] 16 octets
    // __nlmsg_alloc: msg 0x3e3128: Allocated new message, maxlen=4096
    //     .nlmsg_len = 16
    //     .type = 0 <0x0>
    //     .flags = 5 <REQUEST,ACK>
    //     .seq = 1423967746
    //     .port = 29930
    // nlmsg_free: Returned message reference 0x3e3128, 0 remaining
    // nlmsg_free: msg 0x3e3128: Freed
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // recvmsgs: recvmsgs(0x3df080): Increased expected sequence number to 1423967746
    // -- Debug: ACK: type=ERROR length=36 flags=<> sequence-nr=1423967746 pid=29930
    // nlmsg_free: Returned message reference 0x3e30c0, 0 remaining
    // nlmsg_free: msg 0x3e30c0: Freed
    // 0 == nl_recvmsgs_default(sk)
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    del log[:]
    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    assert 16 == nl_send_simple(sk, 0, NLM_F_REQUEST, None)

    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096', log, True)
    assert match('nlmsg_alloc_simple: msg 0x[a-f0-9]+: Allocated new simple message', log, True)
    assert match('nl_msg_out_handler_debug: -- Debug: Sent Message:', log)
    assert match('nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------', log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 16', log)
    assert match('print_hdr:     .type = 0 <0x0>', log)
    assert match('print_hdr:     .flags = 5 <REQUEST,ACK>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------', log)
    assert match('nl_sendmsg: sent 16 bytes', log)
    assert not log

    assert 0 == nl_recvmsgs_default(sk)
    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read 36 bytes', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=36', log, True)
    assert match('nl_msg_in_handler_debug: -- Debug: Received Message:', log)
    assert match('nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------', log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 36', log)
    assert match('print_hdr:     .type = 2 <ERROR>', log)
    assert match('print_hdr:     .flags = 0 <>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('dump_error_msg:   [ERRORMSG] 20 octets', log)
    assert match('dump_error_msg:     .error = 0 "Success"', log)
    assert match('dump_error_msg:   [ORIGINAL MESSAGE] 16 octets', log)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096', log, True)
    assert match('print_hdr:     .nlmsg_len = 16', log)
    assert match('print_hdr:     .type = 0 <0x0>', log)
    assert match('print_hdr:     .flags = 5 <REQUEST,ACK>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------', log)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Increased expected sequence number to \d{4,}', log, True)
    assert match('nl_ack_handler_debug: -- Debug: ACK: type=ERROR length=36 flags=<> sequence-nr=\d{10,} pid=\d{3,}',
                 log, True)
    nl_socket_free(sk)
    assert not log
示例#40
0
def test_multipart_verbose(log, ifaces):
    """Expected output (trimmed).

    // nl_cache_mngt_register: Registered cache operations genl/family
    // Begin main()
    // Allocated socket.
    // 0 == nl_connect(sk, NETLINK_ROUTE)
    // __nlmsg_alloc: msg 0xa180b8: Allocated new message, maxlen=4096
    // nlmsg_alloc_simple: msg 0xa180b8: Allocated new simple message
    // nlmsg_reserve: msg 0xa180b8: Reserved 4 (1) bytes, pad=4, nlmsg_len=20
    // nlmsg_append: msg 0xa180b8: Appended 1 bytes with padding 4
    // nl_sendmsg: sent 20 bytes
    // nlmsg_free: Returned message reference 0xa180b8, 0 remaining
    // nlmsg_free: msg 0xa180b8: Freed
    // Bytes Sent: 20
    // recvmsgs: Attempting to read from 0xa18080
    // recvmsgs: recvmsgs(0xa18080): Read 3364 bytes
    // recvmsgs: recvmsgs(0xa18080): Processing valid message...
    // __nlmsg_alloc: msg 0xa1c0c0: Allocated new message, maxlen=1116
    // -- Warning: unhandled valid message: type=0x10 length=1116 flags=<MULTI> sequence-nr=1424132449 pid=5810
    // recvmsgs: recvmsgs(0xa18080): Processing valid message...
    // nlmsg_free: Returned message reference 0xa1c0c0, 0 remaining
    // nlmsg_free: msg 0xa1c0c0: Freed
    // __nlmsg_alloc: msg 0xa1c0c0: Allocated new message, maxlen=1124
    // -- Warning: unhandled valid message: type=0x10 length=1124 flags=<MULTI> sequence-nr=1424132449 pid=5810
    // recvmsgs: recvmsgs(0xa18080): Processing valid message...
    // nlmsg_free: Returned message reference 0xa1c0c0, 0 remaining
    // nlmsg_free: msg 0xa1c0c0: Freed
    // __nlmsg_alloc: msg 0xa1c0c0: Allocated new message, maxlen=1124
    // -- Warning: unhandled valid message: type=0x10 length=1124 flags=<MULTI> sequence-nr=1424132449 pid=5810
    // nlmsg_free: Returned message reference 0xa1c0c0, 0 remaining
    // nlmsg_free: msg 0xa1c0c0: Freed
    // recvmsgs: Attempting to read from 0xa18080
    // recvmsgs: recvmsgs(0xa18080): Read 20 bytes
    // recvmsgs: recvmsgs(0xa18080): Processing valid message...
    // __nlmsg_alloc: msg 0xa1c0c0: Allocated new message, maxlen=20
    // recvmsgs: recvmsgs(0xa18080): Increased expected sequence number to 1424132450
    // nlmsg_free: Returned message reference 0xa1c0c0, 0 remaining
    // nlmsg_free: msg 0xa1c0c0: Freed
    // 0 == nl_recvmsgs_default(sk)
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    del log[:]
    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    assert 20 == nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, rt_hdr, rt_hdr.SIZEOF)

    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096', log, True)
    assert match('nlmsg_alloc_simple: msg 0x[a-f0-9]+: Allocated new simple message', log, True)
    assert match('nlmsg_reserve: msg 0x[a-f0-9]+: Reserved 4 \(1\) bytes, pad=4, nlmsg_len=20', log, True)
    assert match('nlmsg_append: msg 0x[a-f0-9]+: Appended 1 bytes with padding 4', log, True)
    assert match('nl_sendmsg: sent 20 bytes', log)
    assert not log

    assert 0 == nl_recvmsgs_default(sk)
    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{4,} bytes', log, True)

    for _ in ifaces:
        if 'Attempting to read' in log[0]:
            # Lots of network interfaces on this host.
            assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
            assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{4,} bytes', log, True)
        assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
        assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=\d{3,}', log, True)
        assert match('nl_valid_handler_verbose: -- Warning: unhandled valid message: type=0x10 length=\d{3,} '
                     'flags=<MULTI> sequence-nr=\d{10,} pid=\d{3,}', log, True)

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read 20 bytes', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=20', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Increased expected sequence number to \d{4,}', log, True)

    nl_socket_free(sk)
    assert not log
示例#41
0
文件: test_ctrl.py 项目: 0x90/libnl
def test_ctrl_cmd_getfamily_hex_dump(log):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    static void prefix_line(FILE *ofd, int prefix) { int i; for (i = 0; i < prefix; i++) fprintf(ofd, "  "); }
    static inline void dump_hex(FILE *ofd, char *start, int len, int prefix) {
        int i, a, c, limit; char ascii[21] = {0}; limit = 16 - (prefix * 2); prefix_line(ofd, prefix);
        fprintf(ofd, "    ");
        for (i = 0, a = 0, c = 0; i < len; i++) {
            int v = *(uint8_t *) (start + i); fprintf(ofd, "%02x ", v); ascii[a++] = isprint(v) ? v : '.';
            if (++c >= limit) {
                fprintf(ofd, "%s\n", ascii);
                if (i < (len - 1)) { prefix_line(ofd, prefix); fprintf(ofd, "    "); }
                a = c = 0;
                memset(ascii, 0, sizeof(ascii));
            }
        }
        if (c != 0) { for (i = 0; i < (limit - c); i++) fprintf(ofd, "   "); fprintf(ofd, "%s\n", ascii); }
    }
    struct ucred { pid_t pid; uid_t uid; gid_t gid; };
    struct nl_msg {
        int nm_protocol; int nm_flags; struct sockaddr_nl nm_src; struct sockaddr_nl nm_dst; struct ucred nm_creds;
        struct nlmsghdr *nm_nlh; size_t nm_size; int nm_refcnt;
    };
    static int callback_send(struct nl_sock *sk, struct nl_msg *msg) {
        printf("%d == msg.nm_protocol\n", msg->nm_protocol);
        printf("%d == msg.nm_flags\n", msg->nm_flags);
        printf("%d == msg.nm_src.nl_family\n", msg->nm_src.nl_family);
        printf("%d == msg.nm_src.nl_pid\n", msg->nm_src.nl_pid);
        printf("%d == msg.nm_src.nl_groups\n", msg->nm_src.nl_groups);
        printf("%d == msg.nm_dst.nl_family\n", msg->nm_dst.nl_family);
        printf("%d == msg.nm_dst.nl_pid\n", msg->nm_dst.nl_pid);
        printf("%d == msg.nm_dst.nl_groups\n", msg->nm_dst.nl_groups);
        printf("%d == msg.nm_creds.pid\n", msg->nm_creds.pid);
        printf("%d == msg.nm_creds.uid\n", msg->nm_creds.uid);
        printf("%d == msg.nm_creds.gid\n", msg->nm_creds.gid);
        printf("%d == msg.nm_nlh.nlmsg_type\n", msg->nm_nlh->nlmsg_type);
        printf("%d == msg.nm_nlh.nlmsg_flags\n", msg->nm_nlh->nlmsg_flags);
        printf("%d == msg.nm_nlh.nlmsg_pid\n", msg->nm_nlh->nlmsg_pid);
        printf("%d == msg.nm_size\n", msg->nm_size);
        printf("%d == msg.nm_refcnt\n", msg->nm_refcnt);
        struct iovec iov = { .iov_base = (void *) nlmsg_hdr(msg), .iov_len = nlmsg_hdr(msg)->nlmsg_len, };
        dump_hex(stdout, iov.iov_base, iov.iov_len, 0);
        return nl_send_iovec(sk, msg, &iov, 1);
    }
    static int callback_recv(struct nl_sock *sk, struct sockaddr_nl *nla, unsigned char **buf, struct ucred **creds) {
        int n = nl_recv(sk, nla, buf, creds);
        dump_hex(stdout, (void *) *buf, n, 0);
        return n;
    }
    static int callback_recv_msg(struct nl_msg *msg, void *arg) {
        printf("%d == msg.nm_protocol\n", msg->nm_protocol);
        printf("%d == msg.nm_flags\n", msg->nm_flags);
        printf("%d == msg.nm_src.nl_family\n", msg->nm_src.nl_family);
        printf("%d == msg.nm_src.nl_pid\n", msg->nm_src.nl_pid);
        printf("%d == msg.nm_src.nl_groups\n", msg->nm_src.nl_groups);
        printf("%d == msg.nm_dst.nl_family\n", msg->nm_dst.nl_family);
        printf("%d == msg.nm_dst.nl_pid\n", msg->nm_dst.nl_pid);
        printf("%d == msg.nm_dst.nl_groups\n", msg->nm_dst.nl_groups);
        printf("%d == msg.nm_creds.pid\n", msg->nm_creds.pid);
        printf("%d == msg.nm_creds.uid\n", msg->nm_creds.uid);
        printf("%d == msg.nm_creds.gid\n", msg->nm_creds.gid);
        printf("%d == msg.nm_nlh.nlmsg_type\n", msg->nm_nlh->nlmsg_type);
        printf("%d == msg.nm_nlh.nlmsg_flags\n", msg->nm_nlh->nlmsg_flags);
        printf("%d == msg.nm_nlh.nlmsg_pid\n", msg->nm_nlh->nlmsg_pid);
        printf("%d == msg.nm_size\n", msg->nm_size);
        printf("%d == msg.nm_refcnt\n", msg->nm_refcnt);
        dump_hex(stdout, (char *) msg->nm_nlh, nlmsg_datalen(msg->nm_nlh), 0);
        return NL_OK;
    }
    int main() {
        struct nl_sock *sk = nl_socket_alloc();
        nl_cb_overwrite_send(sk->s_cb, callback_send);
        nl_cb_overwrite_recv(sk->s_cb, callback_recv);
        printf("%d == genl_connect(sk)\n", genl_connect(sk));
        struct genl_family *ret = (struct genl_family *) genl_family_alloc();
        genl_family_set_name(ret, "nl80211");
        struct nl_msg *msg = nlmsg_alloc();
        genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1);
        nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, "nl80211");
        nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, callback_recv_msg, NULL);
        printf("%d == nl_send_auto(sk, msg)\n", nl_send_auto(sk, msg));
        printf("%d == nl_recvmsgs_default(sk)\n", nl_recvmsgs_default(sk));
        nl_socket_free(sk);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // 0 == genl_connect(sk)
    //  nl_object_alloc: Allocated new object 0x2b50b8
    // __nlmsg_alloc: msg 0x2b5110: Allocated new message, maxlen=4096
    // nlmsg_put: msg 0x2b5110: Added netlink header type=16, flags=0, pid=0, seq=0
    // nlmsg_reserve: msg 0x2b5110: Reserved 4 (4) bytes, pad=4, nlmsg_len=20
    // genlmsg_put: msg 0x2b5110: Added generic netlink header cmd=3 version=1
    // nla_reserve: msg 0x2b5110: attr <0x2b5164> 2: Reserved 12 (8) bytes at offset +4 nlmsg_len=32
    // nla_put: msg 0x2b5110: attr <0x2b5164> 2: Wrote 8 bytes at offset +4
    // 16 == msg.nm_protocol
    // 0 == msg.nm_flags
    // 0 == msg.nm_src.nl_family
    // 0 == msg.nm_src.nl_pid
    // 0 == msg.nm_src.nl_groups
    // 0 == msg.nm_dst.nl_family
    // 0 == msg.nm_dst.nl_pid
    // 0 == msg.nm_dst.nl_groups
    // 0 == msg.nm_creds.pid
    // 0 == msg.nm_creds.uid
    // 0 == msg.nm_creds.gid
    // 16 == msg.nm_nlh.nlmsg_type
    // 5 == msg.nm_nlh.nlmsg_flags
    // 14272 == msg.nm_nlh.nlmsg_pid
    // 4096 == msg.nm_size
    // 1 == msg.nm_refcnt
    //     20 00 00 00 10 00 05 00 af aa f6 54 c0 37 00 00  ..........T.7..
    //     03 01 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.
    // nl_sendmsg: sent 32 bytes
    // 32 == nl_send_auto(sk, msg)
    // recvmsgs: Attempting to read from 0x2b5080
    //     2c 07 00 00 10 00 00 00 af aa f6 54 c0 37 00 00 ,..........T.7..
    //     01 02 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.
    //     06 00 01 00 16 00 00 00 08 00 03 00 01 00 00 00 ................
    //     08 00 04 00 00 00 00 00 08 00 05 00 d5 00 00 00 ................
    //     6c 06 06 00 14 00 01 00 08 00 01 00 01 00 00 00 l...............
    //     08 00 02 00 0e 00 00 00 14 00 02 00 08 00 01 00 ................
    //     <trimmed>
    //     63 6f 6e 66 69 67 00 00 18 00 02 00 08 00 02 00 config..........
    //     04 00 00 00 09 00 01 00 73 63 61 6e 00 00 00 00 ........scan....
    //     1c 00 03 00 08 00 02 00 05 00 00 00 0f 00 01 00 ................
    //     72 65 67 75 6c 61 74 6f 72 79 00 00 18 00 04 00 regulatory......
    //     08 00 02 00 06 00 00 00 09 00 01 00 6d 6c 6d 65 ............mlme
    //     00 00 00 00 18 00 05 00 08 00 02 00 07 00 00 00 ................
    //     0b 00 01 00 76 65 6e 64 6f 72 00 00             ....vendor..
    // recvmsgs: recvmsgs(0x2b5080): Read 1836 bytes
    // recvmsgs: recvmsgs(0x2b5080): Processing valid message...
    // __nlmsg_alloc: msg 0x2ba160: Allocated new message, maxlen=1836
    // 16 == msg.nm_protocol
    // 0 == msg.nm_flags
    // 16 == msg.nm_src.nl_family
    // 0 == msg.nm_src.nl_pid
    // 0 == msg.nm_src.nl_groups
    // 0 == msg.nm_dst.nl_family
    // 0 == msg.nm_dst.nl_pid
    // 0 == msg.nm_dst.nl_groups
    // 0 == msg.nm_creds.pid
    // 0 == msg.nm_creds.uid
    // 0 == msg.nm_creds.gid
    // 16 == msg.nm_nlh.nlmsg_type
    // 0 == msg.nm_nlh.nlmsg_flags
    // 14272 == msg.nm_nlh.nlmsg_pid
    // 1836 == msg.nm_size
    // 1 == msg.nm_refcnt
    //     2c 07 00 00 10 00 00 00 af aa f6 54 c0 37 00 00 ,..........T.7..
    //     01 02 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.
    //     06 00 01 00 16 00 00 00 08 00 03 00 01 00 00 00 ................
    //     08 00 04 00 00 00 00 00 08 00 05 00 d5 00 00 00 ................
    //     6c 06 06 00 14 00 01 00 08 00 01 00 01 00 00 00 l...............
    //     08 00 02 00 0e 00 00 00 14 00 02 00 08 00 01 00 ................
    //     <trimmed>
    //     63 6f 6e 66 69 67 00 00 18 00 02 00 08 00 02 00 config..........
    //     04 00 00 00 09 00 01 00 73 63 61 6e 00 00 00 00 ........scan....
    //     1c 00 03 00 08 00 02 00 05 00 00 00 0f 00 01 00 ................
    //     72 65 67 75 6c 61 74 6f 72 79 00 00 18 00 04 00 regulatory......
    //     08 00 02 00 06 00 00 00 09 00 01 00 6d 6c 6d 65 ............mlme
    //     00 00 00 00 18 00 05 00 08 00 02 00             ............
    // nlmsg_free: Returned message reference 0x2ba160, 0 remaining
    // nlmsg_free: msg 0x2ba160: Freed
    // 0 == nl_recvmsgs_default(sk)
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    def callback_send(sk, msg):
        assert 16 == msg.nm_protocol
        assert 0 == msg.nm_flags
        assert 0 == msg.nm_src.nl_family
        assert 0 == msg.nm_src.nl_pid
        assert 0 == msg.nm_src.nl_groups
        assert 0 == msg.nm_dst.nl_family
        assert 0 == msg.nm_dst.nl_pid
        assert 0 == msg.nm_dst.nl_groups
        assert msg.nm_creds is None
        assert 16 == msg.nm_nlh.nlmsg_type
        assert 5 == msg.nm_nlh.nlmsg_flags
        assert 100 < msg.nm_nlh.nlmsg_pid
        assert 1 == msg.nm_refcnt
        hdr = nlmsg_hdr(msg)
        iov = hdr.bytearray[:hdr.nlmsg_len]
        dump_hex(logging.getLogger().debug, iov, len(iov), 0)
        return nl_send_iovec(sk, msg, iov, 1)

    def callback_recv(sk, nla, buf, creds):
        n = nl_recv(sk, nla, buf, creds)
        dump_hex(logging.getLogger().debug, buf, len(buf), 0)
        return n

    def callback_recv_msg(msg, _):
        assert 16 == msg.nm_protocol
        assert 0 == msg.nm_flags
        assert 16 == msg.nm_src.nl_family
        assert 0 == msg.nm_src.nl_pid
        assert 0 == msg.nm_src.nl_groups
        assert 0 == msg.nm_dst.nl_family
        assert 0 == msg.nm_dst.nl_pid
        assert 0 == msg.nm_dst.nl_groups
        assert msg.nm_creds is None
        assert 16 == msg.nm_nlh.nlmsg_type
        assert 0 == msg.nm_nlh.nlmsg_flags
        assert 100 < msg.nm_nlh.nlmsg_pid
        assert 1000 < msg.nm_size
        assert 1 == msg.nm_refcnt
        dump_hex(logging.getLogger().debug, msg.nm_nlh.bytearray, nlmsg_datalen(msg.nm_nlh), 0)
        return NL_OK

    del log[:]
    sk_main = nl_socket_alloc()
    nl_cb_overwrite_send(sk_main.s_cb, callback_send)
    nl_cb_overwrite_recv(sk_main.s_cb, callback_recv)
    genl_connect(sk_main)
    ret = genl_family_alloc()
    genl_family_set_name(ret, b'nl80211')
    msg_main = nlmsg_alloc()
    genlmsg_put(msg_main, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1)
    nla_put_string(msg_main, CTRL_ATTR_FAMILY_NAME, b'nl80211')
    nl_socket_modify_cb(sk_main, NL_CB_VALID, NL_CB_CUSTOM, callback_recv_msg, None)
    assert 32 == nl_send_auto(sk_main, msg_main)
    assert 0 == nl_recvmsgs_default(sk_main)
    nl_socket_free(sk_main)

    assert match('nl_object_alloc: Allocated new object 0x[a-f0-9]+', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096', log, True)
    assert match('nlmsg_put: msg 0x[a-f0-9]+: Added netlink header type=16, flags=0, pid=0, seq=0', log, True)
    assert match('nlmsg_reserve: msg 0x[a-f0-9]+: Reserved 4 \(4\) bytes, pad=4, nlmsg_len=20', log, True)
    assert match('genlmsg_put: msg 0x[a-f0-9]+: Added generic netlink header cmd=3 version=1', log, True)
    assert match(
        'nla_reserve: msg 0x[a-f0-9]+: attr <0x[a-f0-9]+> 2: Reserved 12 \(8\) bytes at offset \+4 nlmsg_len=32',
        log, True)
    assert match('nla_put: msg 0x[a-f0-9]+: attr <0x[a-f0-9]+> 2: Wrote 8 bytes at offset \+4', log, True)

    assert match('dump_hex:     20 00 00 00 10 00 05 00 .. .. .. .. .. .. 00 00  ...............', log, True)
    assert match('dump_hex:     03 01 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.', log)

    assert match('nl_sendmsg: sent 32 bytes', log)
    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)

    assert match('dump_hex:     .. .. 00 00 10 00 00 00 .. .. .. .. .. .. 00 00 ................', log, True)
    assert match('dump_hex:     01 02 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.', log)
    assert match('dump_hex:     06 00 01 00 .. 00 00 00 08 00 03 00 01 00 00 00 ................', log, True)
    assert match('dump_hex:     08 00 04 00 00 00 00 00 08 00 05 00 .. 00 00 00 ................', log, True)

    for i in range(len(log)):
        if re.match(r'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{4,} bytes', log[i]):
            log = log[i:]
            break

    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{3,} bytes', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=\d{3,}', log, True)

    assert match('dump_hex:     .. .. 00 00 10 00 00 00 .. .. .. .. .. .. 00 00 ................', log, True)
    assert match('dump_hex:     01 02 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.', log)
    assert match('dump_hex:     06 00 01 00 .. 00 00 00 08 00 03 00 01 00 00 00 ................', log, True)
    assert match('dump_hex:     08 00 04 00 00 00 00 00 08 00 05 00 .. 00 00 00 ................', log, True)

    while log and log[0].startswith('dump_hex:'):
        log.pop(0)
    assert not log
示例#42
0
def test_defaults(log):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 ./a.out
    #include <netlink/msg.h>
    struct ucred { __u32 pid; __u32 uid; __u32 gid; };
    struct nl_msg {
        int nm_protocol; int nm_flags; struct sockaddr_nl nm_src; struct sockaddr_nl nm_dst; struct ucred nm_creds;
        struct nlmsghdr *nm_nlh; size_t nm_size; int nm_refcnt;
    };
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    void print(struct nl_msg *msg) {
        printf("%d == msg.nm_protocol\n", msg->nm_protocol);
        printf("%d == msg.nm_flags\n", msg->nm_flags);
        printf("%d == msg.nm_src.nl_family\n", msg->nm_src.nl_family);
        printf("%d == msg.nm_src.nl_pid\n", msg->nm_src.nl_pid);
        printf("%d == msg.nm_src.nl_groups\n", msg->nm_src.nl_groups);
        printf("%d == msg.nm_dst.nl_family\n", msg->nm_dst.nl_family);
        printf("%d == msg.nm_dst.nl_pid\n", msg->nm_dst.nl_pid);
        printf("%d == msg.nm_dst.nl_groups\n", msg->nm_dst.nl_groups);
        printf("%d == msg.nm_nlh.nlmsg_type\n", msg->nm_nlh->nlmsg_type);
        printf("%d == msg.nm_nlh.nlmsg_flags\n", msg->nm_nlh->nlmsg_flags);
        printf("%d == msg.nm_nlh.nlmsg_pid\n", msg->nm_nlh->nlmsg_pid);
    }
    int main() {
        printf("Begin main()\n");
        struct nl_sock *sk = nl_socket_alloc();
        printf("Allocated socket.\n");
        struct nl_msg *msg = nlmsg_alloc_simple(0, 0);
        printf("Allocated message.\n");
        printf("%d == nl_socket_get_local_port(sk)\n", nl_socket_get_local_port(sk));
        printf("%d == sk.s_proto\n", sk->s_proto);
        printf("\n");
        print(msg);
        printf("\n");
        nl_complete_msg(sk, msg);
        print(msg);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // Begin main()
    // Allocated socket.
    // __nlmsg_alloc: msg 0x1e9c0b8: Allocated new message, maxlen=4096
    // nlmsg_alloc_simple: msg 0x1e9c0b8: Allocated new simple message
    // Allocated message.
    // 10083 == nl_socket_get_local_port(sk)
    // 0 == sk.s_proto
    //
    // -1 == msg.nm_protocol
    // 0 == msg.nm_flags
    // 0 == msg.nm_src.nl_family
    // 0 == msg.nm_src.nl_pid
    // 0 == msg.nm_src.nl_groups
    // 0 == msg.nm_dst.nl_family
    // 0 == msg.nm_dst.nl_pid
    // 0 == msg.nm_dst.nl_groups
    // 0 == msg.nm_nlh.nlmsg_type
    // 0 == msg.nm_nlh.nlmsg_flags
    // 0 == msg.nm_nlh.nlmsg_pid
    //
    // 0 == msg.nm_protocol
    // 0 == msg.nm_flags
    // 0 == msg.nm_src.nl_family
    // 0 == msg.nm_src.nl_pid
    // 0 == msg.nm_src.nl_groups
    // 0 == msg.nm_dst.nl_family
    // 0 == msg.nm_dst.nl_pid
    // 0 == msg.nm_dst.nl_groups
    // 0 == msg.nm_nlh.nlmsg_type
    // 5 == msg.nm_nlh.nlmsg_flags
    // 10083 == msg.nm_nlh.nlmsg_pid
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    del log[:]
    sk = nl_socket_alloc()
    msg = nlmsg_alloc_simple(0, 0)
    assert re.match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message', log.pop(0))
    assert re.match('nlmsg_alloc_simple: msg 0x[a-f0-9]+: Allocated new simple message', log.pop(0))
    local_port = int(nl_socket_get_local_port(sk))
    proto = int(sk.s_proto)

    assert 0 < local_port
    assert 0 == proto

    assert -1 == msg.nm_protocol
    assert 0 == msg.nm_flags
    assert 0 == msg.nm_src.nl_family
    assert 0 == msg.nm_src.nl_pid
    assert 0 == msg.nm_src.nl_groups
    assert 0 == msg.nm_dst.nl_family
    assert 0 == msg.nm_dst.nl_pid
    assert 0 == msg.nm_dst.nl_groups
    assert 0 == msg.nm_nlh.nlmsg_type
    assert 0 == msg.nm_nlh.nlmsg_flags
    assert 0 == msg.nm_nlh.nlmsg_pid

    nl_complete_msg(sk, msg)
    assert proto == msg.nm_protocol
    assert 0 == msg.nm_flags
    assert 0 == msg.nm_src.nl_family
    assert 0 == msg.nm_src.nl_pid
    assert 0 == msg.nm_src.nl_groups
    assert 0 == msg.nm_dst.nl_family
    assert 0 == msg.nm_dst.nl_pid
    assert 0 == msg.nm_dst.nl_groups
    assert 0 == msg.nm_nlh.nlmsg_type
    assert 5 == msg.nm_nlh.nlmsg_flags
    assert local_port == msg.nm_nlh.nlmsg_pid

    assert not log
    nl_socket_free(sk)
示例#43
0
def test_nl_connect():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    #include <dirent.h>
    struct nl_cb {
        nl_recvmsg_msg_cb_t cb_set[NL_CB_TYPE_MAX+1]; void * cb_args[NL_CB_TYPE_MAX+1]; nl_recvmsg_err_cb_t cb_err;
        void * cb_err_arg; int (*cb_recvmsgs_ow)(struct nl_sock *, struct nl_cb *);
        int (*cb_recv_ow)(struct nl_sock *, struct sockaddr_nl *, unsigned char **, struct ucred **);
        int (*cb_send_ow)(struct nl_sock *, struct nl_msg *); int cb_refcnt; enum nl_cb_type cb_active;
    };
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    void print_fd_count() {
        int fd_count = 0; char buf[64]; struct dirent *dp;
        snprintf(buf, 256, "/proc/self/fd/");
        DIR *dir = opendir(buf); while ((dp = readdir(dir)) != NULL) fd_count++; closedir(dir);
        printf("fd_count: %d\n", fd_count);
    }
    void print(struct nl_sock *sk) {
        printf("sk.s_local.nl_family = %d\n", sk->s_local.nl_family);
        printf("sk.s_local.nl_pid = %d  # changes every process, remains same throughout proc.\n", sk->s_local.nl_pid);
        printf("sk.s_local.nl_groups = %d\n", sk->s_local.nl_groups);
        printf("sk.s_peer.nl_family = %d\n", sk->s_peer.nl_family);
        printf("sk.s_peer.nl_pid = %d\n", sk->s_peer.nl_pid);
        printf("sk.s_peer.nl_groups = %d\n", sk->s_peer.nl_groups);
        printf("sk.s_fd = %d\n", sk->s_fd);
        printf("sk.s_proto = %d\n", sk->s_proto);
        printf("sk.s_flags = %d\n", sk->s_flags);
        printf("sk.s_cb.cb_active = %d\n", sk->s_cb->cb_active);
        printf("addr: sk.s_cb.cb_err = %p\n", sk->s_cb->cb_err);
    }
    int main() {
        struct nl_sock *sk = nl_socket_alloc();
        print_fd_count();
        print(sk);
        printf("\n");

        printf("nl_connect(): %d\n", nl_connect(sk, NETLINK_ROUTE));
        print_fd_count();
        print(sk);
        nl_socket_free(sk);
        print_fd_count();
        print(sk);
        printf("\n");

        sk = nl_socket_alloc();
        printf("nl_connect(): %d\n", nl_connect(sk, NETLINK_GENERIC));
        print_fd_count();
        print(sk);
        nl_socket_free(sk);
        print_fd_count();
        printf("\n");
        return 0;
    }
    // Expected output:
    // fd_count: 6
    // sk.s_local.nl_family = 16
    // sk.s_local.nl_pid = 3121  # changes every process, remains same throughout proc.
    // sk.s_local.nl_groups = 0
    // sk.s_peer.nl_family = 16
    // sk.s_peer.nl_pid = 0
    // sk.s_peer.nl_groups = 0
    // sk.s_fd = -1
    // sk.s_proto = 0
    // sk.s_flags = 0
    // sk.s_cb.cb_active = 11
    // addr: sk.s_cb.cb_err = (nil)
    //
    // nl_connect(): 0
    // fd_count: 7
    // sk.s_local.nl_family = 16
    // sk.s_local.nl_pid = 3121  # changes every process, remains same throughout proc.
    // sk.s_local.nl_groups = 0
    // sk.s_peer.nl_family = 16
    // sk.s_peer.nl_pid = 0
    // sk.s_peer.nl_groups = 0
    // sk.s_fd = 3
    // sk.s_proto = 0
    // sk.s_flags = 1
    // sk.s_cb.cb_active = 11
    // addr: sk.s_cb.cb_err = (nil)
    // fd_count: 6
    // sk.s_local.nl_family = 16
    // sk.s_local.nl_pid = 167775232  # changes every process, remains same throughout proc.
    // sk.s_local.nl_groups = 0
    // sk.s_peer.nl_family = 16
    // sk.s_peer.nl_pid = 0
    // sk.s_peer.nl_groups = 0
    // sk.s_fd = 3
    // sk.s_proto = 0
    // sk.s_flags = 1
    // sk.s_cb.cb_active = 18774
    // addr: sk.s_cb.cb_err = 0x310a0010
    //
    // nl_connect(): 0
    // fd_count: 7
    // sk.s_local.nl_family = 16
    // sk.s_local.nl_pid = 3121  # changes every process, remains same throughout proc.
    // sk.s_local.nl_groups = 0
    // sk.s_peer.nl_family = 16
    // sk.s_peer.nl_pid = 0
    // sk.s_peer.nl_groups = 0
    // sk.s_fd = 3
    // sk.s_proto = 16
    // sk.s_flags = 1
    // sk.s_cb.cb_active = 11
    // addr: sk.s_cb.cb_err = (nil)
    // fd_count: 6
    """
    initial_fd_count = len(os.listdir('/proc/self/fd'))
    assert 2 <= initial_fd_count

    # Allocate but don't connect/bind.
    sk = nl_socket_alloc()
    assert initial_fd_count == len(os.listdir('/proc/self/fd'))
    assert 16 == sk.s_local.nl_family
    assert 0 < sk.s_local.nl_pid
    assert 0 == sk.s_local.nl_groups
    assert 16 == sk.s_peer.nl_family
    assert 0 == sk.s_peer.nl_pid
    assert 0 == sk.s_peer.nl_groups
    assert -1 == sk.s_fd
    assert 0 == sk.s_proto
    assert 0 == sk.s_flags
    assert 11 == sk.s_cb.cb_active
    assert sk.s_cb.cb_err is None
    persistent_pid = int(sk.s_local.nl_pid)

    # Connect, then close the socket at the end.
    assert 0 == nl_connect(sk, NETLINK_ROUTE)
    assert initial_fd_count + 1 == len(os.listdir('/proc/self/fd'))
    assert 16 == sk.s_local.nl_family
    assert persistent_pid == sk.s_local.nl_pid
    assert 0 == sk.s_local.nl_groups
    assert 16 == sk.s_peer.nl_family
    assert 0 == sk.s_peer.nl_pid
    assert 0 == sk.s_peer.nl_groups
    assert 0 < sk.s_fd
    assert 0 == sk.s_proto
    assert 1 == sk.s_flags
    assert 11 == sk.s_cb.cb_active
    assert sk.s_cb.cb_err is None
    persistent_fd = int(sk.s_fd)
    nl_socket_free(sk)
    assert initial_fd_count == len(os.listdir('/proc/self/fd'))
    assert 16 == sk.s_local.nl_family
    # assert persistent_pid == sk.s_local.nl_pid  # In C, pointer points to deallocated memory. In Python, leave alone.
    assert 0 == sk.s_local.nl_groups
    assert 16 == sk.s_peer.nl_family
    assert 0 == sk.s_peer.nl_pid
    assert 0 == sk.s_peer.nl_groups
    # assert persistent_fd == sk.s_fd  # In C, s_fd is a regular int. In Python, it's a class property.
    assert 0 == sk.s_proto
    assert 1 == sk.s_flags
    # assert 11 == sk.s_cb.cb_active  # In C, pointer points to deallocated memory. In Python, leave alone.
    # assert sk.s_cb.cb_err is None  # In C, pointer points to deallocated memory. In Python, leave alone.

    # Re-allocate and connect again, pid should be the same as the previous session.
    sk = nl_socket_alloc()
    assert 0 == nl_connect(sk, NETLINK_GENERIC)
    assert initial_fd_count + 1 == len(os.listdir('/proc/self/fd'))
    assert 16 == sk.s_local.nl_family
    assert persistent_pid == sk.s_local.nl_pid
    assert 0 == sk.s_local.nl_groups
    assert 16 == sk.s_peer.nl_family
    assert 0 == sk.s_peer.nl_pid
    assert 0 == sk.s_peer.nl_groups
    assert persistent_fd == sk.s_fd
    assert 16 == sk.s_proto
    assert 1 == sk.s_flags
    assert 11 == sk.s_cb.cb_active
    assert sk.s_cb.cb_err is None
    nl_socket_free(sk)
    assert initial_fd_count == len(os.listdir('/proc/self/fd'))
示例#44
0
def test_ctrl_cmd_getfamily_hex_dump(log):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    static void prefix_line(FILE *ofd, int prefix) { int i; for (i = 0; i < prefix; i++) fprintf(ofd, "  "); }
    static inline void dump_hex(FILE *ofd, char *start, int len, int prefix) {
        int i, a, c, limit; char ascii[21] = {0}; limit = 16 - (prefix * 2); prefix_line(ofd, prefix);
        fprintf(ofd, "    ");
        for (i = 0, a = 0, c = 0; i < len; i++) {
            int v = *(uint8_t *) (start + i); fprintf(ofd, "%02x ", v); ascii[a++] = isprint(v) ? v : '.';
            if (++c >= limit) {
                fprintf(ofd, "%s\n", ascii);
                if (i < (len - 1)) { prefix_line(ofd, prefix); fprintf(ofd, "    "); }
                a = c = 0;
                memset(ascii, 0, sizeof(ascii));
            }
        }
        if (c != 0) { for (i = 0; i < (limit - c); i++) fprintf(ofd, "   "); fprintf(ofd, "%s\n", ascii); }
    }
    struct ucred { pid_t pid; uid_t uid; gid_t gid; };
    struct nl_msg {
        int nm_protocol; int nm_flags; struct sockaddr_nl nm_src; struct sockaddr_nl nm_dst; struct ucred nm_creds;
        struct nlmsghdr *nm_nlh; size_t nm_size; int nm_refcnt;
    };
    static int callback_send(struct nl_sock *sk, struct nl_msg *msg) {
        printf("%d == msg.nm_protocol\n", msg->nm_protocol);
        printf("%d == msg.nm_flags\n", msg->nm_flags);
        printf("%d == msg.nm_src.nl_family\n", msg->nm_src.nl_family);
        printf("%d == msg.nm_src.nl_pid\n", msg->nm_src.nl_pid);
        printf("%d == msg.nm_src.nl_groups\n", msg->nm_src.nl_groups);
        printf("%d == msg.nm_dst.nl_family\n", msg->nm_dst.nl_family);
        printf("%d == msg.nm_dst.nl_pid\n", msg->nm_dst.nl_pid);
        printf("%d == msg.nm_dst.nl_groups\n", msg->nm_dst.nl_groups);
        printf("%d == msg.nm_creds.pid\n", msg->nm_creds.pid);
        printf("%d == msg.nm_creds.uid\n", msg->nm_creds.uid);
        printf("%d == msg.nm_creds.gid\n", msg->nm_creds.gid);
        printf("%d == msg.nm_nlh.nlmsg_type\n", msg->nm_nlh->nlmsg_type);
        printf("%d == msg.nm_nlh.nlmsg_flags\n", msg->nm_nlh->nlmsg_flags);
        printf("%d == msg.nm_nlh.nlmsg_pid\n", msg->nm_nlh->nlmsg_pid);
        printf("%d == msg.nm_size\n", msg->nm_size);
        printf("%d == msg.nm_refcnt\n", msg->nm_refcnt);
        struct iovec iov = { .iov_base = (void *) nlmsg_hdr(msg), .iov_len = nlmsg_hdr(msg)->nlmsg_len, };
        dump_hex(stdout, iov.iov_base, iov.iov_len, 0);
        return nl_send_iovec(sk, msg, &iov, 1);
    }
    static int callback_recv(struct nl_sock *sk, struct sockaddr_nl *nla, unsigned char **buf, struct ucred **creds) {
        int n = nl_recv(sk, nla, buf, creds);
        dump_hex(stdout, (void *) *buf, n, 0);
        return n;
    }
    static int callback_recv_msg(struct nl_msg *msg, void *arg) {
        printf("%d == msg.nm_protocol\n", msg->nm_protocol);
        printf("%d == msg.nm_flags\n", msg->nm_flags);
        printf("%d == msg.nm_src.nl_family\n", msg->nm_src.nl_family);
        printf("%d == msg.nm_src.nl_pid\n", msg->nm_src.nl_pid);
        printf("%d == msg.nm_src.nl_groups\n", msg->nm_src.nl_groups);
        printf("%d == msg.nm_dst.nl_family\n", msg->nm_dst.nl_family);
        printf("%d == msg.nm_dst.nl_pid\n", msg->nm_dst.nl_pid);
        printf("%d == msg.nm_dst.nl_groups\n", msg->nm_dst.nl_groups);
        printf("%d == msg.nm_creds.pid\n", msg->nm_creds.pid);
        printf("%d == msg.nm_creds.uid\n", msg->nm_creds.uid);
        printf("%d == msg.nm_creds.gid\n", msg->nm_creds.gid);
        printf("%d == msg.nm_nlh.nlmsg_type\n", msg->nm_nlh->nlmsg_type);
        printf("%d == msg.nm_nlh.nlmsg_flags\n", msg->nm_nlh->nlmsg_flags);
        printf("%d == msg.nm_nlh.nlmsg_pid\n", msg->nm_nlh->nlmsg_pid);
        printf("%d == msg.nm_size\n", msg->nm_size);
        printf("%d == msg.nm_refcnt\n", msg->nm_refcnt);
        dump_hex(stdout, (char *) msg->nm_nlh, nlmsg_datalen(msg->nm_nlh), 0);
        return NL_OK;
    }
    int main() {
        struct nl_sock *sk = nl_socket_alloc();
        nl_cb_overwrite_send(sk->s_cb, callback_send);
        nl_cb_overwrite_recv(sk->s_cb, callback_recv);
        printf("%d == genl_connect(sk)\n", genl_connect(sk));
        struct genl_family *ret = (struct genl_family *) genl_family_alloc();
        genl_family_set_name(ret, "nl80211");
        struct nl_msg *msg = nlmsg_alloc();
        genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1);
        nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, "nl80211");
        nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, callback_recv_msg, NULL);
        printf("%d == nl_send_auto(sk, msg)\n", nl_send_auto(sk, msg));
        printf("%d == nl_recvmsgs_default(sk)\n", nl_recvmsgs_default(sk));
        nl_socket_free(sk);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // 0 == genl_connect(sk)
    //  nl_object_alloc: Allocated new object 0x2b50b8
    // __nlmsg_alloc: msg 0x2b5110: Allocated new message, maxlen=4096
    // nlmsg_put: msg 0x2b5110: Added netlink header type=16, flags=0, pid=0, seq=0
    // nlmsg_reserve: msg 0x2b5110: Reserved 4 (4) bytes, pad=4, nlmsg_len=20
    // genlmsg_put: msg 0x2b5110: Added generic netlink header cmd=3 version=1
    // nla_reserve: msg 0x2b5110: attr <0x2b5164> 2: Reserved 12 (8) bytes at offset +4 nlmsg_len=32
    // nla_put: msg 0x2b5110: attr <0x2b5164> 2: Wrote 8 bytes at offset +4
    // 16 == msg.nm_protocol
    // 0 == msg.nm_flags
    // 0 == msg.nm_src.nl_family
    // 0 == msg.nm_src.nl_pid
    // 0 == msg.nm_src.nl_groups
    // 0 == msg.nm_dst.nl_family
    // 0 == msg.nm_dst.nl_pid
    // 0 == msg.nm_dst.nl_groups
    // 0 == msg.nm_creds.pid
    // 0 == msg.nm_creds.uid
    // 0 == msg.nm_creds.gid
    // 16 == msg.nm_nlh.nlmsg_type
    // 5 == msg.nm_nlh.nlmsg_flags
    // 14272 == msg.nm_nlh.nlmsg_pid
    // 4096 == msg.nm_size
    // 1 == msg.nm_refcnt
    //     20 00 00 00 10 00 05 00 af aa f6 54 c0 37 00 00  ..........T.7..
    //     03 01 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.
    // nl_sendmsg: sent 32 bytes
    // 32 == nl_send_auto(sk, msg)
    // recvmsgs: Attempting to read from 0x2b5080
    //     2c 07 00 00 10 00 00 00 af aa f6 54 c0 37 00 00 ,..........T.7..
    //     01 02 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.
    //     06 00 01 00 16 00 00 00 08 00 03 00 01 00 00 00 ................
    //     08 00 04 00 00 00 00 00 08 00 05 00 d5 00 00 00 ................
    //     6c 06 06 00 14 00 01 00 08 00 01 00 01 00 00 00 l...............
    //     08 00 02 00 0e 00 00 00 14 00 02 00 08 00 01 00 ................
    //     <trimmed>
    //     63 6f 6e 66 69 67 00 00 18 00 02 00 08 00 02 00 config..........
    //     04 00 00 00 09 00 01 00 73 63 61 6e 00 00 00 00 ........scan....
    //     1c 00 03 00 08 00 02 00 05 00 00 00 0f 00 01 00 ................
    //     72 65 67 75 6c 61 74 6f 72 79 00 00 18 00 04 00 regulatory......
    //     08 00 02 00 06 00 00 00 09 00 01 00 6d 6c 6d 65 ............mlme
    //     00 00 00 00 18 00 05 00 08 00 02 00 07 00 00 00 ................
    //     0b 00 01 00 76 65 6e 64 6f 72 00 00             ....vendor..
    // recvmsgs: recvmsgs(0x2b5080): Read 1836 bytes
    // recvmsgs: recvmsgs(0x2b5080): Processing valid message...
    // __nlmsg_alloc: msg 0x2ba160: Allocated new message, maxlen=1836
    // 16 == msg.nm_protocol
    // 0 == msg.nm_flags
    // 16 == msg.nm_src.nl_family
    // 0 == msg.nm_src.nl_pid
    // 0 == msg.nm_src.nl_groups
    // 0 == msg.nm_dst.nl_family
    // 0 == msg.nm_dst.nl_pid
    // 0 == msg.nm_dst.nl_groups
    // 0 == msg.nm_creds.pid
    // 0 == msg.nm_creds.uid
    // 0 == msg.nm_creds.gid
    // 16 == msg.nm_nlh.nlmsg_type
    // 0 == msg.nm_nlh.nlmsg_flags
    // 14272 == msg.nm_nlh.nlmsg_pid
    // 1836 == msg.nm_size
    // 1 == msg.nm_refcnt
    //     2c 07 00 00 10 00 00 00 af aa f6 54 c0 37 00 00 ,..........T.7..
    //     01 02 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.
    //     06 00 01 00 16 00 00 00 08 00 03 00 01 00 00 00 ................
    //     08 00 04 00 00 00 00 00 08 00 05 00 d5 00 00 00 ................
    //     6c 06 06 00 14 00 01 00 08 00 01 00 01 00 00 00 l...............
    //     08 00 02 00 0e 00 00 00 14 00 02 00 08 00 01 00 ................
    //     <trimmed>
    //     63 6f 6e 66 69 67 00 00 18 00 02 00 08 00 02 00 config..........
    //     04 00 00 00 09 00 01 00 73 63 61 6e 00 00 00 00 ........scan....
    //     1c 00 03 00 08 00 02 00 05 00 00 00 0f 00 01 00 ................
    //     72 65 67 75 6c 61 74 6f 72 79 00 00 18 00 04 00 regulatory......
    //     08 00 02 00 06 00 00 00 09 00 01 00 6d 6c 6d 65 ............mlme
    //     00 00 00 00 18 00 05 00 08 00 02 00             ............
    // nlmsg_free: Returned message reference 0x2ba160, 0 remaining
    // nlmsg_free: msg 0x2ba160: Freed
    // 0 == nl_recvmsgs_default(sk)
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    def callback_send(sk, msg):
        assert 16 == msg.nm_protocol
        assert 0 == msg.nm_flags
        assert 0 == msg.nm_src.nl_family
        assert 0 == msg.nm_src.nl_pid
        assert 0 == msg.nm_src.nl_groups
        assert 0 == msg.nm_dst.nl_family
        assert 0 == msg.nm_dst.nl_pid
        assert 0 == msg.nm_dst.nl_groups
        assert msg.nm_creds is None
        assert 16 == msg.nm_nlh.nlmsg_type
        assert 5 == msg.nm_nlh.nlmsg_flags
        assert 100 < msg.nm_nlh.nlmsg_pid
        assert 1 == msg.nm_refcnt
        hdr = nlmsg_hdr(msg)
        iov = hdr.bytearray[:hdr.nlmsg_len]
        dump_hex(logging.getLogger().debug, iov, len(iov), 0)
        return nl_send_iovec(sk, msg, iov, 1)

    def callback_recv(sk, nla, buf, creds):
        n = nl_recv(sk, nla, buf, creds)
        dump_hex(logging.getLogger().debug, buf, len(buf), 0)
        return n

    def callback_recv_msg(msg, _):
        assert 16 == msg.nm_protocol
        assert 0 == msg.nm_flags
        assert 16 == msg.nm_src.nl_family
        assert 0 == msg.nm_src.nl_pid
        assert 0 == msg.nm_src.nl_groups
        assert 0 == msg.nm_dst.nl_family
        assert 0 == msg.nm_dst.nl_pid
        assert 0 == msg.nm_dst.nl_groups
        assert msg.nm_creds is None
        assert 16 == msg.nm_nlh.nlmsg_type
        assert 0 == msg.nm_nlh.nlmsg_flags
        assert 100 < msg.nm_nlh.nlmsg_pid
        assert 1000 < msg.nm_size
        assert 1 == msg.nm_refcnt
        dump_hex(logging.getLogger().debug, msg.nm_nlh.bytearray,
                 nlmsg_datalen(msg.nm_nlh), 0)
        return NL_OK

    del log[:]
    sk_main = nl_socket_alloc()
    nl_cb_overwrite_send(sk_main.s_cb, callback_send)
    nl_cb_overwrite_recv(sk_main.s_cb, callback_recv)
    genl_connect(sk_main)
    ret = genl_family_alloc()
    genl_family_set_name(ret, b'nl80211')
    msg_main = nlmsg_alloc()
    genlmsg_put(msg_main, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0,
                CTRL_CMD_GETFAMILY, 1)
    nla_put_string(msg_main, CTRL_ATTR_FAMILY_NAME, b'nl80211')
    nl_socket_modify_cb(sk_main, NL_CB_VALID, NL_CB_CUSTOM, callback_recv_msg,
                        None)
    assert 32 == nl_send_auto(sk_main, msg_main)
    assert 0 == nl_recvmsgs_default(sk_main)
    nl_socket_free(sk_main)

    assert match('nl_object_alloc: Allocated new object 0x[a-f0-9]+', log,
                 True)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096',
        log, True)
    assert match(
        'nlmsg_put: msg 0x[a-f0-9]+: Added netlink header type=16, flags=0, pid=0, seq=0',
        log, True)
    assert match(
        'nlmsg_reserve: msg 0x[a-f0-9]+: Reserved 4 \(4\) bytes, pad=4, nlmsg_len=20',
        log, True)
    assert match(
        'genlmsg_put: msg 0x[a-f0-9]+: Added generic netlink header cmd=3 version=1',
        log, True)
    assert match(
        'nla_reserve: msg 0x[a-f0-9]+: attr <0x[a-f0-9]+> 2: Reserved 12 \(8\) bytes at offset \+4 nlmsg_len=32',
        log, True)
    assert match(
        'nla_put: msg 0x[a-f0-9]+: attr <0x[a-f0-9]+> 2: Wrote 8 bytes at offset \+4',
        log, True)

    assert match(
        'dump_hex:     20 00 00 00 10 00 05 00 .. .. .. .. .. .. 00 00  ...............',
        log, True)
    assert match(
        'dump_hex:     03 01 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.',
        log)

    assert match('nl_sendmsg: sent 32 bytes', log)
    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)

    assert match(
        'dump_hex:     .. .. 00 00 10 00 00 00 .. .. .. .. .. .. 00 00 ................',
        log, True)
    assert match(
        'dump_hex:     01 02 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.',
        log)
    assert match(
        'dump_hex:     06 00 01 00 .. 00 00 00 08 00 03 00 01 00 00 00 ................',
        log, True)
    assert match(
        'dump_hex:     08 00 04 00 00 00 00 00 08 00 05 00 .. 00 00 00 ................',
        log, True)

    for i in range(len(log)):
        if re.match(r'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{4,} bytes',
                    log[i]):
            log = log[i:]
            break

    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{3,} bytes', log,
                 True)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log,
        True)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=\d{3,}',
        log, True)

    assert match(
        'dump_hex:     .. .. 00 00 10 00 00 00 .. .. .. .. .. .. 00 00 ................',
        log, True)
    assert match(
        'dump_hex:     01 02 00 00 0c 00 02 00 6e 6c 38 30 32 31 31 00 ........nl80211.',
        log)
    assert match(
        'dump_hex:     06 00 01 00 .. 00 00 00 08 00 03 00 01 00 00 00 ................',
        log, True)
    assert match(
        'dump_hex:     08 00 04 00 00 00 00 00 08 00 05 00 .. 00 00 00 ................',
        log, True)

    while log and log[0].startswith('dump_hex:'):
        log.pop(0)
    assert not log
示例#45
0
def test_multipart(log, ifaces):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 NLCB=debug ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        // Send data to the kernel.
        printf("Begin main()\n");
        struct nl_sock *sk = nl_socket_alloc();
        printf("Allocated socket.\n");
        printf("%d == nl_connect(sk, NETLINK_ROUTE)\n", nl_connect(sk, NETLINK_ROUTE));
        struct rtgenmsg rt_hdr = { .rtgen_family = AF_PACKET, };
        int ret = nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
        printf("Bytes Sent: %d\n", ret);

        // Retrieve kernel's response.
        printf("%d == nl_recvmsgs_default(sk)\n", nl_recvmsgs_default(sk));

        nl_socket_free(sk);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // Begin main()
    // Allocated socket.
    // 0 == nl_connect(sk, NETLINK_ROUTE)
    // __nlmsg_alloc: msg 0x1bbe0b8: Allocated new message, maxlen=4096
    // nlmsg_alloc_simple: msg 0x1bbe0b8: Allocated new simple message
    // nlmsg_reserve: msg 0x1bbe0b8: Reserved 4 (1) bytes, pad=4, nlmsg_len=20
    // nlmsg_append: msg 0x1bbe0b8: Appended 1 bytes with padding 4
    // -- Debug: Sent Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 20
    //     .type = 18 <0x12>
    //     .flags = 773 <REQUEST,ACK,ROOT,MATCH>
    //     .seq = 1424053819
    //     .port = 18409
    //   [PAYLOAD] 4 octets
    //     11 00 00 00                                     ....
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // nl_sendmsg: sent 20 bytes
    // nlmsg_free: Returned message reference 0x1bbe0b8, 0 remaining
    // nlmsg_free: msg 0x1bbe0b8: Freed
    // Bytes Sent: 20
    // recvmsgs: Attempting to read from 0x1bbe080
    // recvmsgs: recvmsgs(0x1bbe080): Read 3364 bytes
    // recvmsgs: recvmsgs(0x1bbe080): Processing valid message...
    // __nlmsg_alloc: msg 0x1bc20c0: Allocated new message, maxlen=1116
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1116
    //     .type = 16 <0x10>
    //     .flags = 2 <MULTI>
    //     .seq = 1424053819
    //     .port = 18409
    //   [PAYLOAD] 1100 octets
    //     00 00 04 03 01 00 00 00 49 00 01 00 00 00 00 00 ........I.......
    //     <trimmed>
    //     00 00 00 00 00 00 00 00 00 00 00 00             ............
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // -- Debug: Unhandled Valid message: type=0x10 length=1116 flags=<MULTI> sequence-nr=1424053819 pid=18409
    // recvmsgs: recvmsgs(0x1bbe080): Processing valid message...
    // nlmsg_free: Returned message reference 0x1bc20c0, 0 remaining
    // nlmsg_free: msg 0x1bc20c0: Freed
    // __nlmsg_alloc: msg 0x1bc20c0: Allocated new message, maxlen=1124
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1124
    //     .type = 16 <0x10>
    //     .flags = 2 <MULTI>
    //     .seq = 1424053819
    //     .port = 18409
    //   [PAYLOAD] 1108 octets
    //     00 00 01 00 02 00 00 00 43 10 01 00 00 00 00 00 ........C.......
    //     <trimmed>
    //     00 00 00 00                                     ....
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // -- Debug: Unhandled Valid message: type=0x10 length=1124 flags=<MULTI> sequence-nr=1424053819 pid=18409
    // recvmsgs: recvmsgs(0x1bbe080): Processing valid message...
    // nlmsg_free: Returned message reference 0x1bc20c0, 0 remaining
    // nlmsg_free: msg 0x1bc20c0: Freed
    // __nlmsg_alloc: msg 0x1bc20c0: Allocated new message, maxlen=1124
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1124
    //     .type = 16 <0x10>
    //     .flags = 2 <MULTI>
    //     .seq = 1424053819
    //     .port = 18409
    //   [PAYLOAD] 1108 octets
    //     00 00 01 00 03 00 00 00 03 10 00 00 00 00 00 00 ................
    //     <trimmed>
    //     00 00 00 00                                     ....
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // -- Debug: Unhandled Valid message: type=0x10 length=1124 flags=<MULTI> sequence-nr=1424053819 pid=18409
    // nlmsg_free: Returned message reference 0x1bc20c0, 0 remaining
    // nlmsg_free: msg 0x1bc20c0: Freed
    // recvmsgs: Attempting to read from 0x1bbe080
    // recvmsgs: recvmsgs(0x1bbe080): Read 20 bytes
    // recvmsgs: recvmsgs(0x1bbe080): Processing valid message...
    // __nlmsg_alloc: msg 0x1bc20c0: Allocated new message, maxlen=20
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 20
    //     .type = 3 <DONE>
    //     .flags = 2 <MULTI>
    //     .seq = 1424053819
    //     .port = 18409
    //   [PAYLOAD] 4 octets
    //     00 00 00 00                                     ....
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // recvmsgs: recvmsgs(0x1bbe080): Increased expected sequence number to 1424053820
    // -- Debug: End of multipart message block: type=DONE length=20 flags=<MULTI> sequence-nr=1424053819 pid=18409
    // nlmsg_free: Returned message reference 0x1bc20c0, 0 remaining
    // nlmsg_free: msg 0x1bc20c0: Freed
    // 0 == nl_recvmsgs_default(sk)
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    del log[:]
    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    assert 20 == nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP,
                                rt_hdr, rt_hdr.SIZEOF)

    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096',
        log, True)
    assert match(
        'nlmsg_alloc_simple: msg 0x[a-f0-9]+: Allocated new simple message',
        log, True)
    assert match(
        'nlmsg_reserve: msg 0x[a-f0-9]+: Reserved 4 \(1\) bytes, pad=4, nlmsg_len=20',
        log, True)
    assert match(
        'nlmsg_append: msg 0x[a-f0-9]+: Appended 1 bytes with padding 4', log,
        True)
    assert match('nl_msg_out_handler_debug: -- Debug: Sent Message:', log)
    assert match(
        'nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------',
        log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 20', log)
    assert match('print_hdr:     .type = 18 <0x12>', log)
    assert match('print_hdr:     .flags = 773 <REQUEST,ACK,ROOT,MATCH>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('print_msg:   [PAYLOAD] 4 octets', log)
    assert match(
        'dump_hex:     11 00 00 00                                     ....',
        log)
    assert match(
        'nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------',
        log)
    assert match('nl_sendmsg: sent 20 bytes', log)
    assert not log

    assert 0 == nl_recvmsgs_default(sk)
    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{4,} bytes', log,
                 True)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log,
        True)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=\d{3,}',
        log, True)
    assert match('nl_msg_in_handler_debug: -- Debug: Received Message:', log)
    assert match(
        'nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------',
        log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = \d{3,}', log, True)
    assert match('print_hdr:     .type = 16 <0x10>', log)
    assert match('print_hdr:     .flags = 2 <MULTI>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('print_msg:   \[PAYLOAD\] \d{3,} octets', log, True)
    assert match(
        'dump_hex:     00 00 04 03 01 00 00 00 49 00 01 00 00 00 00 00 ........I.......',
        log)
    assert match(
        'dump_hex:     07 00 03 00 6c 6f 00 00 08 00 0d 00 00 00 00 00 ....lo..........',
        log)
    assert match(
        'dump_hex:     05 00 10 00 00 00 00 00 05 00 11 00 00 00 00 00 ................',
        log)

    for _ in ifaces:
        # Done testing this payload. Differs too much between Travis and Raspbian, and probably others.
        rem = log.index(
            'nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------'
        )
        assert 20 < rem  # At least check that there were a lot of log statements skipped.
        log = log[rem:]
        assert match(
            'nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------',
            log)
        assert match(
            'nl_valid_handler_debug: -- Debug: Unhandled Valid message: type=0x10 length=\d{3,} flags=<MULTI> '
            'sequence-nr=\d{10,} pid=\d{3,}', log, True)

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read 20 bytes', log, True)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log,
        True)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=20', log,
        True)
    assert match('nl_msg_in_handler_debug: -- Debug: Received Message:', log)
    assert match(
        'nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------',
        log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 20', log)
    assert match('print_hdr:     .type = 3 <DONE>', log)
    assert match('print_hdr:     .flags = 2 <MULTI>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('print_msg:   [PAYLOAD] 4 octets', log)
    assert match(
        'dump_hex:     00 00 00 00                                     ....',
        log)
    assert match(
        'nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------',
        log)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Increased expected sequence number to \d{4,}',
        log, True)
    assert match(
        'nl_finish_handler_debug: -- Debug: End of multipart message block: type=DONE length=20 flags=<MULTI> '
        'sequence-nr=\d{10,} pid=\d{3,}', log, True)

    nl_socket_free(sk)
    assert not log
示例#46
0
def test_error(log):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 NLCB=debug ./a.out
    #include <netlink/msg.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    int main() {
        // Send data to the kernel.
        printf("Begin main()\n");
        struct nl_sock *sk = nl_socket_alloc();
        printf("Allocated socket.\n");
        printf("%d == nl_connect(sk, NETLINK_ROUTE)\n", nl_connect(sk, NETLINK_ROUTE));
        int ret = nl_send_simple(sk, 0, NLM_F_REQUEST, NULL, 0);
        printf("Bytes Sent: %d\n", ret);

        // Retrieve kernel's response.
        printf("%d == nl_recvmsgs_default(sk)\n", nl_recvmsgs_default(sk));

        nl_socket_free(sk);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // Begin main()
    // Allocated socket.
    // 0 == nl_connect(sk, NETLINK_ROUTE)
    // __nlmsg_alloc: msg 0x3df0b8: Allocated new message, maxlen=4096
    // nlmsg_alloc_simple: msg 0x3df0b8: Allocated new simple message
    // -- Debug: Sent Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 16
    //     .type = 0 <0x0>
    //     .flags = 5 <REQUEST,ACK>
    //     .seq = 1423967746
    //     .port = 29930
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // nl_sendmsg: sent 16 bytes
    // nlmsg_free: Returned message reference 0x3df0b8, 0 remaining
    // nlmsg_free: msg 0x3df0b8: Freed
    // Bytes Sent: 16
    // recvmsgs: Attempting to read from 0x3df080
    // recvmsgs: recvmsgs(0x3df080): Read 36 bytes
    // recvmsgs: recvmsgs(0x3df080): Processing valid message...
    // __nlmsg_alloc: msg 0x3e30c0: Allocated new message, maxlen=36
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 36
    //     .type = 2 <ERROR>
    //     .flags = 0 <>
    //     .seq = 1423967746
    //     .port = 29930
    //   [ERRORMSG] 20 octets
    //     .error = 0 "Success"
    //   [ORIGINAL MESSAGE] 16 octets
    // __nlmsg_alloc: msg 0x3e3128: Allocated new message, maxlen=4096
    //     .nlmsg_len = 16
    //     .type = 0 <0x0>
    //     .flags = 5 <REQUEST,ACK>
    //     .seq = 1423967746
    //     .port = 29930
    // nlmsg_free: Returned message reference 0x3e3128, 0 remaining
    // nlmsg_free: msg 0x3e3128: Freed
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // recvmsgs: recvmsgs(0x3df080): Increased expected sequence number to 1423967746
    // -- Debug: ACK: type=ERROR length=36 flags=<> sequence-nr=1423967746 pid=29930
    // nlmsg_free: Returned message reference 0x3e30c0, 0 remaining
    // nlmsg_free: msg 0x3e30c0: Freed
    // 0 == nl_recvmsgs_default(sk)
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    del log[:]
    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    assert 16 == nl_send_simple(sk, 0, NLM_F_REQUEST, None)

    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096',
        log, True)
    assert match(
        'nlmsg_alloc_simple: msg 0x[a-f0-9]+: Allocated new simple message',
        log, True)
    assert match('nl_msg_out_handler_debug: -- Debug: Sent Message:', log)
    assert match(
        'nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------',
        log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 16', log)
    assert match('print_hdr:     .type = 0 <0x0>', log)
    assert match('print_hdr:     .flags = 5 <REQUEST,ACK>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match(
        'nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------',
        log)
    assert match('nl_sendmsg: sent 16 bytes', log)
    assert not log

    assert 0 == nl_recvmsgs_default(sk)
    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read 36 bytes', log, True)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log,
        True)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=36', log,
        True)
    assert match('nl_msg_in_handler_debug: -- Debug: Received Message:', log)
    assert match(
        'nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------',
        log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 36', log)
    assert match('print_hdr:     .type = 2 <ERROR>', log)
    assert match('print_hdr:     .flags = 0 <>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('dump_error_msg:   [ERRORMSG] 20 octets', log)
    assert match('dump_error_msg:     .error = 0 "Success"', log)
    assert match('dump_error_msg:   [ORIGINAL MESSAGE] 16 octets', log)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096',
        log, True)
    assert match('print_hdr:     .nlmsg_len = 16', log)
    assert match('print_hdr:     .type = 0 <0x0>', log)
    assert match('print_hdr:     .flags = 5 <REQUEST,ACK>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match(
        'nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------',
        log)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Increased expected sequence number to \d{4,}',
        log, True)
    assert match(
        'nl_ack_handler_debug: -- Debug: ACK: type=ERROR length=36 flags=<> sequence-nr=\d{10,} pid=\d{3,}',
        log, True)
    nl_socket_free(sk)
    assert not log
示例#47
0
文件: test_ctrl.py 项目: 0x90/libnl
def test_genl_ctrl_resolve(log):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && NLDBG=4 NLCB=debug ./a.out
    #include <netlink/msg.h>
    int main() {
        struct nl_sock *sk = nl_socket_alloc();
        printf("%d == genl_connect(sk)\n", genl_connect(sk));
        int driver_id = genl_ctrl_resolve(sk, "nl80211");
        printf("%d == driver_id\n", driver_id);
        nl_socket_free(sk);
        return 0;
    }
    // Expected output (trimmed):
    // nl_cache_mngt_register: Registered cache operations genl/family
    // 0 == genl_connect(sk)
    //  nl_object_alloc: Allocated new object 0x6f90b8
    // __nlmsg_alloc: msg 0x6f9110: Allocated new message, maxlen=4096
    // nlmsg_put: msg 0x6f9110: Added netlink header type=16, flags=0, pid=0, seq=0
    // nlmsg_reserve: msg 0x6f9110: Reserved 4 (4) bytes, pad=4, nlmsg_len=20
    // genlmsg_put: msg 0x6f9110: Added generic netlink header cmd=3 version=1
    // nla_reserve: msg 0x6f9110: attr <0x6f9164> 2: Reserved 12 (8) bytes at offset +4 nlmsg_len=32
    // nla_put: msg 0x6f9110: attr <0x6f9164> 2: Wrote 8 bytes at offset +4
    // -- Debug: Sent Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 32
    //     .type = 16 <genl/family::nlctrl>
    //     .flags = 5 <REQUEST,ACK>
    //     .seq = 1425769691
    //     .port = 2568
    //   [GENERIC NETLINK HEADER] 4 octets
    //     .cmd = 3
    //     .version = 1
    //     .unused = 0
    //   [ATTR 02] 8 octets
    //     6e 6c 38 30 32 31 31 00                         nl80211.
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // nl_sendmsg: sent 32 bytes
    // recvmsgs: Attempting to read from 0x6f9080
    // recvmsgs: recvmsgs(0x6f9080): Read 1836 bytes
    // recvmsgs: recvmsgs(0x6f9080): Processing valid message...
    // __nlmsg_alloc: msg 0x6fe1d8: Allocated new message, maxlen=1836
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 1836
    //     .type = 16 <genl/family::nlctrl>
    //     .flags = 0 <>
    //     .seq = 1425769691
    //     .port = 2568
    //   [GENERIC NETLINK HEADER] 4 octets
    //     .cmd = 1
    //     .version = 2
    //     .unused = 0
    //   [ATTR 02] 8 octets
    //     6e 6c 38 30 32 31 31 00                         nl80211.
    //   [ATTR 01] 2 octets
    //     16 00                                           ..
    //   [PADDING] 2 octets
    //     00 00                                           ..
    //   [ATTR 03] 4 octets
    //     01 00 00 00                                     ....
    //   [ATTR 04] 4 octets
    //     00 00 00 00                                     ....
    //   [ATTR 05] 4 octets
    //     d5 00 00 00                                     ....
    //   [ATTR 06] 1640 octets
    //     14 00 01 00 08 00 01 00 01 00 00 00 08 00 02 00 ................
    //     <trimmed>
    //     08 00 02 00 0b 00 00 00                         ........
    //   [ATTR 07] 124 octets
    //     18 00 01 00 08 00 02 00 03 00 00 00 0b 00 01 00 ................
    //     63 6f 6e 66 69 67 00 00 18 00 02 00 08 00 02 00 config..........
    //     04 00 00 00 09 00 01 00 73 63 61 6e 00 00 00 00 ........scan....
    //     1c 00 03 00 08 00 02 00 05 00 00 00 0f 00 01 00 ................
    //     72 65 67 75 6c 61 74 6f 72 79 00 00 18 00 04 00 regulatory......
    //     08 00 02 00 06 00 00 00 09 00 01 00 6d 6c 6d 65 ............mlme
    //     00 00 00 00 18 00 05 00 08 00 02 00 07 00 00 00 ................
    //     0b 00 01 00 76 65 6e 64 6f 72 00 00             ....vendor..
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // nlmsg_free: Returned message reference 0x6fe1d8, 0 remaining
    // nlmsg_free: msg 0x6fe1d8: Freed
    // recvmsgs: Attempting to read from 0x6f9080
    // recvmsgs: recvmsgs(0x6f9080): Read 36 bytes
    // recvmsgs: recvmsgs(0x6f9080): Processing valid message...
    // __nlmsg_alloc: msg 0x6fe1d8: Allocated new message, maxlen=36
    // -- Debug: Received Message:
    // --------------------------   BEGIN NETLINK MESSAGE ---------------------------
    //   [NETLINK HEADER] 16 octets
    //     .nlmsg_len = 36
    //     .type = 2 <ERROR>
    //     .flags = 0 <>
    //     .seq = 1425769691
    //     .port = 2568
    //   [ERRORMSG] 20 octets
    //     .error = 0 "Success"
    //   [ORIGINAL MESSAGE] 16 octets
    // __nlmsg_alloc: msg 0x6fe2b8: Allocated new message, maxlen=4096
    //     .nlmsg_len = 16
    //     .type = 16 <0x10>
    //     .flags = 5 <REQUEST,ACK>
    //     .seq = 1425769691
    //     .port = 2568
    // nlmsg_free: Returned message reference 0x6fe2b8, 0 remaining
    // nlmsg_free: msg 0x6fe2b8: Freed
    // ---------------------------  END NETLINK MESSAGE   ---------------------------
    // recvmsgs: recvmsgs(0x6f9080): Increased expected sequence number to 1425769692
    // nlmsg_free: Returned message reference 0x6fe1d8, 0 remaining
    // nlmsg_free: msg 0x6fe1d8: Freed
    // nlmsg_free: Returned message reference 0x6f9110, 0 remaining
    // nlmsg_free: msg 0x6f9110: Freed
    // nl_object_put: Returned object reference 0x6f90b8, 0 remaining
    // nl_object_free: Freed object 0x6f90b8
    // 22 == driver_id
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    del log[:]

    sk = nl_socket_alloc()
    assert 0 == genl_connect(sk)
    assert not log
    assert 20 <= genl_ctrl_resolve(sk, b'nl80211')
    nl_socket_free(sk)

    assert match('nl_object_alloc: Allocated new object 0x[a-f0-9]+', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096', log, True)
    assert match('nlmsg_put: msg 0x[a-f0-9]+: Added netlink header type=16, flags=0, pid=0, seq=0', log, True)
    assert match('nlmsg_reserve: msg 0x[a-f0-9]+: Reserved 4 \(4\) bytes, pad=4, nlmsg_len=20', log, True)
    assert match('genlmsg_put: msg 0x[a-f0-9]+: Added generic netlink header cmd=3 version=1', log, True)
    assert match(
        'nla_reserve: msg 0x[a-f0-9]+: attr <0x[a-f0-9]+> 2: Reserved 12 \(8\) bytes at offset \+4 nlmsg_len=32',
        log, True)
    assert match('nla_put: msg 0x[a-f0-9]+: attr <0x[a-f0-9]+> 2: Wrote 8 bytes at offset \+4', log, True)
    assert match('nl_msg_out_handler_debug: -- Debug: Sent Message:', log)
    assert match('nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------', log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 32', log)
    assert match('print_hdr:     .type = 16 <genl/family::nlctrl>', log)
    assert match('print_hdr:     .flags = 5 <REQUEST,ACK>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('print_genl_hdr:   [GENERIC NETLINK HEADER] 4 octets', log)
    assert match('print_genl_hdr:     .cmd = 3', log)
    assert match('print_genl_hdr:     .version = 1', log)
    assert match('print_genl_hdr:     .unused = 0', log)
    assert match('dump_attrs:   [ATTR 02] 8 octets', log)
    assert match('dump_hex:     6e 6c 38 30 32 31 31 00                         nl80211.', log)
    assert match('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------', log)
    assert match('nl_sendmsg: sent 32 bytes', log)

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{3,} bytes', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=\d{3,}', log, True)
    assert match('nl_msg_in_handler_debug: -- Debug: Received Message:', log)
    assert match('nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------', log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = \d{3,}', log, True)
    assert match('print_hdr:     .type = 16 <genl/family::nlctrl>', log)
    assert match('print_hdr:     .flags = 0 <>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('print_genl_hdr:   [GENERIC NETLINK HEADER] 4 octets', log)
    assert match('print_genl_hdr:     .cmd = 1', log)
    assert match('print_genl_hdr:     .version = 2', log)
    assert match('print_genl_hdr:     .unused = 0', log)
    assert match('dump_attrs:   [ATTR 02] 8 octets', log)
    assert match('dump_hex:     6e 6c 38 30 32 31 31 00                         nl80211.', log)
    assert match('dump_attrs:   [ATTR 01] 2 octets', log)
    assert match('dump_hex:     .. 00                                           ..', log, True)
    assert match('dump_attrs:   [PADDING] 2 octets', log)
    assert match('dump_hex:     00 00                                           ..', log)
    assert match('dump_attrs:   [ATTR 03] 4 octets', log)
    assert match('dump_hex:     01 00 00 00                                     ....', log)
    assert match('dump_attrs:   [ATTR 04] 4 octets', log)
    assert match('dump_hex:     00 00 00 00                                     ....', log)
    assert match('dump_attrs:   [ATTR 05] 4 octets', log)
    assert match('dump_hex:     .. 00 00 00                                     ....', log, True)
    assert match('dump_attrs:   \[ATTR 06\] \d{4,} octets', log, True)
    assert match('dump_hex:     14 00 01 00 08 00 01 00 01 00 00 00 08 00 02 00 ................', log)

    # Done testing this payload. Too big.
    for line in log:
        if line.startswith('dump_hex'):
            continue
        rem = log.index(line)
        assert 20 < rem  # At least check that there were a lot of log statements skipped.
        log = log[rem:]
        break

    assert match('dump_attrs:   \[ATTR 07\] \d{3,} octets', log, True)
    assert match('dump_hex:     18 00 01 00 08 00 02 00 .. 00 00 00 0b 00 01 00 ................', log, True)
    assert match('dump_hex:     63 6f 6e 66 69 67 00 00 18 00 02 00 08 00 02 00 config..........', log)
    assert match('dump_hex:     .. 00 00 00 09 00 01 00 73 63 61 6e 00 00 00 00 ........scan....', log, True)
    assert match('dump_hex:     1c 00 03 00 08 00 02 00 .. 00 00 00 0f 00 01 00 ................', log, True)
    assert match('dump_hex:     72 65 67 75 6c 61 74 6f 72 79 00 00 18 00 04 00 regulatory......', log)
    assert match('dump_hex:     08 00 02 00 .. 00 00 00 09 00 01 00 6d 6c 6d 65 ............mlme', log, True)
    rem = log.index('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------')
    log = log[rem:]
    assert match('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------', log)

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read 36 bytes', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log, True)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=36', log, True)
    assert match('nl_msg_in_handler_debug: -- Debug: Received Message:', log)
    assert match('nl_msg_dump: --------------------------   BEGIN NETLINK MESSAGE ---------------------------', log)
    assert match('nl_msg_dump:   [NETLINK HEADER] 16 octets', log)
    assert match('print_hdr:     .nlmsg_len = 36', log)
    assert match('print_hdr:     .type = 2 <ERROR>', log)
    assert match('print_hdr:     .flags = 0 <>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('dump_error_msg:   [ERRORMSG] 20 octets', log)
    assert match('dump_error_msg:     .error = 0 "Success"', log)
    assert match('dump_error_msg:   [ORIGINAL MESSAGE] 16 octets', log)
    assert match('nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096', log, True)
    assert match('print_hdr:     .nlmsg_len = 16', log)
    assert match('print_hdr:     .type = 16 <0x[a-f0-9]+>', log, True)
    assert match('print_hdr:     .flags = 5 <REQUEST,ACK>', log)
    assert match('print_hdr:     .seq = \d{10}', log, True)
    assert match('print_hdr:     .port = \d{3,}', log, True)
    assert match('nl_msg_dump: ---------------------------  END NETLINK MESSAGE   ---------------------------', log)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Increased expected sequence number to \d{10}', log, True)

    assert not log
示例#48
0
def test_multipart_verbose(log, ifaces):
    """Expected output (trimmed).

    // nl_cache_mngt_register: Registered cache operations genl/family
    // Begin main()
    // Allocated socket.
    // 0 == nl_connect(sk, NETLINK_ROUTE)
    // __nlmsg_alloc: msg 0xa180b8: Allocated new message, maxlen=4096
    // nlmsg_alloc_simple: msg 0xa180b8: Allocated new simple message
    // nlmsg_reserve: msg 0xa180b8: Reserved 4 (1) bytes, pad=4, nlmsg_len=20
    // nlmsg_append: msg 0xa180b8: Appended 1 bytes with padding 4
    // nl_sendmsg: sent 20 bytes
    // nlmsg_free: Returned message reference 0xa180b8, 0 remaining
    // nlmsg_free: msg 0xa180b8: Freed
    // Bytes Sent: 20
    // recvmsgs: Attempting to read from 0xa18080
    // recvmsgs: recvmsgs(0xa18080): Read 3364 bytes
    // recvmsgs: recvmsgs(0xa18080): Processing valid message...
    // __nlmsg_alloc: msg 0xa1c0c0: Allocated new message, maxlen=1116
    // -- Warning: unhandled valid message: type=0x10 length=1116 flags=<MULTI> sequence-nr=1424132449 pid=5810
    // recvmsgs: recvmsgs(0xa18080): Processing valid message...
    // nlmsg_free: Returned message reference 0xa1c0c0, 0 remaining
    // nlmsg_free: msg 0xa1c0c0: Freed
    // __nlmsg_alloc: msg 0xa1c0c0: Allocated new message, maxlen=1124
    // -- Warning: unhandled valid message: type=0x10 length=1124 flags=<MULTI> sequence-nr=1424132449 pid=5810
    // recvmsgs: recvmsgs(0xa18080): Processing valid message...
    // nlmsg_free: Returned message reference 0xa1c0c0, 0 remaining
    // nlmsg_free: msg 0xa1c0c0: Freed
    // __nlmsg_alloc: msg 0xa1c0c0: Allocated new message, maxlen=1124
    // -- Warning: unhandled valid message: type=0x10 length=1124 flags=<MULTI> sequence-nr=1424132449 pid=5810
    // nlmsg_free: Returned message reference 0xa1c0c0, 0 remaining
    // nlmsg_free: msg 0xa1c0c0: Freed
    // recvmsgs: Attempting to read from 0xa18080
    // recvmsgs: recvmsgs(0xa18080): Read 20 bytes
    // recvmsgs: recvmsgs(0xa18080): Processing valid message...
    // __nlmsg_alloc: msg 0xa1c0c0: Allocated new message, maxlen=20
    // recvmsgs: recvmsgs(0xa18080): Increased expected sequence number to 1424132450
    // nlmsg_free: Returned message reference 0xa1c0c0, 0 remaining
    // nlmsg_free: msg 0xa1c0c0: Freed
    // 0 == nl_recvmsgs_default(sk)
    // nl_cache_mngt_unregister: Unregistered cache operations genl/family
    """
    del log[:]
    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    assert 20 == nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP,
                                rt_hdr, rt_hdr.SIZEOF)

    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=4096',
        log, True)
    assert match(
        'nlmsg_alloc_simple: msg 0x[a-f0-9]+: Allocated new simple message',
        log, True)
    assert match(
        'nlmsg_reserve: msg 0x[a-f0-9]+: Reserved 4 \(1\) bytes, pad=4, nlmsg_len=20',
        log, True)
    assert match(
        'nlmsg_append: msg 0x[a-f0-9]+: Appended 1 bytes with padding 4', log,
        True)
    assert match('nl_sendmsg: sent 20 bytes', log)
    assert not log

    assert 0 == nl_recvmsgs_default(sk)
    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{4,} bytes', log,
                 True)

    for _ in ifaces:
        if 'Attempting to read' in log[0]:
            # Lots of network interfaces on this host.
            assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log,
                         True)
            assert match(
                'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read \d{4,} bytes', log,
                True)
        assert match(
            'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...',
            log, True)
        assert match(
            'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=\d{3,}',
            log, True)
        assert match(
            'nl_valid_handler_verbose: -- Warning: unhandled valid message: type=0x10 length=\d{3,} '
            'flags=<MULTI> sequence-nr=\d{10,} pid=\d{3,}', log, True)

    assert match('recvmsgs: Attempting to read from 0x[a-f0-9]+', log, True)
    assert match('recvmsgs: recvmsgs\(0x[a-f0-9]+\): Read 20 bytes', log, True)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Processing valid message...', log,
        True)
    assert match(
        'nlmsg_alloc: msg 0x[a-f0-9]+: Allocated new message, maxlen=20', log,
        True)
    assert match(
        'recvmsgs: recvmsgs\(0x[a-f0-9]+\): Increased expected sequence number to \d{4,}',
        log, True)

    nl_socket_free(sk)
    assert not log
示例#49
0
文件: test_ctrl.py 项目: 0x90/libnl
def test_genl_ctrl_probe_by_name():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    #define NL_NO_AUTO_ACK (1<<4)
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    struct genl_family {
        int ce_refcnt; struct nl_object_ops *ce_ops; struct nl_cache *ce_cache; struct nl_list_head ce_list;
        int ce_msgtype; int ce_flags; uint32_t ce_mask; uint16_t gf_id; char gf_name[GENL_NAMSIZ]; uint32_t gf_version;
        uint32_t gf_hdrsize; uint32_t gf_maxattr; struct nl_list_head gf_ops; struct nl_list_head gf_mc_grps;
    };
    static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
        [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
        [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING, .maxlen = GENL_NAMSIZ },
        [CTRL_ATTR_VERSION] = { .type = NLA_U32 }, [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 },
        [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 }, [CTRL_ATTR_OPS] = { .type = NLA_NESTED },
        [CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED },
    };
    static struct nla_policy family_grp_policy[CTRL_ATTR_MCAST_GRP_MAX+1] = {
        [CTRL_ATTR_MCAST_GRP_NAME] = { .type = NLA_STRING }, [CTRL_ATTR_MCAST_GRP_ID] = { .type = NLA_U32 },
    };
    static inline int wait_for_ack(struct nl_sock *sk) {
        if (sk->s_flags & NL_NO_AUTO_ACK) return 0;
        else return nl_wait_for_ack(sk);
    }
    static int parse_mcast_grps(struct genl_family *family, struct nlattr *grp_attr) {
        struct nlattr *nla; int remaining, err;
        nla_for_each_nested(nla, grp_attr, remaining) {
            struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1];
            int id;
            const char *name;
            err = nla_parse_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, nla, family_grp_policy);
            if (err < 0) goto errout;
            if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) { err = -NLE_MISSING_ATTR; goto errout; }
            id = nla_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]);
            if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) { err = -NLE_MISSING_ATTR; goto errout; }
            name = nla_get_string(tb[CTRL_ATTR_MCAST_GRP_NAME]);
            err = genl_family_add_grp(family, id, name);
            if (err < 0) goto errout;
        }
        err = 0;
        errout:
            return err;
    }
    static int probe_response(struct nl_msg *msg, void *arg) {
        struct nlattr *tb[CTRL_ATTR_MAX+1];
        struct nlmsghdr *nlh = nlmsg_hdr(msg);
        struct genl_family *ret = (struct genl_family *)arg;
        if (genlmsg_parse(nlh, 0, tb, CTRL_ATTR_MAX, ctrl_policy)) return NL_SKIP;
        if (tb[CTRL_ATTR_FAMILY_ID]) genl_family_set_id(ret, nla_get_u16(tb[CTRL_ATTR_FAMILY_ID]));
        if (tb[CTRL_ATTR_MCAST_GROUPS])
            if (parse_mcast_grps(ret, tb[CTRL_ATTR_MCAST_GROUPS]) < 0)
                return NL_SKIP;
        return NL_STOP;
    }
    static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk, const char *name) {
        struct nl_msg *msg;
        struct genl_family *ret;
        struct nl_cb *cb, *orig;
        int rc;
        ret = (struct genl_family *) genl_family_alloc();
        if (!ret) goto out;
        genl_family_set_name(ret, name);
        msg = nlmsg_alloc();
        if (!msg) goto out_fam_free;
        if (!(orig = nl_socket_get_cb(sk))) goto out_msg_free;
        cb = nl_cb_clone(orig);
        nl_cb_put(orig);
        if (!cb) goto out_msg_free;
        if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1)) goto out_cb_free;
        if (nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name) < 0) goto out_cb_free;
        rc = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, (void *) ret);
        if (rc < 0) goto out_cb_free;
        rc = nl_send_auto_complete(sk, msg);
        if (rc < 0) goto out_cb_free;
        rc = nl_recvmsgs(sk, cb);
        if (rc < 0) goto out_cb_free;
        rc = wait_for_ack(sk);
        if (rc < 0) goto out_cb_free;
        if (genl_family_get_id(ret) != 0) {
            nlmsg_free(msg);
            nl_cb_put(cb);
            return ret;
        }
        out_cb_free:
            nl_cb_put(cb);
        out_msg_free:
            nlmsg_free(msg);
        out_fam_free:
            genl_family_put(ret);
        ret = NULL;
        out:
            return ret;
    }
    int main() {
        struct nl_sock *sk = nl_socket_alloc();
        printf("%d == genl_connect(sk)\n", genl_connect(sk));
        struct genl_family *ret = genl_ctrl_probe_by_name(sk, "nl80211");
        printf("%d == ret.ce_msgtype\n", ret->ce_msgtype);
        printf("%d == ret.ce_flags\n", ret->ce_flags);
        printf("%d == ret.ce_mask\n", ret->ce_mask);
        printf("%d == ret.gf_id\n", ret->gf_id);
        printf("%s == ret.gf_name\n", ret->gf_name);
        printf("%d == ret.gf_version\n", ret->gf_version);
        printf("%d == ret.gf_hdrsize\n", ret->gf_hdrsize);
        printf("%d == ret.gf_maxattr\n", ret->gf_maxattr);
        nl_socket_free(sk);
        return 0;
    }
    // Expected output:
    // 0 == genl_connect(sk)
    // 0 == ret.ce_msgtype
    // 0 == ret.ce_flags
    // 3 == ret.ce_mask
    // 22 == ret.gf_id
    // nl80211 == ret.gf_name
    // 0 == ret.gf_version
    // 0 == ret.gf_hdrsize
    // 0 == ret.gf_maxattr
    """
    sk = nl_socket_alloc()
    assert 0 == genl_connect(sk)
    ret = genl_ctrl_probe_by_name(sk, b'nl80211')
    assert 0 == ret.ce_msgtype
    assert 0 == ret.ce_flags
    assert 3 == ret.ce_mask
    assert 20 <= ret.gf_id
    assert b'nl80211' == ret.gf_name
    assert 0 == ret.gf_version
    assert 0 == ret.gf_hdrsize
    assert 0 == ret.gf_maxattr
    nl_socket_free(sk)
示例#50
0
def test_nl_cache_ops_associate_safe():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/genl/family.h>
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    struct nl_cache_ops {
        char *co_name; int co_hdrsize; int co_protocol; int co_hash_size; unsigned int co_flags; unsigned int co_refcnt;
        struct nl_af_group *co_groups; int (*co_request_update)(struct nl_cache*, struct nl_sock*);
        int (*co_msg_parser)(struct nl_cache_ops*, struct sockaddr_nl*, struct nlmsghdr*, struct nl_parser_param*);
        int (*co_event_filter)(struct nl_cache*, struct nl_object *obj);
        int (*co_include_event)(struct nl_cache *cache, struct nl_object *obj, change_func_t change_cb, void *data);
        void (*reserved_1)(void); void (*reserved_2)(void); void (*reserved_3)(void); void (*reserved_4)(void);
        void (*reserved_5)(void); void (*reserved_6)(void); void (*reserved_7)(void); void (*reserved_8)(void);
        struct nl_object_ops *co_obj_ops;
    };
    struct nl_object_ops { char *oo_name; size_t oo_size; uint32_t oo_id_attrs; };
    struct nl_msgtype { int mt_id; int mt_act; char *mt_name; };
    static int callback(struct nl_sock *sk, struct nl_msg *msg) {
        struct nlmsghdr *nlh = nlmsg_hdr(msg);
        printf("%d == nlh.nlmsg_len\n", nlh->nlmsg_len);
        printf("%d == nlh.nlmsg_type\n", nlh->nlmsg_type);
        printf("%d == nlh.nlmsg_flags\n", nlh->nlmsg_flags);
        struct nl_cache_ops *ops = nl_cache_ops_associate_safe(NETLINK_GENERIC, nlh->nlmsg_type);
        printf("'%s' == ops.co_name\n", ops->co_name);
        printf("%d == ops.co_hdrsize\n", ops->co_hdrsize);
        printf("%d == ops.co_protocol\n", ops->co_protocol);
        printf("%d == ops.co_hash_size\n", ops->co_hash_size);
        printf("%d == ops.co_flags\n", ops->co_flags);
        printf("'%s' == ops.co_obj_ops.oo_name\n", ops->co_obj_ops->oo_name);
        printf("%d == ops.co_obj_ops.oo_size\n", ops->co_obj_ops->oo_size);
        printf("%d == ops.co_obj_ops.oo_id_attrs\n", ops->co_obj_ops->oo_id_attrs);
        printf("%d == nlmsg_attrlen(nlh, ops.co_hdrsize)\n", nlmsg_attrlen(nlh, ops->co_hdrsize));
        struct nl_msgtype *mt = nl_msgtype_lookup(ops, nlh->nlmsg_type);
        printf("%d == mt.mt_id\n", mt->mt_id);
        printf("%d == mt.mt_act\n", mt->mt_act);
        printf("'%s' == mt.mt_name\n", mt->mt_name);
        return NL_STOP;
    }
    int main() {
        struct nl_sock *sk = nl_socket_alloc();
        nl_cb_overwrite_send(sk->s_cb, callback);

        struct genl_family *ret = genl_family_alloc();
        genl_family_set_name(ret, "nl80211");
        struct nl_msg *msg = nlmsg_alloc();
        genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1);
        printf("%d == nl_send_auto(sk, msg)\n", nl_send_auto(sk, msg));
        return 0;
    }
    // Expected output:
    // 20 == nlh.nlmsg_len
    // 16 == nlh.nlmsg_type
    // 5 == nlh.nlmsg_flags
    // 'genl/family' == ops.co_name
    // 4 == ops.co_hdrsize
    // 16 == ops.co_protocol
    // 0 == ops.co_hash_size
    // 0 == ops.co_flags
    // 'genl/family' == ops.co_obj_ops.oo_name
    // 80 == ops.co_obj_ops.oo_size
    // 1 == ops.co_obj_ops.oo_id_attrs
    // 0 == nlmsg_attrlen(nlh, ops.co_hdrsize)
    // 16 == mt.mt_id
    // 0 == mt.mt_act
    // 'nlctrl' == mt.mt_name
    // 2 == nl_send_auto(sk, msg)
    """
    called = list()

    def callback(_, msg_):
        nlh = nlmsg_hdr(msg_)
        assert 20 == nlh.nlmsg_len
        assert 16 == nlh.nlmsg_type
        assert 5 == nlh.nlmsg_flags
        ops = nl_cache_ops_associate_safe(NETLINK_GENERIC, nlh.nlmsg_type)
        assert 'genl/family' == ops.co_name
        assert 4 == ops.co_hdrsize
        assert 16 == ops.co_protocol
        assert 0 == ops.co_hash_size
        assert 0 == ops.co_flags
        assert 'genl/family' == ops.co_obj_ops.oo_name
        assert 80 == ops.co_obj_ops.oo_size
        assert 1 == ops.co_obj_ops.oo_id_attrs
        assert 0 == nlmsg_attrlen(nlh, ops.co_hdrsize)
        mt = nl_msgtype_lookup(ops, nlh.nlmsg_type)
        assert 16 == mt.mt_id
        assert 0 == mt.mt_act
        assert 'nlctrl' == mt.mt_name
        called.append(True)
        return NL_STOP

    sk = nl_socket_alloc()
    nl_cb_overwrite_send(sk.s_cb, callback)
    ret = genl_family_alloc()
    genl_family_set_name(ret, 'nl80211')
    msg = nlmsg_alloc()
    genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0,
                CTRL_CMD_GETFAMILY, 1)
    assert 2 == nl_send_auto(sk, msg)
    assert [True] == called
示例#51
0
def test_list_interfaces(ifacesi):
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    static int callback(struct nl_msg *msg, void *arg) {
        struct nlmsghdr *nlh = nlmsg_hdr(msg);
        struct ifinfomsg *iface = NLMSG_DATA(nlh);
        struct rtattr *hdr = IFLA_RTA(iface);
        int remaining = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*iface));

        while (RTA_OK(hdr, remaining)) {
            if (hdr->rta_type == IFLA_IFNAME) {
                printf("Found network interface %d: %s\n", iface->ifi_index, (char *) RTA_DATA(hdr));
            }
            hdr = RTA_NEXT(hdr, remaining);
        }
        return NL_OK;
    }
    int main() {
        // Send data to the kernel.
        struct nl_sock *sk = nl_socket_alloc();
        printf("%d == nl_connect(sk, NETLINK_ROUTE)\n", nl_connect(sk, NETLINK_ROUTE));
        struct rtgenmsg rt_hdr = { .rtgen_family = AF_PACKET, };
        int ret = nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr));
        printf("Bytes Sent: %d\n", ret);

        // Retrieve kernel's response.
        nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, callback, NULL);
        printf("%d == nl_recvmsgs_default(sk)\n", nl_recvmsgs_default(sk));

        nl_socket_free(sk);
        return 0;
    }
    // Expected output:
    // 0 == nl_connect(sk, NETLINK_ROUTE)
    // Bytes Sent: 20
    // Found network interface 1: lo
    // Found network interface 2: eth0
    // Found network interface 4: wlan0
    // 0 == nl_recvmsgs_default(sk)
    """
    got_something = dict()

    def callback(msg, arg):
        nlh = nlmsg_hdr(msg)
        iface = ifinfomsg(nlmsg_data(nlh))
        hdr = IFLA_RTA(iface)
        remaining = c_int(nlh.nlmsg_len - NLMSG_LENGTH(iface.SIZEOF))

        while RTA_OK(hdr, remaining):
            if hdr.rta_type == IFLA_IFNAME:
                arg[int(iface.ifi_index)] = str(get_string(RTA_DATA(hdr)).decode('ascii'))
            hdr = RTA_NEXT(hdr, remaining)
        return NL_OK

    sk = nl_socket_alloc()
    nl_connect(sk, NETLINK_ROUTE)
    rt_hdr = rtgenmsg(rtgen_family=socket.AF_PACKET)
    assert 20 == nl_send_simple(sk, RTM_GETLINK, NLM_F_REQUEST | NLM_F_DUMP, rt_hdr, rt_hdr.SIZEOF)

    assert 0 == nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, callback, got_something)
    assert 0 == nl_recvmsgs_default(sk)
    assert dict(ifacesi) == got_something

    nl_socket_free(sk)
示例#52
0
def test_genl_ctrl_probe_by_name():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    #define NL_NO_AUTO_ACK (1<<4)
    struct nl_sock {
        struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next;
        unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize;
    };
    struct genl_family {
        int ce_refcnt; struct nl_object_ops *ce_ops; struct nl_cache *ce_cache; struct nl_list_head ce_list;
        int ce_msgtype; int ce_flags; uint32_t ce_mask; uint16_t gf_id; char gf_name[GENL_NAMSIZ]; uint32_t gf_version;
        uint32_t gf_hdrsize; uint32_t gf_maxattr; struct nl_list_head gf_ops; struct nl_list_head gf_mc_grps;
    };
    static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
        [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
        [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING, .maxlen = GENL_NAMSIZ },
        [CTRL_ATTR_VERSION] = { .type = NLA_U32 }, [CTRL_ATTR_HDRSIZE] = { .type = NLA_U32 },
        [CTRL_ATTR_MAXATTR] = { .type = NLA_U32 }, [CTRL_ATTR_OPS] = { .type = NLA_NESTED },
        [CTRL_ATTR_MCAST_GROUPS] = { .type = NLA_NESTED },
    };
    static struct nla_policy family_grp_policy[CTRL_ATTR_MCAST_GRP_MAX+1] = {
        [CTRL_ATTR_MCAST_GRP_NAME] = { .type = NLA_STRING }, [CTRL_ATTR_MCAST_GRP_ID] = { .type = NLA_U32 },
    };
    static inline int wait_for_ack(struct nl_sock *sk) {
        if (sk->s_flags & NL_NO_AUTO_ACK) return 0;
        else return nl_wait_for_ack(sk);
    }
    static int parse_mcast_grps(struct genl_family *family, struct nlattr *grp_attr) {
        struct nlattr *nla; int remaining, err;
        nla_for_each_nested(nla, grp_attr, remaining) {
            struct nlattr *tb[CTRL_ATTR_MCAST_GRP_MAX+1];
            int id;
            const char *name;
            err = nla_parse_nested(tb, CTRL_ATTR_MCAST_GRP_MAX, nla, family_grp_policy);
            if (err < 0) goto errout;
            if (tb[CTRL_ATTR_MCAST_GRP_ID] == NULL) { err = -NLE_MISSING_ATTR; goto errout; }
            id = nla_get_u32(tb[CTRL_ATTR_MCAST_GRP_ID]);
            if (tb[CTRL_ATTR_MCAST_GRP_NAME] == NULL) { err = -NLE_MISSING_ATTR; goto errout; }
            name = nla_get_string(tb[CTRL_ATTR_MCAST_GRP_NAME]);
            err = genl_family_add_grp(family, id, name);
            if (err < 0) goto errout;
        }
        err = 0;
        errout:
            return err;
    }
    static int probe_response(struct nl_msg *msg, void *arg) {
        struct nlattr *tb[CTRL_ATTR_MAX+1];
        struct nlmsghdr *nlh = nlmsg_hdr(msg);
        struct genl_family *ret = (struct genl_family *)arg;
        if (genlmsg_parse(nlh, 0, tb, CTRL_ATTR_MAX, ctrl_policy)) return NL_SKIP;
        if (tb[CTRL_ATTR_FAMILY_ID]) genl_family_set_id(ret, nla_get_u16(tb[CTRL_ATTR_FAMILY_ID]));
        if (tb[CTRL_ATTR_MCAST_GROUPS])
            if (parse_mcast_grps(ret, tb[CTRL_ATTR_MCAST_GROUPS]) < 0)
                return NL_SKIP;
        return NL_STOP;
    }
    static struct genl_family *genl_ctrl_probe_by_name(struct nl_sock *sk, const char *name) {
        struct nl_msg *msg;
        struct genl_family *ret;
        struct nl_cb *cb, *orig;
        int rc;
        ret = (struct genl_family *) genl_family_alloc();
        if (!ret) goto out;
        genl_family_set_name(ret, name);
        msg = nlmsg_alloc();
        if (!msg) goto out_fam_free;
        if (!(orig = nl_socket_get_cb(sk))) goto out_msg_free;
        cb = nl_cb_clone(orig);
        nl_cb_put(orig);
        if (!cb) goto out_msg_free;
        if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1)) goto out_cb_free;
        if (nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name) < 0) goto out_cb_free;
        rc = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, (void *) ret);
        if (rc < 0) goto out_cb_free;
        rc = nl_send_auto_complete(sk, msg);
        if (rc < 0) goto out_cb_free;
        rc = nl_recvmsgs(sk, cb);
        if (rc < 0) goto out_cb_free;
        rc = wait_for_ack(sk);
        if (rc < 0) goto out_cb_free;
        if (genl_family_get_id(ret) != 0) {
            nlmsg_free(msg);
            nl_cb_put(cb);
            return ret;
        }
        out_cb_free:
            nl_cb_put(cb);
        out_msg_free:
            nlmsg_free(msg);
        out_fam_free:
            genl_family_put(ret);
        ret = NULL;
        out:
            return ret;
    }
    int main() {
        struct nl_sock *sk = nl_socket_alloc();
        printf("%d == genl_connect(sk)\n", genl_connect(sk));
        struct genl_family *ret = genl_ctrl_probe_by_name(sk, "nl80211");
        printf("%d == ret.ce_msgtype\n", ret->ce_msgtype);
        printf("%d == ret.ce_flags\n", ret->ce_flags);
        printf("%d == ret.ce_mask\n", ret->ce_mask);
        printf("%d == ret.gf_id\n", ret->gf_id);
        printf("%s == ret.gf_name\n", ret->gf_name);
        printf("%d == ret.gf_version\n", ret->gf_version);
        printf("%d == ret.gf_hdrsize\n", ret->gf_hdrsize);
        printf("%d == ret.gf_maxattr\n", ret->gf_maxattr);
        nl_socket_free(sk);
        return 0;
    }
    // Expected output:
    // 0 == genl_connect(sk)
    // 0 == ret.ce_msgtype
    // 0 == ret.ce_flags
    // 3 == ret.ce_mask
    // 22 == ret.gf_id
    // nl80211 == ret.gf_name
    // 0 == ret.gf_version
    // 0 == ret.gf_hdrsize
    // 0 == ret.gf_maxattr
    """
    sk = nl_socket_alloc()
    assert 0 == genl_connect(sk)
    ret = genl_ctrl_probe_by_name(sk, b'nl80211')
    assert 0 == ret.ce_msgtype
    assert 0 == ret.ce_flags
    assert 3 == ret.ce_mask
    assert 20 <= ret.gf_id
    assert b'nl80211' == ret.gf_name
    assert 0 == ret.gf_version
    assert 0 == ret.gf_hdrsize
    assert 0 == ret.gf_maxattr
    nl_socket_free(sk)