static struct nlattr * find_dump_kind(const struct nlmsghdr *n) { struct nlattr *tb1, *tb2[TCA_ACT_MAX + 1]; struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; struct nlattr *nla[TCAA_MAX + 1]; struct nlattr *kind; if (nlmsg_parse(n, sizeof(struct tcamsg), nla, TCAA_MAX, NULL) < 0) return NULL; tb1 = nla[TCA_ACT_TAB]; if (tb1 == NULL) return NULL; if (nla_parse(tb, TCA_ACT_MAX_PRIO, nla_data(tb1), NLMSG_ALIGN(nla_len(tb1)), NULL) < 0) return NULL; if (tb[1] == NULL) return NULL; if (nla_parse(tb2, TCA_ACT_MAX, nla_data(tb[1]), nla_len(tb[1]), NULL) < 0) return NULL; kind = tb2[TCA_ACT_KIND]; return kind; }
static int display_rx_statcs(struct nl_msg *msg, void *arg) { struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct nlattr *td[WL1271_TM_ATTR_MAX + 1]; struct wl1271_radio_rx_statcs *prms; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (!tb[NL80211_ATTR_TESTDATA]) { fprintf(stderr, "no data!\n"); return NL_SKIP; } nla_parse(td, WL1271_TM_ATTR_MAX, nla_data(tb[NL80211_ATTR_TESTDATA]), nla_len(tb[NL80211_ATTR_TESTDATA]), NULL); prms = (struct wl1271_radio_rx_statcs *) nla_data(td[WL1271_TM_ATTR_DATA]); printf("\n\tTotal number of pkts\t- %d\n\tAccepted pkts\t\t- %d\n\t" "FCS error pkts\t\t- %d\n\tAddress mismatch pkts\t- %d\n\t" "Average SNR\t\t- % d dBm\n\tAverage RSSI\t\t- % d dBm\n\n", prms->base_pkt_id, prms->rx_path_statcs.nbr_rx_valid_pkts, prms->rx_path_statcs.nbr_rx_fcs_err_pkts, prms->rx_path_statcs.nbr_rx_plcp_err_pkts, (signed short)prms->rx_path_statcs.ave_snr/8, (signed short)prms->rx_path_statcs.ave_rssi/8); return NL_SKIP; }
static int calib_valid_handler(struct nl_msg *msg, void *arg) { struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct nlattr *td[WL1271_TM_ATTR_MAX + 1]; struct wl1271_cmd_cal_p2g *prms; #if 0 int i; unsigned char *pc; #endif nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (!tb[NL80211_ATTR_TESTDATA]) { fprintf(stderr, "no data!\n"); return NL_SKIP; } nla_parse(td, WL1271_TM_ATTR_MAX, nla_data(tb[NL80211_ATTR_TESTDATA]), nla_len(tb[NL80211_ATTR_TESTDATA]), NULL); prms = (struct wl1271_cmd_cal_p2g *)nla_data(td[WL1271_TM_ATTR_DATA]); if (prms->radio_status) { fprintf(stderr, "Fail to calibrate ith radio status (%d)\n", (signed short)prms->radio_status); return 2; } #if 0 printf("%s> id %04x status %04x\ntest id %02x ver %08x len %04x=%d\n", __func__, prms->header.id, prms->header.status, prms->test.id, prms->ver, prms->len, prms->len); pc = (unsigned char *)prms->buf; printf("++++++++++++++++++++++++\n"); for (i = 0; i < prms->len; i++) { if (i%0xf == 0) printf("\n"); printf("%02x ", *(unsigned char *)pc); pc += 1; } printf("++++++++++++++++++++++++\n"); #endif if (prepare_nvs_file(prms, arg)) { fprintf(stderr, "Fail to prepare calibrated NVS file\n"); return 2; } #if 0 printf("\n\tThe NVS file (%s) is ready\n\tCopy it to %s and " "reboot the system\n\n", NEW_NVS_NAME, CURRENT_NVS_NAME); #endif return NL_SKIP; }
// valid interface callback handler static int iface_handler(struct nl_msg *msg, void *arg) { struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (tb_msg[NL80211_ATTR_WIPHY]) { char wiphy[IFNAMSIZ]; sprintf(wiphy, "phy%d", nla_get_u32(tb_msg[NL80211_ATTR_WIPHY])); // If selected physical interface matches the result, search for a monitor interface and copy the name if(strcmp(phy_name, wiphy) == 0) { if (tb_msg[NL80211_ATTR_IFTYPE] && tb_msg[NL80211_ATTR_IFNAME]) { // If the interface type is monitor if(nla_get_u32(tb_msg[NL80211_ATTR_IFTYPE]) == 6) strcpy(IF_name, nla_get_string(tb_msg[NL80211_ATTR_IFNAME])); } } } return NL_SKIP; }
static int zlib_decompress_setup(struct crypto_pcomp *tfm, void *params, unsigned int len) { struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); struct z_stream_s *stream = &ctx->decomp_stream; struct nlattr *tb[ZLIB_DECOMP_MAX + 1]; int ret = 0; ret = nla_parse(tb, ZLIB_DECOMP_MAX, params, len, NULL); if (ret) return ret; zlib_decomp_exit(ctx); ctx->decomp_windowBits = tb[ZLIB_DECOMP_WINDOWBITS] ? nla_get_u32(tb[ZLIB_DECOMP_WINDOWBITS]) : DEF_WBITS; stream->workspace = vzalloc(zlib_inflate_workspacesize()); if (!stream->workspace) return -ENOMEM; ret = zlib_inflateInit2(stream, ctx->decomp_windowBits); if (ret != Z_OK) { vfree(stream->workspace); stream->workspace = NULL; return -EINVAL; } return 0; }
static int nl80211_subscribe_cb(struct nl_msg *msg, void *arg) { struct nl80211_group_conveyor *cv = arg; struct nlattr **attr = nl80211_parse(msg); struct nlattr *mgrpinfo[CTRL_ATTR_MCAST_GRP_MAX + 1]; struct nlattr *mgrp; int mgrpidx; if (!attr[CTRL_ATTR_MCAST_GROUPS]) return NL_SKIP; nla_for_each_nested(mgrp, attr[CTRL_ATTR_MCAST_GROUPS], mgrpidx) { nla_parse(mgrpinfo, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mgrp), nla_len(mgrp), NULL); if (mgrpinfo[CTRL_ATTR_MCAST_GRP_ID] && mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME] && !strncmp(nla_data(mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME]), cv->name, nla_len(mgrpinfo[CTRL_ATTR_MCAST_GRP_NAME]))) { cv->id = nla_get_u32(mgrpinfo[CTRL_ATTR_MCAST_GRP_ID]); break; } }
int mac80211_get_coverageclass(char *interface) { struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct nl_msg *msg; struct genlmsghdr *gnlh; int phy; unsigned char coverage=0; phy = mac80211_get_phyidx_by_vifname(interface); if (phy == -1) return 0; msg = unl_genl_msg(&unl, NL80211_CMD_GET_WIPHY, false); NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, phy); if (unl_genl_request_single(&unl, msg, &msg) < 0) return 0; if (!msg) return 0; gnlh=nlmsg_data(nlmsg_hdr(msg)); nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (tb[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) { coverage = nla_get_u8(tb[NL80211_ATTR_WIPHY_COVERAGE_CLASS]); /* See handle_distance() for an explanation where the '450' comes from */ // printf("\tCoverage class: %d (up to %dm)\n", coverage, 450 * coverage); } // printf ("%d\n", coverage); nlmsg_free(msg); return coverage; nla_put_failure: nlmsg_free(msg); return 0; }
static int nl80211_iface_info_handler (struct nl_msg *msg, void *arg) { struct nl80211_iface_info *info = arg; struct genlmsghdr *gnlh = nlmsg_data (nlmsg_hdr (msg)); struct nlattr *tb[NL80211_ATTR_MAX + 1]; if (nla_parse (tb, NL80211_ATTR_MAX, genlmsg_attrdata (gnlh, 0), genlmsg_attrlen (gnlh, 0), NULL) < 0) return NL_SKIP; if (!tb[NL80211_ATTR_IFTYPE]) return NL_SKIP; switch (nla_get_u32 (tb[NL80211_ATTR_IFTYPE])) { case NL80211_IFTYPE_ADHOC: info->mode = NM_802_11_MODE_ADHOC; break; case NL80211_IFTYPE_AP: info->mode = NM_802_11_MODE_AP; break; case NL80211_IFTYPE_STATION: info->mode = NM_802_11_MODE_INFRA; break; } return NL_SKIP; }
int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) { struct ath6kl *ar = wiphy_priv(wiphy); struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; int err, buf_len; void *buf; err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, ath6kl_tm_policy); if (err) return err; if (!tb[ATH6KL_TM_ATTR_CMD]) return -EINVAL; switch (nla_get_u32(tb[ATH6KL_TM_ATTR_CMD])) { case ATH6KL_TM_CMD_TCMD: if (!tb[ATH6KL_TM_ATTR_DATA]) return -EINVAL; buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len); return 0; break; default: return -EOPNOTSUPP; } }
/* ----------------GET CMD WITH INT ARG REPLY-------------------- */ static int print_reply_rx_count_data(struct nl_msg *msg, void *arg) { struct nlattr *tb_msg[NLNPI_ATTR_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); unsigned int count[3]; nla_parse(tb_msg, NLNPI_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (tb_msg[NLNPI_ATTR_REPLY_DATA]) { if (nla_len(tb_msg[NLNPI_ATTR_REPLY_DATA]) == 12) { memcpy(count, nla_data(tb_msg[NLNPI_ATTR_REPLY_DATA]), sizeof(count)); printf ("ret: reg value: rx_end_count=%d rx_err_end_count=%d fcs_fail_count=%d :end\n", count[0], count[1], count[2]); } else { printf("ret: Invild len %d :end\n", nla_len(tb_msg[NLNPI_ATTR_REPLY_DATA])); } } else { printf("ret: Failed to get result! :end\n"); } return NL_SKIP; }
int LLStatsCommand::handleResponse(WifiEvent &reply) { ALOGI("Got a LLStats message from Driver"); unsigned i=0; u32 status; WifiVendorCommand::handleResponse(reply); // Parse the vendordata and get the attribute switch(mSubcmd) { case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR: { struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1]; nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX, (struct nlattr *)mVendorData, mDataLen, NULL); ALOGI("Resp mask : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK])); ALOGI("STOP resp : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP])); mClearRspParams.stats_clear_rsp_mask = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]); mClearRspParams.stop_rsp = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]); break; } default : ALOGE("%s: Wrong LLStats subcmd received %d", __func__, mSubcmd); } return NL_SKIP; }
static void get_wifi_iface_stats(wifi_iface_stat *stats, struct nlattr **tb_vendor) { struct nlattr *wmmInfo; wifi_wmm_ac_stat *pWmmStats; int i=0, rem; stats->beacon_rx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX]); stats->mgmt_rx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX]); stats->mgmt_action_rx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX]); stats->mgmt_action_tx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX]); stats->rssi_mgmt = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT]); stats->rssi_data = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA]); stats->rssi_ack = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK]); ALOGI("STATS IFACE: beaconRx : %u ", stats->beacon_rx); ALOGI("STATS IFACE: mgmtRx %u ", stats->mgmt_rx); ALOGI("STATS IFACE: mgmtActionRx %u ", stats->mgmt_action_rx); ALOGI("STATS IFACE: mgmtActionTx %u ", stats->mgmt_action_tx); ALOGI("STATS IFACE: rssiMgmt %u ", stats->rssi_mgmt); ALOGI("STATS IFACE: rssiData %u ", stats->rssi_data); ALOGI("STATS IFACE: rssiAck %u ", stats->rssi_ack); for (wmmInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]); nla_ok(wmmInfo, rem); wmmInfo = nla_next(wmmInfo, &(rem))) { struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1]; pWmmStats = (wifi_wmm_ac_stat *) ((u8 *)stats->ac + (i * sizeof(wifi_wmm_ac_stat))); nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(wmmInfo), nla_len(wmmInfo), NULL); get_wifi_wmm_ac_stat(pWmmStats, tb2); } }
static void get_wifi_peer_info(wifi_peer_info *stats, struct nlattr **tb_vendor) { u32 i = 0, len = 0; int rem; wifi_rate_stat * pRateStats; struct nlattr *rateInfo; stats->type = (wifi_peer_type)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE]); len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]); len = ((sizeof(stats->peer_mac_address) <= len) ? sizeof(stats->peer_mac_address) : len); memcpy((void *)&stats->peer_mac_address[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]), len); stats->capabilities = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES]); stats->num_rate = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]); ALOGI("STATS PEER_ALL : numPeers %u", stats->type); ALOGI("STATS PEER_ALL : peerMacAddress %0x:%0x:%0x:%0x:%0x:%0x ", stats->peer_mac_address[0], stats->peer_mac_address[1], stats->peer_mac_address[2],stats->peer_mac_address[3], stats->peer_mac_address[4],stats->peer_mac_address[5]); ALOGI("STATS PEER_ALL : capabilities %0x", stats->capabilities); ALOGI("STATS PEER_ALL : numRate %u", stats->num_rate); for (rateInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO]); nla_ok(rateInfo, rem); rateInfo = nla_next(rateInfo, &(rem))) { struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1]; pRateStats = (wifi_rate_stat *) ((u8 *)stats->rate_stats + (i++ * sizeof(wifi_rate_stat))); nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(rateInfo), nla_len(rateInfo), NULL); get_wifi_rate_stat(pRateStats, tb2); } }
static int dump_mgmt_frame(struct nl_msg *msg, void *arg) { struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (tb_msg[NL80211_ATTR_WIPHY_FREQ]) { uint32_t freq = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_FREQ]); printf("freq %u MHz\n", freq); } if (tb_msg[NL80211_ATTR_RX_SIGNAL_DBM]) { /* nl80211_send_mgmt sends signed dBm value as u32 */ int dbm = nla_get_u32(tb_msg[NL80211_ATTR_RX_SIGNAL_DBM]); printf("rssi %d dBm\n", dbm); } if (tb_msg[NL80211_ATTR_FRAME]) { int len = nla_len(tb_msg[NL80211_ATTR_FRAME]); uint8_t *data = nla_data(tb_msg[NL80211_ATTR_FRAME]); iw_hexdump("mgmt", data, len); } return 0; }
int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) { struct wl1271 *wl = hw->priv; struct nlattr *tb[WL1271_TM_ATTR_MAX + 1]; int err; err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy); if (err) return err; if (!tb[WL1271_TM_ATTR_CMD_ID]) return -EINVAL; switch (nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID])) { case WL1271_TM_CMD_TEST: return wl1271_tm_cmd_test(wl, tb); case WL1271_TM_CMD_INTERROGATE: return wl1271_tm_cmd_interrogate(wl, tb); case WL1271_TM_CMD_CONFIGURE: return wl1271_tm_cmd_configure(wl, tb); case WL1271_TM_CMD_SET_PLT_MODE: return wl1271_tm_cmd_set_plt_mode(wl, tb); case WL1271_TM_CMD_RECOVER: return wl1271_tm_cmd_recover(wl, tb); case WL1271_TM_CMD_GET_MAC: return wl12xx_tm_cmd_get_mac(wl, tb); default: return -EOPNOTSUPP; } }
static int ac_kmod_valid_handler(struct nl_msg* msg, void* data) { struct nlattr* tb_msg[NLSMARTCAPWAP_ATTR_MAX + 1]; struct genlmsghdr* gnlh = nlmsg_data(nlmsg_hdr(msg)); nla_parse(tb_msg, NLSMARTCAPWAP_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); return ac_kmod_event_handler(gnlh, tb_msg, data); }
/* Process one complete nfnetlink message. */ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { const struct nfnl_callback *nc; const struct nfnetlink_subsystem *ss; int type, err; #if 0 if (security_netlink_recv(skb, CAP_NET_ADMIN)) return -EPERM; #endif /* All the messages must at least contain nfgenmsg */ if (nlh->nlmsg_len < NLMSG_SPACE(sizeof(struct nfgenmsg))) return 0; type = nlh->nlmsg_type; replay: ss = nfnetlink_get_subsys(type); if (!ss) { #ifdef CONFIG_MODULES nfnl_unlock(); request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); nfnl_lock(); ss = nfnetlink_get_subsys(type); if (!ss) #endif return -EINVAL; } nc = nfnetlink_find_client(type, ss); if (!nc) return -EINVAL; { int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type); u_int16_t attr_count = ss->cb[cb_id].attr_count; struct nlattr *cda[attr_count+1]; if (likely(nlh->nlmsg_len >= min_len)) { struct nlattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); err = nla_parse(cda, attr_count, attr, attrlen, ss->cb[cb_id].policy); if (err < 0) return err; } else return -EINVAL; err = nc->call(nfnl, skb, nlh, (struct nfattr **)cda); if (err == -EAGAIN) goto replay; return err; } }
int SoftapController::linkDumpCbHandler(struct nl_msg *msg, void *arg) { struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct genlmsghdr *gnlh = (genlmsghdr *)nlmsg_data(nlmsg_hdr(msg)); struct nlattr *bss[NL80211_BSS_MAX + 1]; int *sta_freq = (int *)arg; // bah - cpp doesn't support C99 named initializers. do it manually memset(&link_bss_policy, 0, sizeof(link_bss_policy)); link_bss_policy[NL80211_BSS_TSF].type = NLA_U64; link_bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32; //link_bss_policy[NL80211_BSS_BSSID] = { }; link_bss_policy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16; link_bss_policy[NL80211_BSS_CAPABILITY].type = NLA_U16; //link_bss_policy[NL80211_BSS_INFORMATION_ELEMENTS] = { }; link_bss_policy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32; link_bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8; link_bss_policy[NL80211_BSS_STATUS].type = NLA_U32; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (!tb[NL80211_ATTR_BSS]) { LOGD("bss info missing!"); return NL_SKIP; } if (nla_parse_nested(bss, NL80211_BSS_MAX, tb[NL80211_ATTR_BSS], link_bss_policy)) { LOGD("failed to parse nested attributes!"); return NL_SKIP; } if (!bss[NL80211_BSS_BSSID]) return NL_SKIP; if (!bss[NL80211_BSS_STATUS]) return NL_SKIP; switch (nla_get_u32(bss[NL80211_BSS_STATUS])) { case NL80211_BSS_STATUS_ASSOCIATED: break; case NL80211_BSS_STATUS_AUTHENTICATED: case NL80211_BSS_STATUS_IBSS_JOINED: default: return NL_SKIP; } /* only in the assoc case do we want more info from station get */ if (bss[NL80211_BSS_FREQUENCY]) { *sta_freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); LOGD("sta freq: %d", *sta_freq); } return NL_SKIP; }
static int __tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd, struct tipc_nl_compat_msg *msg) { int err; struct sk_buff *doit_buf; struct sk_buff *trans_buf; struct nlattr **attrbuf; struct genl_info info; trans_buf = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!trans_buf) return -ENOMEM; attrbuf = kmalloc_array(tipc_genl_family.maxattr + 1, sizeof(struct nlattr *), GFP_KERNEL); if (!attrbuf) { err = -ENOMEM; goto trans_out; } doit_buf = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!doit_buf) { err = -ENOMEM; goto attrbuf_out; } memset(&info, 0, sizeof(info)); info.attrs = attrbuf; rtnl_lock(); err = (*cmd->transcode)(cmd, trans_buf, msg); if (err) goto doit_out; err = nla_parse(attrbuf, tipc_genl_family.maxattr, (const struct nlattr *)trans_buf->data, trans_buf->len, NULL, NULL); if (err) goto doit_out; doit_buf->sk = msg->dst_sk; err = (*cmd->doit)(doit_buf, &info); doit_out: rtnl_unlock(); kfree_skb(doit_buf); attrbuf_out: kfree(attrbuf); trans_out: kfree_skb(trans_buf); return err; }
static int print_iface_handler(struct nl_msg *msg, void *arg) { struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct nlattr *tb_msg[NL802154_ATTR_MAX + 1]; unsigned int *wpan_phy = arg; const char *indent = ""; nla_parse(tb_msg, NL802154_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (wpan_phy && tb_msg[NL802154_ATTR_WPAN_PHY]) { unsigned int thiswpan_phy = nla_get_u32(tb_msg[NL802154_ATTR_WPAN_PHY]); indent = "\t"; if (*wpan_phy != thiswpan_phy) printf("phy#%d\n", thiswpan_phy); *wpan_phy = thiswpan_phy; } if (tb_msg[NL802154_ATTR_IFNAME]) printf("%sInterface %s\n", indent, nla_get_string(tb_msg[NL802154_ATTR_IFNAME])); else printf("%sUnnamed/non-netdev interface\n", indent); if (tb_msg[NL802154_ATTR_IFINDEX]) printf("%s\tifindex %d\n", indent, nla_get_u32(tb_msg[NL802154_ATTR_IFINDEX])); if (tb_msg[NL802154_ATTR_WPAN_DEV]) printf("%s\twpan_dev 0x%llx\n", indent, (unsigned long long)nla_get_u64(tb_msg[NL802154_ATTR_WPAN_DEV])); if (tb_msg[NL802154_ATTR_EXTENDED_ADDR]) printf("%s\textended_addr 0x%016" PRIx64 "\n", indent, le64toh(nla_get_u64(tb_msg[NL802154_ATTR_EXTENDED_ADDR]))); if (tb_msg[NL802154_ATTR_SHORT_ADDR]) printf("%s\tshort_addr 0x%04x\n", indent, le16toh(nla_get_u16(tb_msg[NL802154_ATTR_SHORT_ADDR]))); if (tb_msg[NL802154_ATTR_PAN_ID]) printf("%s\tpan_id 0x%04x\n", indent, le16toh(nla_get_u16(tb_msg[NL802154_ATTR_PAN_ID]))); if (tb_msg[NL802154_ATTR_IFTYPE]) printf("%s\ttype %s\n", indent, iftype_name(nla_get_u32(tb_msg[NL802154_ATTR_IFTYPE]))); if (tb_msg[NL802154_ATTR_MAX_FRAME_RETRIES]) printf("%s\tmax_frame_retries %d\n", indent, nla_get_s8(tb_msg[NL802154_ATTR_MAX_FRAME_RETRIES])); if (tb_msg[NL802154_ATTR_MIN_BE]) printf("%s\tmin_be %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_MIN_BE])); if (tb_msg[NL802154_ATTR_MAX_BE]) printf("%s\tmax_be %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_MAX_BE])); if (tb_msg[NL802154_ATTR_MAX_CSMA_BACKOFFS]) printf("%s\tmax_csma_backoffs %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_MAX_CSMA_BACKOFFS])); if (tb_msg[NL802154_ATTR_LBT_MODE]) printf("%s\tlbt %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_LBT_MODE])); if (tb_msg[NL802154_ATTR_ACKREQ_DEFAULT]) printf("%s\tackreq_default %d\n", indent, nla_get_u8(tb_msg[NL802154_ATTR_ACKREQ_DEFAULT])); return NL_SKIP; }
static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params, unsigned int len) { struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); struct z_stream_s *stream = &ctx->comp_stream; struct nlattr *tb[ZLIB_COMP_MAX + 1]; int window_bits, mem_level; size_t workspacesize; int ret; ret = nla_parse(tb, ZLIB_COMP_MAX, params, len, NULL); if (ret) return ret; zlib_comp_exit(ctx); window_bits = tb[ZLIB_COMP_WINDOWBITS] ? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS]) : MAX_WBITS; mem_level = tb[ZLIB_COMP_MEMLEVEL] ? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL]) : DEF_MEM_LEVEL; workspacesize = zlib_deflate_workspacesize(window_bits, mem_level); stream->workspace = vmalloc(workspacesize); if (!stream->workspace) return -ENOMEM; memset(stream->workspace, 0, workspacesize); ret = zlib_deflateInit2(stream, tb[ZLIB_COMP_LEVEL] ? nla_get_u32(tb[ZLIB_COMP_LEVEL]) : Z_DEFAULT_COMPRESSION, tb[ZLIB_COMP_METHOD] ? nla_get_u32(tb[ZLIB_COMP_METHOD]) : Z_DEFLATED, tb[ZLIB_COMP_WINDOWBITS] ? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS]) : MAX_WBITS, tb[ZLIB_COMP_MEMLEVEL] ? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL]) : DEF_MEM_LEVEL, tb[ZLIB_COMP_STRATEGY] ? nla_get_u32(tb[ZLIB_COMP_STRATEGY]) : Z_DEFAULT_STRATEGY); if (ret != Z_OK) { vfree(stream->workspace); stream->workspace = NULL; return -EINVAL; } return 0; }
/** * Parse Generic Netlink message including attributes * @arg nlh Pointer to Netlink message header * @arg hdrlen Length of user header * @arg tb Array to store parsed attributes * @arg maxtype Maximum attribute id expected * @arg policy Attribute validation policy * * Verifies the validity of the Netlink and Generic Netlink headers using * genlmsg_valid_hdr() and calls nla_parse() on the message payload to * parse eventual attributes. * * @par Example: * @code * struct nlattr *attrs[MY_TYPE_MAX+1]; * * if ((err = genlsmg_parse(nlmsg_nlh(msg), sizeof(struct my_hdr), attrs, * MY_TYPE_MAX, attr_policy)) < 0) * // ERROR * @endcode * * @see genlmsg_valid_hdr() * @see genlmsg_validate() * @see nla_parse() * * @return 0 on success or a negative error code. */ int genlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy) { struct genlmsghdr *ghdr; if (!genlmsg_valid_hdr(nlh, hdrlen)) return -NLE_MSG_TOOSHORT; ghdr = nlmsg_data(nlh); return nla_parse(tb, maxtype, genlmsg_attrdata(ghdr, hdrlen), genlmsg_attrlen(ghdr, hdrlen), policy); }
static int parse_reply (struct nl_msg *msg, void *arg) { struct nlmsghdr *n = nlmsg_hdr (msg); struct nlattr *tb[XFRMA_MAX + 1]; struct xfrm_userpolicy_info *xpinfo = NULL; if (n->nlmsg_type != XFRM_MSG_NEWPOLICY) { g_warning ("msg type %d not NEWPOLICY", n->nlmsg_type); return NL_SKIP; } /* Netlink message header is followed by 'struct xfrm_userpolicy_info' and * then the attributes. */ if (!nlmsg_valid_hdr (n, sizeof (struct xfrm_userpolicy_info))) { g_warning ("msg too short"); return -NLE_MSG_TOOSHORT; } xpinfo = nlmsg_data (n); if (nla_parse (tb, XFRMA_MAX, nlmsg_attrdata (n, sizeof (struct xfrm_userpolicy_info)), nlmsg_attrlen (n, sizeof (struct xfrm_userpolicy_info)), NULL) < 0) { g_warning ("failed to parse attributes"); return NL_SKIP; } if (tb[XFRMA_TMPL]) { int attrlen = nla_len (tb[XFRMA_TMPL]); struct xfrm_user_tmpl *list = nla_data (tb[XFRMA_TMPL]); int i; xfrm_selector_print (&xpinfo->sel); for (i = 0; i < attrlen / sizeof (struct xfrm_user_tmpl); i++) { struct xfrm_user_tmpl *tmpl = &list[i]; char buf[INET6_ADDRSTRLEN]; g_print (" tmpl "); inet_ntop (tmpl->family, (gpointer) &tmpl->saddr, buf, sizeof (buf)); g_print ("src %s ", buf); inet_ntop (tmpl->family, &tmpl->id.daddr, buf, sizeof (buf)); g_print ("dst %s\n", buf); } } return NL_OK; }
int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) { struct ath6kl *ar = wiphy_priv(wiphy); struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; int err, buf_len, reply_len; struct sk_buff *skb; void *buf; err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, ath6kl_tm_policy); if (err) return err; if (!tb[ATH6KL_TM_ATTR_CMD]) return -EINVAL; switch (nla_get_u32(tb[ATH6KL_TM_ATTR_CMD])) { case ATH6KL_TM_CMD_TCMD: if (!tb[ATH6KL_TM_ATTR_DATA]) return -EINVAL; buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len); return 0; break; case ATH6KL_TM_CMD_RX_REPORT: if (!tb[ATH6KL_TM_ATTR_DATA]) return -EINVAL; buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); reply_len = nla_total_size(ATH6KL_TM_DATA_MAX_LEN); skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); if (!skb) return -ENOMEM; err = ath6kl_tm_rx_report(ar, buf, buf_len, skb); if (err < 0) { kfree_skb(skb); return err; } return cfg80211_testmode_reply(skb); default: return -EOPNOTSUPP; } }
//scan netlink messages are nested (and may even be multipart) (see nl80211.c line 2591: nl80211_send_bss) int CNL80211::parseNlScanResult(nl_msg * msg) { struct nlattr * attr_buffer[NL80211_ATTR_MAX + 1]; struct nlmsghdr * msg_hdr = nlmsg_hdr(msg); struct genlmsghdr * msg_header = (struct genlmsghdr *) nlmsg_data(msg_hdr); struct nlattr * bss_buffer[NL80211_BSS_MAX + 1]; //bss = basic service set ScanResult scanresult; //This is the struct to check the validity of the attributes. See enum nl80211_bss struct nla_policy bss_policy[NL80211_BSS_MAX + 1]; bss_policy[NL80211_BSS_TSF].type = NLA_U64; bss_policy[NL80211_BSS_FREQUENCY].type = NLA_U32; bss_policy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16; bss_policy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32; bss_policy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8; if (msg_hdr->nlmsg_flags & NLM_F_MULTI) qDebug() << "netlink: Mutlipart message"; //Parse the complete message nla_parse(attr_buffer, NL80211_ATTR_MAX, genlmsg_attrdata(msg_header, 0), genlmsg_attrlen(msg_header, 0), NULL); if (!attr_buffer[NL80211_ATTR_BSS]) { //Check if BSS return NL_SKIP; } //Parse the nested attributes. this is where the scan results are if (nla_parse_nested(bss_buffer, NL80211_BSS_MAX, attr_buffer[NL80211_ATTR_BSS], bss_policy)) { return NL_SKIP; } if (!bss_buffer[NL80211_BSS_BSSID]) return NL_SKIP; scanresult.bssid = libnutcommon::MacAddress((ether_addr*)(bss_buffer[NL80211_BSS_BSSID])); scanresult.signal.bssid = scanresult.bssid; if (bss_buffer[NL80211_BSS_FREQUENCY]) scanresult.freq = nla_get_u32(bss_buffer[NL80211_BSS_FREQUENCY]); if (bss_buffer[NL80211_BSS_SIGNAL_MBM]) { scanresult.signal.type = WSR_RCPI; scanresult.signal.quality.value = nla_get_u32(bss_buffer[NL80211_BSS_SIGNAL_MBM])/100; } if (bss_buffer[NL80211_BSS_SIGNAL_UNSPEC]) { scanresult.signal.type = WSR_UNKNOWN; scanresult.signal.quality.value = nla_get_u8(bss_buffer[NL80211_BSS_SIGNAL_UNSPEC]); } // if (bss_buffer[NL80211_BSS_INFORMATION_ELEMENTS]) // print_ies(nla_data(bss_buffer[NL80211_BSS_INFORMATION_ELEMENTS]), // nla_len(bss_buffer[NL80211_BSS_INFORMATION_ELEMENTS]), // params->unknown, params->type); m_scanResults.push_back(scanresult); return NL_SKIP; }
static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy, int len) { int nested_len = nla_len(nla) - NLA_ALIGN(len); if (nested_len < 0) return -EINVAL; if (nested_len >= nla_attr_size(0)) return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len), nested_len, policy); memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); return 0; }
static int cb_kmod_create_iface(struct nl_msg* msg, void* data) { struct nlattr* tb_msg[NLSMARTCAPWAP_ATTR_MAX + 1]; struct genlmsghdr* gnlh = nlmsg_data(nlmsg_hdr(msg)); uint32_t* ifindex = (uint32_t*)data; nla_parse(tb_msg, NLSMARTCAPWAP_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (tb_msg[NLSMARTCAPWAP_ATTR_IFPHY_INDEX]) { *ifindex = nla_get_u32(tb_msg[NLSMARTCAPWAP_ATTR_IFPHY_INDEX]); } return NL_SKIP; }
static int event_handler(struct nl_msg *msg, void *arg) { struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct nlattr *tb[NL80211_ATTR_MAX + 1]; int cmd = gnlh->cmd; uint8_t *pos; int i; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); switch (gnlh->cmd) { case NL80211_CMD_FRAME: if (tb[NL80211_ATTR_FRAME] && nla_len(tb[NL80211_ATTR_FRAME])) { pos = nla_data(tb[NL80211_ATTR_FRAME]); if (*(pos + 24) == 0x20) { switch (*(pos + 25)) { case MPATH_PREQ: printf("Path Request Frame "); break; case MPATH_PREP: printf("Path Reply Frame "); break; case MPATH_PERR: printf("Path Error Frame "); break; } printf("from %02x:%02x:%02x:%02x:%02x:%02x\n", *(pos + 10), *(pos + 11), *(pos + 12), *(pos + 13), *(pos + 14), *(pos + 15)); } printf("----------\n"); printf("frame hexdump: "); for (i=0; i<nla_len(tb[NL80211_ATTR_FRAME]); i++) { if (!(i%20)) printf("\n"); printf("%02x ", *pos++); } printf("\n----------\n\n"); } break; case NL80211_CMD_NEW_STATION: printf("NL80211_CMD_NEW_STATION :)\n"); break; default: printf("Ignored event\n"); break; } return NL_SKIP; }
int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, struct netlink_callback *cb, void *data, int len) { struct nlattr *tb[IWL_TM_ATTR_MAX]; struct iwl_priv *priv = hw->priv; int result; u32 cmd; if (cb->args[3]) { /* offset by 1 since commands start at 0 */ cmd = cb->args[3] - 1; } else { result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, iwl_testmode_gnl_msg_policy); if (result) { IWL_DEBUG_INFO(priv, "Error parsing the gnl message : %d\n", result); return result; } /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ if (!tb[IWL_TM_ATTR_COMMAND]) { IWL_DEBUG_INFO(priv, "Error finding testmode command type\n"); return -ENOMSG; } cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); cb->args[3] = cmd + 1; } /* in case multiple accesses to the device happens */ mutex_lock(&priv->shrd->mutex); switch (cmd) { case IWL_TM_CMD_APP2DEV_READ_TRACE: IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); result = iwl_testmode_trace_dump(hw, tb, skb, cb); break; case IWL_TM_CMD_APP2DEV_DUMP_SRAM: IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n"); result = iwl_testmode_sram_dump(hw, tb, skb, cb); break; default: result = -EINVAL; break; } mutex_unlock(&priv->shrd->mutex); return result; }
static int protocol_feature_handler(struct nl_msg *msg, void *arg) { u32 *feat = arg; struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); if (tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]) *feat = nla_get_u32(tb_msg[NL80211_ATTR_PROTOCOL_FEATURES]); return NL_SKIP; }