--- a/station.c +++ b/station.c @@ -29,13 +29,47 @@ enum plink_actions { PLINK_ACTION_BLOCK, }; +static void print_sta_bitrate(struct nlattr *nla, const char *name) +{ + struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1]; + + static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = { + [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 }, + [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 }, + [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 }, + [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG }, + [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG }, + }; + + if (!nla) + return; + + if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, nla, rate_policy)) { + fprintf(stderr, "failed to parse nested rate attributes!\n"); + } else { + int rate = 0; + printf("\n\t%s:\t", name); + if (rinfo[NL80211_RATE_INFO_BITRATE32]) + rate = nla_get_u32(rinfo[NL80211_RATE_INFO_BITRATE32]); + else if (rinfo[NL80211_RATE_INFO_BITRATE]) + rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]); + if (rate > 0) + printf("%d.%d MBit/s", rate / 10, rate % 10); + + if (rinfo[NL80211_RATE_INFO_MCS]) + printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS])); + if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH]) + printf(" 40Mhz"); + if (rinfo[NL80211_RATE_INFO_SHORT_GI]) + printf(" short GI"); + } +} static int print_sta_handler(struct nl_msg *msg, void *arg) { struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1]; - struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1]; char mac_addr[20], state_name[10], dev[20]; struct nl80211_sta_flag_update *sta_flags; static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = { @@ -47,6 +81,7 @@ static int print_sta_handler(struct nl_m [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 }, [NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 }, [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED }, + [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED }, [NL80211_STA_INFO_LLID] = { .type = NLA_U16 }, [NL80211_STA_INFO_PLID] = { .type = NLA_U16 }, [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 }, @@ -56,14 +91,6 @@ static int print_sta_handler(struct nl_m { .minlen = sizeof(struct nl80211_sta_flag_update) }, }; - static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = { - [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 }, - [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 }, - [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 }, - [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG }, - [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG }, - }; - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); @@ -119,28 +146,8 @@ static int print_sta_handler(struct nl_m printf("\n\tToffset:\t%lld us", (unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_T_OFFSET])); - if (sinfo[NL80211_STA_INFO_TX_BITRATE]) { - if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, - sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) { - fprintf(stderr, "failed to parse nested rate attributes!\n"); - } else { - int rate = 0; - printf("\n\ttx bitrate:\t"); - if (rinfo[NL80211_RATE_INFO_BITRATE32]) - rate = nla_get_u32(rinfo[NL80211_RATE_INFO_BITRATE32]); - else if (rinfo[NL80211_RATE_INFO_BITRATE]) - rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]); - if (rate > 0) - printf("%d.%d MBit/s", rate / 10, rate % 10); - - if (rinfo[NL80211_RATE_INFO_MCS]) - printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS])); - if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH]) - printf(" 40Mhz"); - if (rinfo[NL80211_RATE_INFO_SHORT_GI]) - printf(" short GI"); - } - } + print_sta_bitrate(sinfo[NL80211_STA_INFO_TX_BITRATE], "tx bitrate"); + print_sta_bitrate(sinfo[NL80211_STA_INFO_RX_BITRATE], "rx bitrate"); if (sinfo[NL80211_STA_INFO_LLID]) printf("\n\tmesh llid:\t%d",