根据来自:
的代码
https://github.com/puzzlet/madwifi/blob/master/tools/wlanconfig.c#L565 struct iwreq
曾经从80211驱动程序(例如站点列表)中获取信息,但是https://elixir.bootlin.com/linux/v4.0/source/include/uapi/linux/wireless.h#L685成员iwr.u.data.length (struct iw_point)
表示__u16 length;
有局限性>具有65535字节的最大值,代表数据的大小,指向void __user *pointer;
。
我的下一个问题:如何通过iw_point正确传输数据,大于65535字节,(在Linux内核中是否有一些要求,例如IOCTL系统调用行为,或其他原因)标准化或基于驱动程序,我可以随意使用它,例如使用__u16 flags;
?)。
即如何标记void __user *pointer
指向大小大于65535的内存??
在struct iw_point
的标题注释中显示注释,该数据可以大于65535字节,但是如何处理呢?
/*
* For all data larger than 16 octets, we need to use a
* pointer to memory allocated in user space.
*/
struct iw_point
{
void __user *pointer; /* Pointer to the data (in user space) */
__u16 length; /* number of fields or size in bytes */
__u16 flags; /* Optional params */
};
使用struct iwreq的函数示例(必须看到前20行):
static void
list_stations(const char *ifname)
{
uint8_t buf[24 * 1024];
struct iwreq iwr;
uint8_t *cp;
int s, len;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0)
err(1, "socket(SOCK_DGRAM)");
(void) memset(&iwr, 0, sizeof(iwr));
(void) strncpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
iwr.u.data.pointer = (void *)buf;
iwr.u.data.length = sizeof(buf);
if (ioctl(s, IEEE80211_IOCTL_STA_INFO, &iwr) < 0)
errx(1, "unable to get station information");
len = iwr.u.data.length;
if (len < sizeof(struct ieee80211req_sta_info))
return;
close(s);
printf("%-17.17s %4s %4s %4s %4s %4s %5s %6s %7s %6s %7s %4s %5s %3s %8s %8s\n",
"ADDR",
"AID",
"CHAN",
"RATE",
"RSSI",
"DBM",
"IDLE",
"TXSEQ",
"TXFRAG",
"RXSEQ",
"RXFRAG",
"CAPS",
"ACAPS",
"ERP",
"STATE",
"MODE");
cp = buf;
do {
struct ieee80211req_sta_info *si;
uint8_t *vp;
si = (struct ieee80211req_sta_info *)cp;
vp = (u_int8_t *)(si+1);
printf("%s %4u %4d %3dM %4d %4d %5d %6d %7d %6d %7d %-4.4s %-5.5s %3x %8x %8s",
ieee80211_ntoa(si->isi_macaddr),
IEEE80211_AID(si->isi_associd),
ieee80211_mhz2ieee(si->isi_freq),
(si->isi_rates[si->isi_txrate] & IEEE80211_RATE_VAL) / 2,
si->isi_rssi,
rssi2dbm(si->isi_rssi),
si->isi_inact,
(si->isi_txseqs[0] & IEEE80211_SEQ_SEQ_MASK)
>> IEEE80211_SEQ_SEQ_SHIFT,
si->isi_txseqs[0] & IEEE80211_SEQ_FRAG_MASK,
(si->isi_rxseqs[0] & IEEE80211_SEQ_SEQ_MASK)
>> IEEE80211_SEQ_SEQ_SHIFT,
si->isi_rxseqs[0] & IEEE80211_SEQ_FRAG_MASK,
getcaps(si->isi_capinfo),
getathcaps(si->isi_athflags),
si->isi_erp,
si->isi_state,
getstamode(si->isi_opmode));
printies(vp, si->isi_ie_len, 24);
printf("\n");
if (si->isi_uapsd) {
printf(" UAPSD QoSInfo: 0x%02x, ",
si->isi_uapsd);
printf("(VO,VI,BE,BK) = (%d,%d,%d,%d), MaxSpLimit = %s\n",
WME_UAPSD_AC_ENABLED(WME_AC_VO, si->isi_uapsd) ? 1 : 0,
WME_UAPSD_AC_ENABLED(WME_AC_VI, si->isi_uapsd) ? 1 : 0,
WME_UAPSD_AC_ENABLED(WME_AC_BE, si->isi_uapsd) ? 1 : 0,
WME_UAPSD_AC_ENABLED(WME_AC_BK, si->isi_uapsd) ? 1 : 0,
WME_UAPSD_MAXSP(si->isi_uapsd) == 1 ? "2" :
WME_UAPSD_MAXSP(si->isi_uapsd) == 2 ? "4" :
WME_UAPSD_MAXSP(si->isi_uapsd) == 3 ? "6" : "NoLimit");
}
cp += si->isi_len;
len -= si->isi_len;
} while (len >= sizeof(struct ieee80211req_sta_info));
}