Example #1
0
File: msg.py Project: 0x90/libnl
def dump_attrs(ofd, attrs, attrlen, prefix=0):
    """https://github.com/thom311/libnl/blob/libnl3_2_25/lib/msg.c#L869.

    Positional arguments:
    ofd -- function to call with arguments similar to `logging.debug`.
    attrs -- nlattr class instance.
    attrlen -- length of payload (integer).

    Keyword arguments:
    prefix -- additional number of whitespace pairs to prefix each log statement with.
    """
    prefix_whitespaces = '  ' * prefix
    rem = c_int()
    for nla in nla_for_each_attr(attrs, attrlen, rem):
        alen = nla_len(nla)
        if nla.nla_type == 0:
            ofd('%s  [ATTR PADDING] %d octets', prefix_whitespaces, alen)
        else:
            is_nested = ' NESTED' if nla_is_nested(nla) else ''
            ofd('%s  [ATTR %02d%s] %d octets', prefix_whitespaces, nla.nla_type, is_nested, alen)

        if nla_is_nested(nla):
            dump_attrs(ofd, nla_data(nla), alen, prefix + 1)
        else:
            dump_attr(ofd, nla, prefix)

        padlen = nla_padlen(alen)
        if padlen > 0:
            ofd('%s  [PADDING] %d octets', prefix_whitespaces, padlen)
            dump_hex(ofd, bytearray_ptr(nla_data(nla), alen), padlen, prefix)

    if rem.value:
        ofd('%s  [LEFTOVER] %d octets', prefix_whitespaces, rem)
def callback(msg, has_printed):
    """Callback function called by libnl upon receiving messages from the kernel.

    Positional arguments:
    msg -- nl_msg class instance containing the data sent by the kernel.
    has_printed -- simple pseudo boolean (if list is empty) to keep track of when to print emtpy lines.

    Returns:
    An integer, value of NL_SKIP. It tells libnl to stop calling other callbacks for this message and proceed with
    processing the next kernel message.
    """
    table = AsciiTable([['Data Type', 'Data Value']])
    # First convert `msg` into something more manageable.
    gnlh = genlmsghdr(nlmsg_data(nlmsg_hdr(msg)))

    # Partially parse the raw binary data and place them in the `tb` dictionary.
    tb = dict(
        (i, None)
        for i in range(nl80211.NL80211_ATTR_MAX +
                       1))  # Need to populate dict with all possible keys.
    nla_parse(tb, nl80211.NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
              genlmsg_attrlen(gnlh, 0), None)

    # Now it's time to grab the juicy data!
    if tb[nl80211.NL80211_ATTR_IFNAME]:
        table.title = nla_get_string(
            tb[nl80211.NL80211_ATTR_IFNAME]).decode('ascii')
    else:
        table.title = 'Unnamed Interface'

    if tb[nl80211.NL80211_ATTR_WIPHY]:
        wiphy_num = nla_get_u32(tb[nl80211.NL80211_ATTR_WIPHY])
        wiphy = ('wiphy {0}'
                 if OPTIONS['<interface>'] else 'phy#{0}').format(wiphy_num)
        table.table_data.append(['NL80211_ATTR_WIPHY', wiphy])

    if tb[nl80211.NL80211_ATTR_MAC]:
        mac_address = ':'.join(
            format(x, '02x')
            for x in nla_data(tb[nl80211.NL80211_ATTR_MAC])[:6])
        table.table_data.append(['NL80211_ATTR_MAC', mac_address])

    if tb[nl80211.NL80211_ATTR_IFINDEX]:
        table.table_data.append([
            'NL80211_ATTR_IFINDEX',
            str(nla_get_u32(tb[nl80211.NL80211_ATTR_IFINDEX]))
        ])

    # Print all data.
    if has_printed:
        print()
    else:
        has_printed.append(True)
    print(table.table)
    return NL_SKIP
Example #3
0
File: msg.py Project: 0x90/libnl
def dump_attr(ofd, attr, prefix=0):
    """https://github.com/thom311/libnl/blob/libnl3_2_25/lib/msg.c#L862.

    Positional arguments:
    ofd -- function to call with arguments similar to `logging.debug`.
    attr -- nlattr class instance.

    Keyword arguments:
    prefix -- additional number of whitespace pairs to prefix each log statement with.
    """
    dump_hex(ofd, nla_data(attr), nla_len(attr), prefix)
Example #4
0
def callback(msg, has_printed):
    """Callback function called by libnl upon receiving messages from the kernel.

    Positional arguments:
    msg -- nl_msg class instance containing the data sent by the kernel.
    has_printed -- simple pseudo boolean (if list is empty) to keep track of when to print emtpy lines.

    Returns:
    An integer, value of NL_SKIP. It tells libnl to stop calling other callbacks for this message and proceed with
    processing the next kernel message.
    """
    table = AsciiTable([['Data Type', 'Data Value']])
    # First convert `msg` into something more manageable.
    gnlh = genlmsghdr(nlmsg_data(nlmsg_hdr(msg)))

    # Partially parse the raw binary data and place them in the `tb` dictionary.
    tb = dict((i, None) for i in range(nl80211.NL80211_ATTR_MAX + 1))  # Need to populate dict with all possible keys.
    nla_parse(tb, nl80211.NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), None)

    # Now it's time to grab the juicy data!
    if tb[nl80211.NL80211_ATTR_IFNAME]:
        table.title = nla_get_string(tb[nl80211.NL80211_ATTR_IFNAME]).decode('ascii')
    else:
        table.title = 'Unnamed Interface'

    if tb[nl80211.NL80211_ATTR_WIPHY]:
        wiphy_num = nla_get_u32(tb[nl80211.NL80211_ATTR_WIPHY])
        wiphy = ('wiphy {0}' if OPTIONS['<interface>'] else 'phy#{0}').format(wiphy_num)
        table.table_data.append(['NL80211_ATTR_WIPHY', wiphy])

    if tb[nl80211.NL80211_ATTR_MAC]:
        mac_address = ':'.join(format(x, '02x') for x in nla_data(tb[nl80211.NL80211_ATTR_MAC])[:6])
        table.table_data.append(['NL80211_ATTR_MAC', mac_address])

    if tb[nl80211.NL80211_ATTR_IFINDEX]:
        table.table_data.append(['NL80211_ATTR_IFINDEX', str(nla_get_u32(tb[nl80211.NL80211_ATTR_IFINDEX]))])

    # Print all data.
    if has_printed:
        print()
    else:
        has_printed.append(True)
    print(table.table)
    return NL_SKIP
    def _iface_callback(self, msg, _):
        # Callback function called by libnl upon receiving messages from the
        # kernel.
        #
        # Positional arguments:
        # msg -- nl_msg class instance containing the data sent by the kernel.
        #
        # Returns:
        # An integer, value of NL_SKIP. It tells libnl to stop calling other
        # callbacks for this message and proceed with processing the next kernel
        # message.
        # First convert `msg` into something more manageable.
        gnlh = genlmsghdr(nlmsg_data(nlmsg_hdr(msg)))

        # Partially parse the raw binary data and place them in the `tb`
        # dictionary. Need to populate dict with all possible keys.
        tb = dict((i, None) for i in range(nl80211.NL80211_ATTR_MAX + 1))
        nla_parse(tb, nl80211.NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
                  genlmsg_attrlen(gnlh, 0), None)

        # Now it's time to grab the data, we start with the interface index as
        # universal identifier
        if tb[nl80211.NL80211_ATTR_IFINDEX]:
            if_index = nla_get_u32(tb[nl80211.NL80211_ATTR_IFINDEX])
        else:
            return NL_SKIP

        # Create new interface dict if this interface is not yet known
        if if_index in self.iface_data:
            iface_data = self.iface_data[if_index]
        else:
            iface_data = {}

        if tb[nl80211.NL80211_ATTR_IFNAME]:
            iface_data['name'] = nla_get_string(
                tb[nl80211.NL80211_ATTR_IFNAME]).decode('ascii')

        if tb[nl80211.NL80211_ATTR_IFTYPE]:
            iftype = nla_get_u32(tb[nl80211.NL80211_ATTR_IFTYPE])

            if iftype == nl80211.NL80211_IFTYPE_UNSPECIFIED:
                typestr = 'UNSPECIFIED'
            elif iftype == nl80211.NL80211_IFTYPE_ADHOC:
                typestr = 'ADHOC'
            elif iftype == nl80211.NL80211_IFTYPE_STATION:
                typestr = 'STATION'
            elif iftype == nl80211.NL80211_IFTYPE_AP:
                typestr = 'AP'
            elif iftype == nl80211.NL80211_IFTYPE_AP_VLAN:
                typestr = 'AP_VLAN'
            elif iftype == nl80211.NL80211_IFTYPE_WDS:
                typestr = 'WDS'
            elif iftype == nl80211.NL80211_IFTYPE_MONITOR:
                typestr = 'MONITOR'
            elif iftype == nl80211.NL80211_IFTYPE_MESH_POINT:
                typestr = 'MESH_POINT'
            elif iftype == nl80211.NL80211_IFTYPE_P2P_CLIENT:
                typestr = 'P2P_CLIENT'
            elif iftype == nl80211.NL80211_IFTYPE_P2P_GO:
                typestr = 'P2P_GO'
            elif iftype == nl80211.NL80211_IFTYPE_P2P_DEVICE:
                typestr = 'P2P_DEVICE'

            iface_data['type'] = typestr

        if tb[nl80211.NL80211_ATTR_WIPHY]:
            wiphy_num = nla_get_u32(tb[nl80211.NL80211_ATTR_WIPHY])
            iface_data['wiphy'] = 'phy#{0}'.format(wiphy_num)

        if tb[nl80211.NL80211_ATTR_MAC]:
            mac_raw = nla_data(tb[nl80211.NL80211_ATTR_MAC])[:6]
            mac_address = ':'.join(format(x, '02x') for x in mac_raw)
            iface_data['mac'] = mac_address
            if (gnlh.cmd == nl80211.NL80211_CMD_NEW_STATION
                    and if_index == self.if_idx):
                # This is the BSSID that we're currently associated to
                self.bssid = mac_address

        if tb[nl80211.NL80211_ATTR_GENERATION]:
            generation = nla_get_u32(tb[nl80211.NL80211_ATTR_GENERATION])
            # Do not overwrite the generation for excessively large values
            if generation < 100:
                iface_data['generation'] = generation

        if tb[nl80211.NL80211_ATTR_WIPHY_TX_POWER_LEVEL]:
            iface_data['tx_power'] = nla_get_u32(
                tb[nl80211.NL80211_ATTR_WIPHY_TX_POWER_LEVEL]) / 100  # mW

        if tb[nl80211.NL80211_ATTR_CHANNEL_WIDTH]:
            iface_data['ch_width'] = nla_get_u32(
                tb[nl80211.NL80211_ATTR_CHANNEL_WIDTH])

        if tb[nl80211.NL80211_ATTR_CENTER_FREQ1]:
            iface_data['frequency'] = nla_get_u32(
                tb[nl80211.NL80211_ATTR_CENTER_FREQ1])

        # Station infos
        if tb[nl80211.NL80211_ATTR_STA_INFO]:
            # Need to unpack the data
            sinfo = dict(
                (i, None) for i in range(nl80211.NL80211_STA_INFO_MAX))
            rinfo = dict(
                (i, None) for i in range(nl80211.NL80211_STA_INFO_TX_BITRATE))

            # Extract data
            nla_parse_nested(sinfo, nl80211.NL80211_STA_INFO_MAX,
                             tb[nl80211.NL80211_ATTR_STA_INFO], None)

            # Extract info about signal strength (= quality)
            if sinfo[nl80211.NL80211_STA_INFO_SIGNAL]:
                iface_data['signal'] = 100 + \
                    nla_get_u8(sinfo[nl80211.NL80211_STA_INFO_SIGNAL])
                # Compute quality (formula found in iwinfo_nl80211.c and largely
                # simplified)
                iface_data['quality'] = iface_data['signal'] + 110
                iface_data['quality_max'] = 70

            # Extract info about negotiated bitrate
            if sinfo[nl80211.NL80211_STA_INFO_TX_BITRATE]:
                nla_parse_nested(rinfo, nl80211.NL80211_RATE_INFO_MAX,
                                 sinfo[nl80211.NL80211_STA_INFO_TX_BITRATE],
                                 None)
                if rinfo[nl80211.NL80211_RATE_INFO_BITRATE]:
                    iface_data['bitrate'] = nla_get_u16(
                        rinfo[nl80211.NL80211_RATE_INFO_BITRATE]) / 10

        # BSS info
        if tb[nl80211.NL80211_ATTR_BSS]:
            # Need to unpack the data
            binfo = dict((i, None) for i in range(nl80211.NL80211_BSS_MAX))
            nla_parse_nested(binfo, nl80211.NL80211_BSS_MAX,
                             tb[nl80211.NL80211_ATTR_BSS], None)

            # Parse BSS section (if complete)
            try:
                bss = parse_bss(binfo)

                # Remove duplicated information blocks
                if 'beacon_ies' in bss:
                    del bss['beacon_ies']
                if 'information_elements' in bss:
                    del bss['information_elements']
                if 'supported_rates' in bss:
                    del bss['supported_rates']

                # Convert timedelta objects for later JSON encoding
                for prop in bss:
                    if isinstance(bss[prop], datetime.timedelta):
                        bss[prop] = int(bss[prop].microseconds) / 1000

                # Append BSS data to general object
                iface_data = {**iface_data, **bss}
            except Exception as e:
                logger.warning("Obtaining BSS data failed: {}".format(e))
                pass

        # Append data to global structure
        self.iface_data[if_index] = iface_data
        return NL_SKIP
Example #6
0
def info_callback(msg, _):

    nlh = nlmsg_hdr(msg)
    gnlh = genlmsghdr(nlmsg_data(nlh))
    tb = dict((i, None) for i in range(NCSI_ATTR_MAX + 1))

    ret = genlmsg_parse(nlh, 0, tb, NCSI_ATTR_MAX, ncsi_policy)
    if ret != 0:
        reason = errmsg[abs(ret)]
        print("genlmsg_parse returned {}, {}".format(ret, reason))
        return ret

    if not NCSI_ATTR_PACKAGE_LIST in tb:
        print('No packages!')
        return -1

    rem = c_int()
    for nla in nla_for_each_nested(tb[NCSI_ATTR_PACKAGE_LIST], rem):
        ptb = dict()
        ret = nla_parse_nested(ptb, NCSI_PKG_ATTR_MAX, nla,
                               ncsi_package_policy)
        if ret < 0:
            print('Failed to parse package nest')
            return ret
        if NCSI_PKG_ATTR_ID in ptb:
            print('package {}'.format(nla_get_u32(ptb[NCSI_PKG_ATTR_ID])))
        else:
            print('package (with no id?)')
        if NCSI_PKG_ATTR_FORCED in ptb:
            print('this package is forced')
        print('----------')

        crem = c_int()
        for cnla in nla_for_each_nested(ptb[NCSI_PKG_ATTR_CHANNEL_LIST], crem):
            ctb = dict()
            ret = nla_parse_nested(ctb, NCSI_CHANNEL_ATTR_MAX, cnla,
                                   ncsi_channel_policy)
            if ret < 0:
                print('Failed to parse channel nest')
                return ret
            if NCSI_CHANNEL_ATTR_ID in ctb:
                channel = nla_get_u32(ctb[NCSI_CHANNEL_ATTR_ID])
                if NCSI_CHANNEL_ATTR_ACTIVE in ctb:
                    print('channel {} - active!'.format(channel))
                else:
                    print('channel {}'.format(channel))
                if NCSI_CHANNEL_ATTR_FORCED in ctb:
                    print('\tthis channel is forced')
            else:
                print('channel (with no id?)')
            if NCSI_CHANNEL_ATTR_VERSION_MAJOR in ctb:
                print('\tmajor version {}'.format(
                    nla_get_u32(ctb[NCSI_CHANNEL_ATTR_VERSION_MAJOR])))
            if NCSI_CHANNEL_ATTR_VERSION_MINOR in ctb:
                print('\tminor version {}'.format(
                    nla_get_u32(ctb[NCSI_CHANNEL_ATTR_VERSION_MINOR])))
            if NCSI_CHANNEL_ATTR_VERSION_STR in ctb:
                print('\tversion string {}'.format(
                    nla_get_string(ctb[NCSI_CHANNEL_ATTR_VERSION_STR])))
            if NCSI_CHANNEL_ATTR_LINK_STATE in ctb:
                print('\tlink state {}'.format(
                    nla_get_u32(ctb[NCSI_CHANNEL_ATTR_LINK_STATE])))
            if NCSI_CHANNEL_ATTR_VLAN_LIST in ctb:
                print('\tactive vlan ids:')
                rrem = c_int()
                vids = ctb[NCSI_CHANNEL_ATTR_VLAN_LIST]
                vid = nlattr(nla_data(vids))
                rrem.value = nla_len(vids)
                while nla_ok(vid, rrem):
                    print('\t\t{}'.format(nla_get_u16(vid)))
                    vid = nla_next(vid, rrem)

    return NL_SKIP