Как передать данные через iw_point больше, чем 65535 байт? - PullRequest
0 голосов
/ 08 января 2019

Согласно коду от:
https://github.com/puzzlet/madwifi/blob/master/tools/wlanconfig.c#L565 struct iwreq используется для получения информации от драйвера 80211 (список станций в примере), но, iwr.u.data.length (struct iw_point) имеет ограничения, согласно https://elixir.bootlin.com/linux/v4.0/source/include/uapi/linux/wireless.h#L685 это член __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));
}
...