コード例 #1
0
ファイル: test_attr.py プロジェクト: ewa/libnl
def test_ints():
    """Test integer attributes."""
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_u8(msg, 2, 10)
    assert 0 == libnl.attr.nla_put_u16(msg, 3, 11)
    assert 0 == libnl.attr.nla_put_u32(msg, 4, 12)
    assert 0 == libnl.attr.nla_put_u64(msg, 5, 13195)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 2)
    assert 2 == libnl.attr.nla_type(attr)
    assert 10 == libnl.attr.nla_get_u8(attr)
    assert 5 == attr.nla_len
    assert b"BQACAAo=" == base64.b64encode(buffer(attr.bytearray[: attr.nla_len]))

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 3)
    assert 3 == libnl.attr.nla_type(attr)
    assert 11 == libnl.attr.nla_get_u16(attr)
    assert 6 == attr.nla_len
    assert b"BgADAAsA" == base64.b64encode(buffer(attr.bytearray[: attr.nla_len]))

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 4)
    assert 4 == libnl.attr.nla_type(attr)
    assert 12 == libnl.attr.nla_get_u32(attr)
    assert 8 == attr.nla_len
    assert b"CAAEAAwAAAA=" == base64.b64encode(buffer(attr.bytearray[: attr.nla_len]))

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 5)
    assert 5 == libnl.attr.nla_type(attr)
    assert 13195 == libnl.attr.nla_get_u64(attr)  # printf("%llu\n", nla_get_u64(attr));
    assert 12 == attr.nla_len
    assert b"DAAFAIszAAAAAAAA" == base64.b64encode(buffer(attr.bytearray[: attr.nla_len]))
コード例 #2
0
ファイル: ncsi-netlink.py プロジェクト: yongli3/ncsi-netlink
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
ファイル: test_attr.py プロジェクト: ewa/libnl
def test_nla_put_get_u32():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    int main() {
        int rem, i, range[] = { 0, 1, 2, 19, 20, 50 };
        struct nl_msg *msg = nlmsg_alloc();
        struct nlmsghdr *nlh = nlmsg_hdr(msg);
        struct nlattr *nla;
        for (i = 0; i < (sizeof(range) / sizeof(int)); i++) nla_put_u32(msg, i, range[i]);
        nlmsg_for_each_attr(nla, nlh, 0, rem) printf("type: %d; nla_get_u32: %d\n", nla_type(nla), nla_get_u32(nla));
        nlmsg_free(msg);
        return 0;
    }
    // Expected output:
    // type: 0; nla_get_u32: 0
    // type: 1; nla_get_u32: 1
    // type: 2; nla_get_u32: 2
    // type: 3; nla_get_u32: 19
    // type: 4; nla_get_u32: 20
    // type: 5; nla_get_u32: 50
    """
    rem = c_int()
    range_ = (0, 1, 2, 19, 20, 50)
    msg = nlmsg_alloc()
    nlh = nlmsg_hdr(msg)
    for i in range(len(range_)):
        libnl.attr.nla_put_u32(msg, i, range_[i])
    i = 0
    for nla in nlmsg_for_each_attr(nlh, 0, rem):
        assert i == libnl.attr.nla_type(nla)
        assert range_[i] == libnl.attr.nla_get_u32(nla)
        i += 1
コード例 #4
0
    def _do_scan_results(self, if_index, driver_id, results):
        # Retrieve the results of a successful scan (SSIDs and data about them).
        # This function does not require root privileges. It eventually calls a
        # callback that actually decodes data about SSIDs but this function
        # kicks that off. May exit the program (sys.exit()) if a fatal error
        # occurs.
        #
        # Positional arguments:
        # self._nl_sock -- nl_sock class instance (from nl_socket_alloc()).
        # if_index -- interface index (integer).
        # driver_id -- nl80211 driver ID from genl_ctrl_resolve() (integer).
        # results -- dictionary to populate with results. Keys are BSSIDs (MAC
        #            addresses) and values are dicts of data.
        # Returns:
        # 0 on success or a negative error code.

        msg = nlmsg_alloc()
        genlmsg_put(msg, 0, 0, driver_id, 0, NLM_F_DUMP,
                    nl80211.NL80211_CMD_GET_SCAN, 0)
        nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX, if_index)
        cb = libnl.handlers.nl_cb_alloc(libnl.handlers.NL_CB_DEFAULT)
        libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_VALID,
                                 libnl.handlers.NL_CB_CUSTOM,
                                 self._callback_dump, results)
        logger.debug('Sending NL80211_CMD_GET_SCAN...')
        ret = nl_send_auto(self._nl_sock, msg)
        if ret >= 0:
            logger.debug('Retrieving NL80211_CMD_GET_SCAN response...')
            ret = nl_recvmsgs(self._nl_sock, cb)
        return ret
コード例 #5
0
ファイル: test_attr.py プロジェクト: kimocoder/libnl-1
def test_nla_put_get_u32():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    int main() {
        int rem, i, range[] = { 0, 1, 2, 19, 20, 50 };
        struct nl_msg *msg = nlmsg_alloc();
        struct nlmsghdr *nlh = nlmsg_hdr(msg);
        struct nlattr *nla;
        for (i = 0; i < (sizeof(range) / sizeof(int)); i++) nla_put_u32(msg, i, range[i]);
        nlmsg_for_each_attr(nla, nlh, 0, rem) printf("type: %d; nla_get_u32: %d\n", nla_type(nla), nla_get_u32(nla));
        nlmsg_free(msg);
        return 0;
    }
    // Expected output:
    // type: 0; nla_get_u32: 0
    // type: 1; nla_get_u32: 1
    // type: 2; nla_get_u32: 2
    // type: 3; nla_get_u32: 19
    // type: 4; nla_get_u32: 20
    // type: 5; nla_get_u32: 50
    """
    rem = c_int()
    range_ = (0, 1, 2, 19, 20, 50)
    msg = nlmsg_alloc()
    nlh = nlmsg_hdr(msg)
    for i in range(len(range_)):
        libnl.attr.nla_put_u32(msg, i, range_[i])
    i = 0
    for nla in nlmsg_for_each_attr(nlh, 0, rem):
        assert i == libnl.attr.nla_type(nla)
        assert range_[i] == libnl.attr.nla_get_u32(nla)
        i += 1
コード例 #6
0
ファイル: scan_access_points.py プロジェクト: 0x90/libnl
def do_scan_results(sk, if_index, driver_id, results):
    """Retrieve the results of a successful scan (SSIDs and data about them).

    This function does not require root privileges. It eventually calls a callback that actually decodes data about
    SSIDs but this function kicks that off.

    May exit the program (sys.exit()) if a fatal error occurs.

    Positional arguments:
    sk -- nl_sock class instance (from nl_socket_alloc()).
    if_index -- interface index (integer).
    driver_id -- nl80211 driver ID from genl_ctrl_resolve() (integer).
    results -- dictionary to populate with results. Keys are BSSIDs (MAC addresses) and values are dicts of data.

    Returns:
    0 on success or a negative error code.
    """
    msg = nlmsg_alloc()
    genlmsg_put(msg, 0, 0, driver_id, 0, NLM_F_DUMP, nl80211.NL80211_CMD_GET_SCAN, 0)
    nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX, if_index)
    cb = libnl.handlers.nl_cb_alloc(libnl.handlers.NL_CB_DEFAULT)
    libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_VALID, libnl.handlers.NL_CB_CUSTOM, callback_dump, results)
    _LOGGER.debug('Sending NL80211_CMD_GET_SCAN...')
    ret = nl_send_auto(sk, msg)
    if ret >= 0:
        _LOGGER.debug('Retrieving NL80211_CMD_GET_SCAN response...')
        ret = nl_recvmsgs(sk, cb)
    return ret
コード例 #7
0
def do_scan_results(sk, if_index, driver_id, results):
    """Retrieve the results of a successful scan (SSIDs and data about them).

    This function does not require root privileges. It eventually calls a callback that actually decodes data about
    SSIDs but this function kicks that off.

    May exit the program (sys.exit()) if a fatal error occurs.

    Positional arguments:
    sk -- nl_sock class instance (from nl_socket_alloc()).
    if_index -- interface index (integer).
    driver_id -- nl80211 driver ID from genl_ctrl_resolve() (integer).
    results -- dictionary to populate with results. Keys are BSSIDs (MAC addresses) and values are dicts of data.

    Returns:
    0 on success or a negative error code.
    """
    msg = nlmsg_alloc()
    genlmsg_put(msg, 0, 0, driver_id, 0, NLM_F_DUMP,
                nl80211.NL80211_CMD_GET_SCAN, 0)
    nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX, if_index)
    cb = libnl.handlers.nl_cb_alloc(libnl.handlers.NL_CB_DEFAULT)
    libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_VALID,
                             libnl.handlers.NL_CB_CUSTOM, callback_dump,
                             results)
    ret = nl_send_auto(sk, msg)
    if ret >= 0:
        try:
            ret = nl_recvmsgs(sk, cb)
        except NotImplementedError:
            pass
    return ret
コード例 #8
0
ファイル: test_attr.py プロジェクト: ewa/libnl
def test_flag():
    """Test flags."""
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_flag(msg, 7)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 7)
    assert 7 == libnl.attr.nla_type(attr)
    assert libnl.attr.nla_get_flag(attr) is True  # printf("%s\n", nla_get_flag(attr) ? "True" : "False");
    assert 4 == attr.nla_len
    assert b"BAAHAA==" == base64.b64encode(buffer(attr.bytearray[: attr.nla_len]))
コード例 #9
0
ファイル: test_attr.py プロジェクト: ewa/libnl
def test_msecs():
    """Test milliseconds."""
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_msecs(msg, 12, 99)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 12)
    assert 12 == libnl.attr.nla_type(attr)
    assert 99 == libnl.attr.nla_get_msecs(attr)
    assert 12 == attr.nla_len
    assert b"DAAMAGMAAAAAAAAA" == base64.b64encode(buffer(attr.bytearray[: attr.nla_len]))
コード例 #10
0
ファイル: test_attr.py プロジェクト: kimocoder/libnl-1
def test_msecs():
    """Test milliseconds."""
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_msecs(msg, 12, 99)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 12)
    assert 12 == libnl.attr.nla_type(attr)
    assert 99 == libnl.attr.nla_get_msecs(attr)
    assert 12 == attr.nla_len
    assert b'DAAMAGMAAAAAAAAA' == base64.b64encode(
        buffer(attr.bytearray[:attr.nla_len]))
コード例 #11
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 {}
コード例 #12
0
ファイル: test_attr.py プロジェクト: ewa/libnl
def test_string_short():
    """Test string attributes with a short string."""
    payload = bytes("test".encode("ascii"))
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_string(msg, 6, payload)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 6)
    assert 6 == libnl.attr.nla_type(attr)
    assert payload == libnl.attr.nla_get_string(attr)
    assert 9 == attr.nla_len
    assert b"CQAGAHRlc3QA" == base64.b64encode(buffer(attr.bytearray[: attr.nla_len]))
コード例 #13
0
ファイル: test_attr.py プロジェクト: kimocoder/libnl-1
def test_string_short():
    """Test string attributes with a short string."""
    payload = bytes('test'.encode('ascii'))
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_string(msg, 6, payload)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 6)
    assert 6 == libnl.attr.nla_type(attr)
    assert payload == libnl.attr.nla_get_string(attr)
    assert 9 == attr.nla_len
    assert b'CQAGAHRlc3QA' == base64.b64encode(
        buffer(attr.bytearray[:attr.nla_len]))
コード例 #14
0
ファイル: test_attr.py プロジェクト: ewa/libnl
def test_string_medium():
    """Test string attributes with a longer string."""
    payload = bytes("The quick br()wn f0x jumps over the l@zy dog!".encode("ascii"))
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_string(msg, 6, payload)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 6)
    assert 6 == libnl.attr.nla_type(attr)
    assert payload == libnl.attr.nla_get_string(attr)
    assert 50 == attr.nla_len
    expected = b"MgAGAFRoZSBxdWljayBicigpd24gZjB4IGp1bXBzIG92ZXIgdGhlIGxAenkgZG9nIQA="
    assert expected == base64.b64encode(buffer(attr.bytearray[: attr.nla_len]))
コード例 #15
0
ファイル: test_attr.py プロジェクト: kimocoder/libnl-1
def test_flag():
    """Test flags."""
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_flag(msg, 7)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 7)
    assert 7 == libnl.attr.nla_type(attr)
    assert libnl.attr.nla_get_flag(
        attr) is True  # printf("%s\n", nla_get_flag(attr) ? "True" : "False");
    assert 4 == attr.nla_len
    assert b'BAAHAA==' == base64.b64encode(
        buffer(attr.bytearray[:attr.nla_len]))
コード例 #16
0
def read_function():
    # Initialize the message sent by netlink socket
    msg = nlmsg_alloc()
    # Use command CMD_GET_STATION to retreive the connected stations attributes
    # With Hostapd, the connected stations are the clients
    # See https://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git/tree/include/uapi/linux/nl80211.h?id=HEAD#n222
    genlmsg_put(msg, 0, 0, DRIVER_ID, 0, NLM_F_DUMP,
                nl80211.NL80211_CMD_GET_STATION, 0)
    # Set the network interface of the device we are working with
    # See https://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git/tree/include/uapi/linux/nl80211.h?id=HEAD#n1032
    nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX, INTERFACEINDEX)
    # Finalize and transmit message
    nl_send_auto(SOCKET, msg)
    # This list will contain the results of the kernel
    results = []
    # Bind the callbacks methods for events NL_CB_VALID and NL_CB_FINISH
    cb = libnl.handlers.nl_cb_alloc(libnl.handlers.NL_CB_DEFAULT)
    libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_VALID,
                             libnl.handlers.NL_CB_CUSTOM,
                             getStationInfo_callback, results)
    libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_FINISH,
                             libnl.handlers.NL_CB_CUSTOM, finish_callback,
                             results)
    # Receive messages from Kernel
    nl_recvmsgs(SOCKET, cb)
    while len(results) == 0:
        continue
    # Configure the collectd data sending object
    VALUES.plugin = "hostapd"
    VALUES.plugin_instance = INTERFACE
    VALUES.type = 'gauge'
    VALUES.type_instance = 'stations-count'
    # If no clients are connected, just send 0 to the metrics storage backend,
    # otherwise, send the count and the attributes of clients
    if results[-1] == -1:
        VALUES.dispatch(values=[0])
    else:
        VALUES.dispatch(values=[len(results)])
        # Browse the stations returned by the kernel
        for station in results:
            # If we shouldn't send data for every clients, we check the MAC address
            if len(CLIENTS) > 0:
                if station.mac_addr in CLIENTS:
                    send_station_stats(station)
            # If not, just send the data
            else:
                send_station_stats(station)

    # Clean a few values to avoid memory leak
    del (msg)
    del (cb)
    del (results)
コード例 #17
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))
コード例 #18
0
ファイル: test_attr.py プロジェクト: kimocoder/libnl-1
def test_string_medium():
    """Test string attributes with a longer string."""
    payload = bytes(
        'The quick br()wn f0x jumps over the l@zy dog!'.encode('ascii'))
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_string(msg, 6, payload)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 6)
    assert 6 == libnl.attr.nla_type(attr)
    assert payload == libnl.attr.nla_get_string(attr)
    assert 50 == attr.nla_len
    expected = b'MgAGAFRoZSBxdWljayBicigpd24gZjB4IGp1bXBzIG92ZXIgdGhlIGxAenkgZG9nIQA='
    assert expected == base64.b64encode(buffer(attr.bytearray[:attr.nla_len]))
コード例 #19
0
ファイル: test_attr.py プロジェクト: kimocoder/libnl-1
def test_string_long():
    """Test string attributes with a long string."""
    payload = bytes(string.printable[:-2].encode('ascii'))
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_string(msg, 6, payload)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 6)
    assert 6 == libnl.attr.nla_type(attr)
    assert payload == libnl.attr.nla_get_string(attr)
    assert 103 == attr.nla_len
    expected = (
        b'ZwAGADAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaISIjJCUmJygp'
        b'KissLS4vOjs8PT4/QFtcXV5fYHt8fX4gCQoNAA==')
    assert expected == base64.b64encode(buffer(attr.bytearray[:attr.nla_len]))
コード例 #20
0
ファイル: test_attr.py プロジェクト: ewa/libnl
def test_string_long():
    """Test string attributes with a long string."""
    payload = bytes(string.printable[:-2].encode("ascii"))
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_string(msg, 6, payload)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 6)
    assert 6 == libnl.attr.nla_type(attr)
    assert payload == libnl.attr.nla_get_string(attr)
    assert 103 == attr.nla_len
    expected = (
        b"ZwAGADAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaISIjJCUmJygp"
        b"KissLS4vOjs8PT4/QFtcXV5fYHt8fX4gCQoNAA=="
    )
    assert expected == base64.b64encode(buffer(attr.bytearray[: attr.nla_len]))
コード例 #21
0
ファイル: ncsi-netlink.py プロジェクト: yongli3/ncsi-netlink
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 genl_ctrl_probe_by_name(sk, name):
    """Look up generic Netlink family by family name querying the kernel directly.

    https://github.com/thom311/libnl/blob/libnl3_2_25/lib/genl/ctrl.c#L237

    Directly query's the kernel for a given family name.

    Note: This API call differs from genl_ctrl_search_by_name in that it queries the kernel directly, allowing for
    module autoload to take place to resolve the family request. Using an nl_cache prevents that operation.

    Positional arguments:
    sk -- Generic Netlink socket (nl_sock class instance).
    name -- family name (bytes).

    Returns:
    Generic Netlink family `genl_family` class instance or None if no match was found.
    """
    ret = genl_family_alloc()
    if not ret:
        return None

    genl_family_set_name(ret, name)
    msg = nlmsg_alloc()
    orig = nl_socket_get_cb(sk)
    cb = nl_cb_clone(orig)
    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, name)
    nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, ret)

    if nl_send_auto(sk, msg) < 0:
        return None
    if nl_recvmsgs(sk, cb) < 0:
        return None
    if wait_for_ack(
            sk
    ) < 0:  # If search was successful, request may be ACKed after data.
        return None

    if genl_family_get_id(ret) != 0:
        return ret
コード例 #23
0
ファイル: test_netlink_nlmsghdr.py プロジェクト: 0x90/libnl
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_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]))
コード例 #25
0
ファイル: ctrl.py プロジェクト: 0x90/libnl
def genl_ctrl_probe_by_name(sk, name):
    """Look up generic Netlink family by family name querying the kernel directly.

    https://github.com/thom311/libnl/blob/libnl3_2_25/lib/genl/ctrl.c#L237

    Directly query's the kernel for a given family name.

    Note: This API call differs from genl_ctrl_search_by_name in that it queries the kernel directly, allowing for
    module autoload to take place to resolve the family request. Using an nl_cache prevents that operation.

    Positional arguments:
    sk -- Generic Netlink socket (nl_sock class instance).
    name -- family name (bytes).

    Returns:
    Generic Netlink family `genl_family` class instance or None if no match was found.
    """
    ret = genl_family_alloc()
    if not ret:
        return None

    genl_family_set_name(ret, name)
    msg = nlmsg_alloc()
    orig = nl_socket_get_cb(sk)
    cb = nl_cb_clone(orig)
    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, name)
    nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, ret)

    if nl_send_auto(sk, msg) < 0:
        return None
    if nl_recvmsgs(sk, cb) < 0:
        return None
    if wait_for_ack(sk) < 0:  # If search was successful, request may be ACKed after data.
        return None

    if genl_family_get_id(ret) != 0:
        return ret
コード例 #26
0
ファイル: test_netlink_nlmsghdr.py プロジェクト: 0x90/libnl
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
ファイル: test_attr.py プロジェクト: kimocoder/libnl-1
def test_ints():
    """Test integer attributes."""
    msg = nlmsg_alloc()
    assert 0 == libnl.attr.nla_put_u8(msg, 2, 10)
    assert 0 == libnl.attr.nla_put_u16(msg, 3, 11)
    assert 0 == libnl.attr.nla_put_u32(msg, 4, 12)
    assert 0 == libnl.attr.nla_put_u64(msg, 5, 13195)

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 2)
    assert 2 == libnl.attr.nla_type(attr)
    assert 10 == libnl.attr.nla_get_u8(attr)
    assert 5 == attr.nla_len
    assert b'BQACAAo=' == base64.b64encode(
        buffer(attr.bytearray[:attr.nla_len]))

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 3)
    assert 3 == libnl.attr.nla_type(attr)
    assert 11 == libnl.attr.nla_get_u16(attr)
    assert 6 == attr.nla_len
    assert b'BgADAAsA' == base64.b64encode(
        buffer(attr.bytearray[:attr.nla_len]))

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 4)
    assert 4 == libnl.attr.nla_type(attr)
    assert 12 == libnl.attr.nla_get_u32(attr)
    assert 8 == attr.nla_len
    assert b'CAAEAAwAAAA=' == base64.b64encode(
        buffer(attr.bytearray[:attr.nla_len]))

    attr = nlmsg_find_attr(nlmsg_hdr(msg), 0, 5)
    assert 5 == libnl.attr.nla_type(attr)
    assert 13195 == libnl.attr.nla_get_u64(
        attr)  # printf("%llu\n", nla_get_u64(attr));
    assert 12 == attr.nla_len
    assert b'DAAFAIszAAAAAAAA' == base64.b64encode(
        buffer(attr.bytearray[:attr.nla_len]))
コード例 #29
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)
コード例 #30
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)
コード例 #31
0
ファイル: test_netlink_nlmsghdr.py プロジェクト: 0x90/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();
        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)
コード例 #32
0
ファイル: test_cache_mngt.py プロジェクト: kimocoder/libnl-1
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
コード例 #33
0
ファイル: scan_access_points.py プロジェクト: 0x90/libnl
def do_scan_trigger(sk, if_index, driver_id, mcid):
    """Issue a scan request to the kernel and wait for it to reply with a signal.

    This function issues NL80211_CMD_TRIGGER_SCAN which requires root privileges.

    The way NL80211 works is first you issue NL80211_CMD_TRIGGER_SCAN and wait for the kernel to signal that the scan is
    done. When that signal occurs, data is not yet available. The signal tells us if the scan was aborted or if it was
    successful (if new scan results are waiting). This function handles that simple signal.

    May exit the program (sys.exit()) if a fatal error occurs.

    Positional arguments:
    sk -- nl_sock class instance (from nl_socket_alloc()).
    if_index -- interface index (integer).
    driver_id -- nl80211 driver ID from genl_ctrl_resolve() (integer).
    mcid -- nl80211 scanning group ID from genl_ctrl_resolve_grp() (integer).

    Returns:
    0 on success or a negative error code.
    """
    # First get the "scan" membership group ID and join the socket to the group.
    _LOGGER.debug('Joining group %d.', mcid)
    ret = nl_socket_add_membership(sk, mcid)  # Listen for results of scan requests (aborted or new results).
    if ret < 0:
        return ret

    # Build the message to be sent to the kernel.
    msg = nlmsg_alloc()
    genlmsg_put(msg, 0, 0, driver_id, 0, 0, nl80211.NL80211_CMD_TRIGGER_SCAN, 0)  # Setup which command to run.
    nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX, if_index)  # Setup which interface to use.
    ssids_to_scan = nlmsg_alloc()
    nla_put(ssids_to_scan, 1, 0, b'')  # Scan all SSIDs.
    nla_put_nested(msg, nl80211.NL80211_ATTR_SCAN_SSIDS, ssids_to_scan)  # Setup what kind of scan to perform.

    # Setup the callbacks to be used for triggering the scan only.
    err = ctypes.c_int(1)  # Used as a mutable integer to be updated by the callback function. Signals end of messages.
    results = ctypes.c_int(-1)  # Signals if the scan was successful (new results) or aborted, or not started.
    cb = libnl.handlers.nl_cb_alloc(libnl.handlers.NL_CB_DEFAULT)
    libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_VALID, libnl.handlers.NL_CB_CUSTOM, callback_trigger, results)
    libnl.handlers.nl_cb_err(cb, libnl.handlers.NL_CB_CUSTOM, error_handler, err)
    libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_ACK, libnl.handlers.NL_CB_CUSTOM, ack_handler, err)
    libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_SEQ_CHECK, libnl.handlers.NL_CB_CUSTOM,
                             lambda *_: libnl.handlers.NL_OK, None)  # Ignore sequence checking.

    # Now we send the message to the kernel, and retrieve the acknowledgement. The kernel takes a few seconds to finish
    # scanning for access points.
    _LOGGER.debug('Sending NL80211_CMD_TRIGGER_SCAN...')
    ret = nl_send_auto(sk, msg)
    if ret < 0:
        return ret
    while err.value > 0:
        _LOGGER.debug('Retrieving NL80211_CMD_TRIGGER_SCAN acknowledgement...')
        ret = nl_recvmsgs(sk, cb)
        if ret < 0:
            return ret
    if err.value < 0:
        error('Unknown error {0} ({1})'.format(err.value, errmsg[abs(err.value)]))

    # Block until the kernel is done scanning or aborted the scan.
    while results.value < 0:
        _LOGGER.debug('Retrieving NL80211_CMD_TRIGGER_SCAN final response...')
        ret = nl_recvmsgs(sk, cb)
        if ret < 0:
            return ret
    if results.value > 0:
        error('The kernel aborted the scan.')

    # Done, cleaning up.
    _LOGGER.debug('Leaving group %d.', mcid)
    return nl_socket_drop_membership(sk, mcid)  # No longer need to receive multicast messages.
コード例 #34
0
ファイル: test_attr.py プロジェクト: kimocoder/libnl-1
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)
コード例 #35
0
ファイル: test_attr.py プロジェクト: kimocoder/libnl-1
def test_nested():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    int main() {
        int i, rem1, rem2;
        struct nlattr *nla;
        struct nl_msg *msg = nlmsg_alloc();
        struct nl_msg *sub = nlmsg_alloc();
        struct nlmsghdr *nlh = nlmsg_hdr(sub);
        unsigned char *buf = (unsigned char *) nlh;
        nla_put_string(sub, 0, "");
        nla_put_string(sub, 1, "Just tell me why!");
        nla_put_string(sub, 2, "Please read this 55-page warrant.");
        nla_put_string(sub, 3, "There must be robots worse than I!");
        nla_put_string(sub, 4, "We've checked around, there really aren't.");
        nlmsg_for_each_attr(nla, nlh, 0, rem1) {
            printf("type: %d len: %d; nla_get_string: %s\n", nla_type(nla), nla_len(nla), nla_get_string(nla));
        }
        for (i = 0; i < nlmsg_total_size(nlmsg_datalen(nlh)); i++) printf("%02x", buf[i]); printf("\n");
        nla_put_nested(msg, 5, sub);
        nlmsg_free(sub);

        sub = nlmsg_alloc();
        nlh = nlmsg_hdr(sub);
        buf = (unsigned char *) nlh;
        nla_put_string(sub, 6, "Aw, don't blame me,");
        nla_put_string(sub, 7, "Blame my upbringing!");
        nlmsg_for_each_attr(nla, nlh, 0, rem1) {
            printf("type: %d len: %d; nla_get_string: %s\n", nla_type(nla), nla_len(nla), nla_get_string(nla));
        }
        for (i = 0; i < nlmsg_total_size(nlmsg_datalen(nlh)); i++) printf("%02x", buf[i]); printf("\n");
        nla_put_nested(msg, 8, sub);
        nlmsg_free(sub);

        nlh = nlmsg_hdr(msg);
        buf = (unsigned char *) nlh;
        nla_put_u16(msg, 9, 666);
        for (i = 0; i < nlmsg_total_size(nlmsg_datalen(nlh)); i++) printf("%02x", buf[i]); printf("\n");

        struct nlattr *nla_outer;
        nlmsg_for_each_attr(nla_outer, nlh, 0, rem1) {
            if (nla_type(nla_outer) != 9) {
                printf("Outer type: %d len:%d\n", nla_type(nla_outer), nla_len(nla_outer));
                nla_for_each_nested(nla, nla_outer, rem2) {
                    printf("type: %d len: %d; nla_get_string: %s\n", nla_type(nla), nla_len(nla), nla_get_string(nla));
                }
            } else {
                printf("t: %d l:%d; get_u16: %d\n", nla_type(nla_outer), nla_len(nla_outer), nla_get_u16(nla_outer));
            }
        }

        nlmsg_free(msg);
        return 0;
    }
    // Expected output:
    // type: 0 len: 1; nla_get_string:
    // type: 1 len: 18; nla_get_string: Just tell me why!
    // type: 2 len: 34; nla_get_string: Please read this 55-page warrant.
    // type: 3 len: 35; nla_get_string: There must be robots worse than I!
    // type: 4 len: 43; nla_get_string: We've checked around, there really aren't.
    // b00000000000000000000000000000000500000000000000160001004a7573742074656c6c206d65207768792100000026000200506c65617
    365207265616420746869732035352d706167652077617272616e742e000000270003005468657265206d75737420626520726f626f747320776
    f727365207468616e20492100002f000400576527766520636865636b65642061726f756e642c207468657265207265616c6c79206172656e277
    42e0000
    // type: 6 len: 20; nla_get_string: Aw, don't blame me,
    // type: 7 len: 21; nla_get_string: Blame my upbringing!
    // 440000000000000000000000000000001800060041772c20646f6e277420626c616d65206d652c0019000700426c616d65206d79207570627
    2696e67696e672100000000
    // f4000000000000000000000000000000a40005000500000000000000160001004a7573742074656c6c206d652077687921000000260002005
    06c65617365207265616420746869732035352d706167652077617272616e742e000000270003005468657265206d75737420626520726f626f7
    47320776f727365207468616e20492100002f000400576527766520636865636b65642061726f756e642c207468657265207265616c6c7920617
    2656e27742e0000380008001800060041772c20646f6e277420626c616d65206d652c0019000700426c616d65206d792075706272696e67696e6
    72100000000060009009a020000
    // Outer type: 5 len:160
    // type: 0 len: 1; nla_get_string:
    // type: 1 len: 18; nla_get_string: Just tell me why!
    // type: 2 len: 34; nla_get_string: Please read this 55-page warrant.
    // type: 3 len: 35; nla_get_string: There must be robots worse than I!
    // type: 4 len: 43; nla_get_string: We've checked around, there really aren't.
    // Outer type: 8 len:52
    // type: 6 len: 20; nla_get_string: Aw, don't blame me,
    // type: 7 len: 21; nla_get_string: Blame my upbringing!
    // t: 9 l:2; get_u16: 666
    """
    rem1, rem2 = c_int(), c_int()
    msg = nlmsg_alloc()
    sub = nlmsg_alloc()
    nlh = nlmsg_hdr(sub)
    libnl.attr.nla_put_string(sub, 0, b'')
    libnl.attr.nla_put_string(sub, 1, b'Just tell me why!')
    libnl.attr.nla_put_string(sub, 2, b'Please read this 55-page warrant.')
    libnl.attr.nla_put_string(sub, 3, b'There must be robots worse than I!')
    libnl.attr.nla_put_string(sub, 4,
                              b"We've checked around, there really aren't.")
    actual = list()
    for nla in nlmsg_for_each_attr(nlh, 0, rem1):
        actual.append((libnl.attr.nla_type(nla), libnl.attr.nla_len(nla),
                       libnl.attr.nla_get_string(nla)))
    expected = [
        (0, 1, b''),
        (1, 18, b'Just tell me why!'),
        (2, 34, b'Please read this 55-page warrant.'),
        (3, 35, b'There must be robots worse than I!'),
        (4, 43, b"We've checked around, there really aren't."),
    ]
    assert expected == actual
    expected = (
        'b00000000000000000000000000000000500000000000000160001004a7573742074656c6c206d652077687921000000260002'
        '00506c65617365207265616420746869732035352d706167652077617272616e742e000000270003005468657265206d757374'
        '20626520726f626f747320776f727365207468616e20492100002f000400576527766520636865636b65642061726f756e642c'
        '207468657265207265616c6c79206172656e27742e0000')
    assert expected == ''.join(
        format(c, '02x')
        for c in nlh.bytearray[:nlmsg_total_size(nlmsg_datalen(nlh))])
    libnl.attr.nla_put_nested(msg, 5, sub)

    sub = nlmsg_alloc()
    nlh = nlmsg_hdr(sub)
    libnl.attr.nla_put_string(sub, 6, b"Aw, don't blame me,")
    libnl.attr.nla_put_string(sub, 7, b'Blame my upbringing!')
    actual = list()
    for nla in nlmsg_for_each_attr(nlh, 0, rem1):
        actual.append((libnl.attr.nla_type(nla), libnl.attr.nla_len(nla),
                       libnl.attr.nla_get_string(nla)))
    expected = [
        (6, 20, b"Aw, don't blame me,"),
        (7, 21, b'Blame my upbringing!'),
    ]
    assert expected == actual
    expected = (
        '440000000000000000000000000000001800060041772c20646f6e277420626c616d65206d652c0019000700426c616d65206d'
        '792075706272696e67696e672100000000')
    assert expected == ''.join(
        format(c, '02x')
        for c in nlh.bytearray[:nlmsg_total_size(nlmsg_datalen(nlh))])
    libnl.attr.nla_put_nested(msg, 8, sub)

    nlh = nlmsg_hdr(msg)
    libnl.attr.nla_put_u16(msg, 9, 666)
    expected = (
        'f4000000000000000000000000000000a40005000500000000000000160001004a7573742074656c6c206d6520776879210000'
        '0026000200506c65617365207265616420746869732035352d706167652077617272616e742e00000027000300546865726520'
        '6d75737420626520726f626f747320776f727365207468616e20492100002f000400576527766520636865636b65642061726f'
        '756e642c207468657265207265616c6c79206172656e27742e0000380008001800060041772c20646f6e277420626c616d6520'
        '6d652c0019000700426c616d65206d792075706272696e67696e672100000000060009009a020000'
    )
    assert expected == ''.join(
        format(c, '02x')
        for c in nlh.bytearray[:nlmsg_total_size(nlmsg_datalen(nlh))])

    actual = list()
    for nla_outer in nlmsg_for_each_attr(nlh, 0, rem1):
        if libnl.attr.nla_type(nla_outer) != 9:
            actual.append((libnl.attr.nla_type(nla_outer),
                           libnl.attr.nla_len(nla_outer), b'Outer'))
            for nla in libnl.attr.nla_for_each_nested(nla_outer, rem2):
                actual.append(
                    (libnl.attr.nla_type(nla), libnl.attr.nla_len(nla),
                     libnl.attr.nla_get_string(nla)))
        else:
            actual.append(
                (libnl.attr.nla_type(nla_outer), libnl.attr.nla_len(nla_outer),
                 libnl.attr.nla_get_u16(nla_outer)))
    expected = [
        (5, 160, b'Outer'),
        (0, 1, b''),
        (1, 18, b'Just tell me why!'),
        (2, 34, b'Please read this 55-page warrant.'),
        (3, 35, b'There must be robots worse than I!'),
        (4, 43, b"We've checked around, there really aren't."),
        (8, 52, b'Outer'),
        (6, 20, b"Aw, don't blame me,"),
        (7, 21, b'Blame my upbringing!'),
        (9, 2, 666),
    ]
    assert expected == actual
コード例 #36
0
ファイル: test_attr.py プロジェクト: ewa/libnl
def test_nested():
    r"""C code to test against.

    // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out
    #include <netlink/msg.h>
    int main() {
        int i, rem1, rem2;
        struct nlattr *nla;
        struct nl_msg *msg = nlmsg_alloc();
        struct nl_msg *sub = nlmsg_alloc();
        struct nlmsghdr *nlh = nlmsg_hdr(sub);
        unsigned char *buf = (unsigned char *) nlh;
        nla_put_string(sub, 0, "");
        nla_put_string(sub, 1, "Just tell me why!");
        nla_put_string(sub, 2, "Please read this 55-page warrant.");
        nla_put_string(sub, 3, "There must be robots worse than I!");
        nla_put_string(sub, 4, "We've checked around, there really aren't.");
        nlmsg_for_each_attr(nla, nlh, 0, rem1) {
            printf("type: %d len: %d; nla_get_string: %s\n", nla_type(nla), nla_len(nla), nla_get_string(nla));
        }
        for (i = 0; i < nlmsg_total_size(nlmsg_datalen(nlh)); i++) printf("%02x", buf[i]); printf("\n");
        nla_put_nested(msg, 5, sub);
        nlmsg_free(sub);

        sub = nlmsg_alloc();
        nlh = nlmsg_hdr(sub);
        buf = (unsigned char *) nlh;
        nla_put_string(sub, 6, "Aw, don't blame me,");
        nla_put_string(sub, 7, "Blame my upbringing!");
        nlmsg_for_each_attr(nla, nlh, 0, rem1) {
            printf("type: %d len: %d; nla_get_string: %s\n", nla_type(nla), nla_len(nla), nla_get_string(nla));
        }
        for (i = 0; i < nlmsg_total_size(nlmsg_datalen(nlh)); i++) printf("%02x", buf[i]); printf("\n");
        nla_put_nested(msg, 8, sub);
        nlmsg_free(sub);

        nlh = nlmsg_hdr(msg);
        buf = (unsigned char *) nlh;
        nla_put_u16(msg, 9, 666);
        for (i = 0; i < nlmsg_total_size(nlmsg_datalen(nlh)); i++) printf("%02x", buf[i]); printf("\n");

        struct nlattr *nla_outer;
        nlmsg_for_each_attr(nla_outer, nlh, 0, rem1) {
            if (nla_type(nla_outer) != 9) {
                printf("Outer type: %d len:%d\n", nla_type(nla_outer), nla_len(nla_outer));
                nla_for_each_nested(nla, nla_outer, rem2) {
                    printf("type: %d len: %d; nla_get_string: %s\n", nla_type(nla), nla_len(nla), nla_get_string(nla));
                }
            } else {
                printf("t: %d l:%d; get_u16: %d\n", nla_type(nla_outer), nla_len(nla_outer), nla_get_u16(nla_outer));
            }
        }

        nlmsg_free(msg);
        return 0;
    }
    // Expected output:
    // type: 0 len: 1; nla_get_string:
    // type: 1 len: 18; nla_get_string: Just tell me why!
    // type: 2 len: 34; nla_get_string: Please read this 55-page warrant.
    // type: 3 len: 35; nla_get_string: There must be robots worse than I!
    // type: 4 len: 43; nla_get_string: We've checked around, there really aren't.
    // b00000000000000000000000000000000500000000000000160001004a7573742074656c6c206d65207768792100000026000200506c65617
    365207265616420746869732035352d706167652077617272616e742e000000270003005468657265206d75737420626520726f626f747320776
    f727365207468616e20492100002f000400576527766520636865636b65642061726f756e642c207468657265207265616c6c79206172656e277
    42e0000
    // type: 6 len: 20; nla_get_string: Aw, don't blame me,
    // type: 7 len: 21; nla_get_string: Blame my upbringing!
    // 440000000000000000000000000000001800060041772c20646f6e277420626c616d65206d652c0019000700426c616d65206d79207570627
    2696e67696e672100000000
    // f4000000000000000000000000000000a40005000500000000000000160001004a7573742074656c6c206d652077687921000000260002005
    06c65617365207265616420746869732035352d706167652077617272616e742e000000270003005468657265206d75737420626520726f626f7
    47320776f727365207468616e20492100002f000400576527766520636865636b65642061726f756e642c207468657265207265616c6c7920617
    2656e27742e0000380008001800060041772c20646f6e277420626c616d65206d652c0019000700426c616d65206d792075706272696e67696e6
    72100000000060009009a020000
    // Outer type: 5 len:160
    // type: 0 len: 1; nla_get_string:
    // type: 1 len: 18; nla_get_string: Just tell me why!
    // type: 2 len: 34; nla_get_string: Please read this 55-page warrant.
    // type: 3 len: 35; nla_get_string: There must be robots worse than I!
    // type: 4 len: 43; nla_get_string: We've checked around, there really aren't.
    // Outer type: 8 len:52
    // type: 6 len: 20; nla_get_string: Aw, don't blame me,
    // type: 7 len: 21; nla_get_string: Blame my upbringing!
    // t: 9 l:2; get_u16: 666
    """
    rem1, rem2 = c_int(), c_int()
    msg = nlmsg_alloc()
    sub = nlmsg_alloc()
    nlh = nlmsg_hdr(sub)
    libnl.attr.nla_put_string(sub, 0, b"")
    libnl.attr.nla_put_string(sub, 1, b"Just tell me why!")
    libnl.attr.nla_put_string(sub, 2, b"Please read this 55-page warrant.")
    libnl.attr.nla_put_string(sub, 3, b"There must be robots worse than I!")
    libnl.attr.nla_put_string(sub, 4, b"We've checked around, there really aren't.")
    actual = list()
    for nla in nlmsg_for_each_attr(nlh, 0, rem1):
        actual.append((libnl.attr.nla_type(nla), libnl.attr.nla_len(nla), libnl.attr.nla_get_string(nla)))
    expected = [
        (0, 1, b""),
        (1, 18, b"Just tell me why!"),
        (2, 34, b"Please read this 55-page warrant."),
        (3, 35, b"There must be robots worse than I!"),
        (4, 43, b"We've checked around, there really aren't."),
    ]
    assert expected == actual
    expected = (
        "b00000000000000000000000000000000500000000000000160001004a7573742074656c6c206d652077687921000000260002"
        "00506c65617365207265616420746869732035352d706167652077617272616e742e000000270003005468657265206d757374"
        "20626520726f626f747320776f727365207468616e20492100002f000400576527766520636865636b65642061726f756e642c"
        "207468657265207265616c6c79206172656e27742e0000"
    )
    assert expected == "".join(format(c, "02x") for c in nlh.bytearray[: nlmsg_total_size(nlmsg_datalen(nlh))])
    libnl.attr.nla_put_nested(msg, 5, sub)

    sub = nlmsg_alloc()
    nlh = nlmsg_hdr(sub)
    libnl.attr.nla_put_string(sub, 6, b"Aw, don't blame me,")
    libnl.attr.nla_put_string(sub, 7, b"Blame my upbringing!")
    actual = list()
    for nla in nlmsg_for_each_attr(nlh, 0, rem1):
        actual.append((libnl.attr.nla_type(nla), libnl.attr.nla_len(nla), libnl.attr.nla_get_string(nla)))
    expected = [(6, 20, b"Aw, don't blame me,"), (7, 21, b"Blame my upbringing!")]
    assert expected == actual
    expected = (
        "440000000000000000000000000000001800060041772c20646f6e277420626c616d65206d652c0019000700426c616d65206d"
        "792075706272696e67696e672100000000"
    )
    assert expected == "".join(format(c, "02x") for c in nlh.bytearray[: nlmsg_total_size(nlmsg_datalen(nlh))])
    libnl.attr.nla_put_nested(msg, 8, sub)

    nlh = nlmsg_hdr(msg)
    libnl.attr.nla_put_u16(msg, 9, 666)
    expected = (
        "f4000000000000000000000000000000a40005000500000000000000160001004a7573742074656c6c206d6520776879210000"
        "0026000200506c65617365207265616420746869732035352d706167652077617272616e742e00000027000300546865726520"
        "6d75737420626520726f626f747320776f727365207468616e20492100002f000400576527766520636865636b65642061726f"
        "756e642c207468657265207265616c6c79206172656e27742e0000380008001800060041772c20646f6e277420626c616d6520"
        "6d652c0019000700426c616d65206d792075706272696e67696e672100000000060009009a020000"
    )
    assert expected == "".join(format(c, "02x") for c in nlh.bytearray[: nlmsg_total_size(nlmsg_datalen(nlh))])

    actual = list()
    for nla_outer in nlmsg_for_each_attr(nlh, 0, rem1):
        if libnl.attr.nla_type(nla_outer) != 9:
            actual.append((libnl.attr.nla_type(nla_outer), libnl.attr.nla_len(nla_outer), b"Outer"))
            for nla in libnl.attr.nla_for_each_nested(nla_outer, rem2):
                actual.append((libnl.attr.nla_type(nla), libnl.attr.nla_len(nla), libnl.attr.nla_get_string(nla)))
        else:
            actual.append(
                (libnl.attr.nla_type(nla_outer), libnl.attr.nla_len(nla_outer), libnl.attr.nla_get_u16(nla_outer))
            )
    expected = [
        (5, 160, b"Outer"),
        (0, 1, b""),
        (1, 18, b"Just tell me why!"),
        (2, 34, b"Please read this 55-page warrant."),
        (3, 35, b"There must be robots worse than I!"),
        (4, 43, b"We've checked around, there really aren't."),
        (8, 52, b"Outer"),
        (6, 20, b"Aw, don't blame me,"),
        (7, 21, b"Blame my upbringing!"),
        (9, 2, 666),
    ]
    assert expected == actual
コード例 #37
0
ファイル: test_cache_mngt.py プロジェクト: 0x90/libnl
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
コード例 #38
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
コード例 #39
0
def do_scan_trigger(sk, if_index, driver_id, mcid):
    """Issue a scan request to the kernel and wait for it to reply with a signal.

    This function issues NL80211_CMD_TRIGGER_SCAN which requires root privileges.

    The way NL80211 works is first you issue NL80211_CMD_TRIGGER_SCAN and wait for the kernel to signal that the scan is
    done. When that signal occurs, data is not yet available. The signal tells us if the scan was aborted or if it was
    successful (if new scan results are waiting). This function handles that simple signal.

    May exit the program (sys.exit()) if a fatal error occurs.

    Positional arguments:
    sk -- nl_sock class instance (from nl_socket_alloc()).
    if_index -- interface index (integer).
    driver_id -- nl80211 driver ID from genl_ctrl_resolve() (integer).
    mcid -- nl80211 scanning group ID from genl_ctrl_resolve_grp() (integer).

    Returns:
    0 on success or a negative error code.
    """
    # First get the "scan" membership group ID and join the socket to the group.
    ret = nl_socket_add_membership(
        sk,
        mcid)  # Listen for results of scan requests (aborted or new results).
    if ret < 0:
        return ret

    # Build the message to be sent to the kernel.
    msg = nlmsg_alloc()
    genlmsg_put(msg, 0, 0, driver_id, 0, 0, nl80211.NL80211_CMD_TRIGGER_SCAN,
                0)  # Setup which command to run.
    nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX,
                if_index)  # Setup which interface to use.
    ssids_to_scan = nlmsg_alloc()
    nla_put(ssids_to_scan, 1, 0, b'')  # Scan all SSIDs.
    nla_put_nested(msg, nl80211.NL80211_ATTR_SCAN_SSIDS,
                   ssids_to_scan)  # Setup what kind of scan to perform.

    # Setup the callbacks to be used for triggering the scan only.
    err = ctypes.c_int(
        1
    )  # Used as a mutable integer to be updated by the callback function. Signals end of messages.
    results = ctypes.c_int(
        -1
    )  # Signals if the scan was successful (new results) or aborted, or not started.
    cb = libnl.handlers.nl_cb_alloc(libnl.handlers.NL_CB_DEFAULT)
    libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_VALID,
                             libnl.handlers.NL_CB_CUSTOM, callback_trigger,
                             results)
    libnl.handlers.nl_cb_err(cb, libnl.handlers.NL_CB_CUSTOM, error_handler,
                             err)
    libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_ACK,
                             libnl.handlers.NL_CB_CUSTOM, ack_handler, err)
    libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_SEQ_CHECK,
                             libnl.handlers.NL_CB_CUSTOM,
                             lambda *_: libnl.handlers.NL_OK,
                             None)  # Ignore sequence checking.

    # Now we send the message to the kernel, and retrieve the acknowledgement. The kernel takes a few seconds to finish
    # scanning for access points.
    ret = nl_send_auto(sk, msg)
    if ret < 0:
        return ret
    while err.value > 0:
        ret = nl_recvmsgs(sk, cb)
        if ret < 0:
            return ret
    if err.value < 0:
        raise RuntimeError("Unknown Error")

    # Block until the kernel is done scanning or aborted the scan.
    while results.value < 0:
        ret = nl_recvmsgs(sk, cb)
        if ret < 0:
            return ret
    if results.value > 0:
        raise RuntimeError('The kernel aborted the scan.')

    # Done, cleaning up.
    return nl_socket_drop_membership(
        sk, mcid)  # No longer need to receive multicast messages.
コード例 #40
0
    def _do_scan_trigger(self, if_index, driver_id, mcid):
        # Issue a scan request to the kernel and wait for it to reply with a
        # signal.
        #
        # This function issues NL80211_CMD_TRIGGER_SCAN which requires root
        # privileges. The way NL80211 works is first you issue
        # NL80211_CMD_TRIGGER_SCAN and wait for the kernel to signal that the
        # scan is done. When that signal occurs, data is not yet available. The
        # signal tells us if the scan was aborted or if it was successful (if
        # new scan results are waiting). This function handles that simple
        # signal. May exit the program (sys.exit()) if a fatal error occurs.
        #
        # Positional arguments:
        # self._nl_sock -- nl_sock class instance (from nl_socket_alloc()).
        # if_index -- interface index (integer).
        # driver_id -- nl80211 driver ID from genl_ctrl_resolve() (integer).
        # mcid -- nl80211 scanning group ID from genl_ctrl_resolve_grp()
        #                (integer).
        #
        # Returns:
        # 0 on success or a negative error code.

        # First get the "scan" membership group ID and join the socket to the
        # group.
        logger.debug('Joining group %d.', mcid)
        # Listen for results of scan requests (aborted or new results).
        ret = nl_socket_add_membership(self._nl_sock, mcid)
        if ret < 0:
            return ret

        # Build the message to be sent to the kernel.
        msg = nlmsg_alloc()
        # Setup which command to run.
        genlmsg_put(msg, 0, 0, driver_id, 0, 0,
                    nl80211.NL80211_CMD_TRIGGER_SCAN, 0)
        # Setup which interface to use.
        nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX, if_index)
        ssids_to_scan = nlmsg_alloc()
        nla_put(ssids_to_scan, 1, 0, b'')  # Scan all SSIDs.
        # Setup what kind of scan to perform.
        nla_put_nested(msg, nl80211.NL80211_ATTR_SCAN_SSIDS, ssids_to_scan)

        # Setup the callbacks to be used for triggering the scan only.
        # Used as a mutable integer to be updated by the callback function.
        # Signals end of messages.
        err = ctypes.c_int(1)
        # Signals if the scan was successful (new results) or aborted, or not
        # started.
        results = ctypes.c_int(-1)
        cb = libnl.handlers.nl_cb_alloc(libnl.handlers.NL_CB_DEFAULT)
        libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_VALID,
                                 libnl.handlers.NL_CB_CUSTOM,
                                 self._callback_trigger, results)
        libnl.handlers.nl_cb_err(cb, libnl.handlers.NL_CB_CUSTOM,
                                 self._error_handler, err)
        libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_ACK,
                                 libnl.handlers.NL_CB_CUSTOM,
                                 self._ack_handler, err)
        libnl.handlers.nl_cb_set(cb, libnl.handlers.NL_CB_SEQ_CHECK,
                                 libnl.handlers.NL_CB_CUSTOM,
                                 lambda *_: libnl.handlers.NL_OK,
                                 None)  # Ignore sequence checking.

        # Now we send the message to the kernel, and retrieve the
        # acknowledgement. The kernel takes a few seconds to finish scanning for
        # access points.
        logger.debug('Sending NL80211_CMD_TRIGGER_SCAN...')
        ret = nl_send_auto(self._nl_sock, msg)
        if ret < 0:
            return ret
        while err.value > 0:
            logger.debug(
                'Retrieving NL80211_CMD_TRIGGER_SCAN acknowledgement...')
            ret = nl_recvmsgs(self._nl_sock, cb)
            if ret < 0:
                return ret
        if err.value < 0:
            logger.warning('Unknown error {0} ({1})'.format(
                err.value, errmsg[abs(err.value)]))

        # Block until the kernel is done scanning or aborted the scan.
        while results.value < 0:
            logger.debug(
                'Retrieving NL80211_CMD_TRIGGER_SCAN final response...')
            ret = nl_recvmsgs(self._nl_sock, cb)
            if ret < 0:
                return ret
        if results.value > 0:
            logger.warning('The kernel aborted the scan.')

        # Done, cleaning up.
        logger.debug('Leaving group %d.', mcid)
        # No longer need to receive multicast messages.
        return nl_socket_drop_membership(self._nl_sock, mcid)
コード例 #41
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
コード例 #42
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))
コード例 #43
0
def channel_hopper():
    global count

    # Get the index of the interface
    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, IOError):
        error('wireless interface {0} does not exist.'.format(interface))
        return -1
    finally:
        sk.close()

    if_index = int(info[1])

    # Open a socket to the kernel
    sk = nl_socket_alloc()
    ret = genl_connect(sk)
    if ret < 0:
        reason = errmsg[abs(ret)]
        error('genl_connect() failed: {0} ({1})'.format(ret, reason))
        return -1

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

    # Iterate over channels using the corresponding dwell time
    supported_channels = [x for x in channels if x not in unsupported_channels]
    for ch in supported_channels:

        if not sniffing:
            break

        # Set new channel
        msg = nlmsg_alloc()
        genlmsg_put(msg, 0, 0, driver_id, 0, 0,
                    nl80211.NL80211_CMD_SET_CHANNEL, 0)
        nla_put_u32(msg, nl80211.NL80211_ATTR_IFINDEX, if_index)
        nla_put_u32(msg, nl80211.NL80211_ATTR_WIPHY_FREQ,
                    channel_to_frequency(ch))
        nla_put_u32(msg, nl80211.NL80211_ATTR_WIPHY_CHANNEL_TYPE,
                    nl80211.NL80211_CHAN_WIDTH_20)

        if nl_send_auto(sk, msg) < 0:
            unsupported_channels.add(ch)
            time.sleep(0.02)
        else:
            count = 0
            time.sleep(dwelltimes[ch])
            if count == 0:
                dwelltimes[ch] = mindwelltime
            else:
                dwelltimes[ch] = maxdwelltime

    return 0