Skip to main content
 首页 » 编程设计

linux之使用 ioctl SIOCGIWSCAN 进行 wifi 扫描

2025年05月04日25虾米哥

我想知道是否有人可以告诉我如何解释 wifi 扫描结果中的数据

if (-1 != (status = ioctl(handle, SIOCGIWSCAN, &data))) 
{ 
    data.u.data.pointer = ? what struct is this ? 
} 

它看起来像是一个很大的 char [] blob 数据,但背后一定有某种结构。

谢谢

请您参考如下方法:

回答第 2 部分(共 2 部分)。为了方便/C++ 兼容性而进行了修改。

linuxwifistream.h

#ifndef LINUX_WIFI_STREAM_H 
#define LINUX_WIFI_STREAM_H 
 
#include <linux/wireless.h> 
 
#define IW_DESCR_FLAG_NONE        0x0000 
#define IW_DESCR_FLAG_DUMP        0x0001 
#define IW_DESCR_FLAG_EVENT       0x0002 
#define IW_DESCR_FLAG_RESTRICT    0x0004 
#define IW_DESCR_FLAG_NOMAX       0x0008 
#define IW_DESCR_FLAG_WAIT        0x0100 
 
struct iw_event_stream { 
    char *end; 
    char *current; 
    char *value; 
}; 
 
int iw_extract_event_stream( 
    struct iw_event_stream *stream, struct iw_event *iwe, int we_version ); 
 
#endif // LINUX_WIFI_STREAM_H 

linuxwifistream.cpp

#include "linuxwifistream.h" 
 
#define IW_HEADER_TYPE_NULL    0     
#define IW_HEADER_TYPE_CHAR    2     
#define IW_HEADER_TYPE_UINT    4     
#define IW_HEADER_TYPE_FREQ    5     
#define IW_HEADER_TYPE_ADDR    6     
#define IW_HEADER_TYPE_POINT    8    
#define IW_HEADER_TYPE_PARAM    9    
#define IW_HEADER_TYPE_QUAL    10    
 
struct iw_ioctl_description 
{ 
    __u8    header_type;         
    __u8    token_type;         
    __u16    token_size;        
    __u16    min_tokens;        
    __u16    max_tokens;        
    __u32    flags;             
}; 
 
// Fill Missing Defines 
#ifndef SIOCSIWMODUL 
#define SIOCSIWMODUL    0x8B2E        /* set Modulations settings */ 
#endif 
#ifndef SIOCGIWMODUL 
#define SIOCGIWMODUL    0x8B2F        /* get Modulations settings */ 
#endif 
 
const struct iw_ioctl_description standard_ioctl_descr[] = { 
    [SIOCSIWCOMMIT    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_NULL, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWNAME    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_CHAR, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = IW_DESCR_FLAG_DUMP, 
    }, 
    [SIOCSIWNWID    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = IW_DESCR_FLAG_EVENT, 
    }, 
    [SIOCGIWNWID    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = IW_DESCR_FLAG_DUMP, 
    }, 
    [SIOCSIWFREQ    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_FREQ, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = IW_DESCR_FLAG_EVENT, 
    }, 
    [SIOCGIWFREQ    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_FREQ, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = IW_DESCR_FLAG_DUMP, 
    }, 
    [SIOCSIWMODE    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_UINT, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = IW_DESCR_FLAG_EVENT, 
    }, 
    [SIOCGIWMODE    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_UINT, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = IW_DESCR_FLAG_DUMP, 
    }, 
    [SIOCSIWSENS    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWSENS    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCSIWRANGE    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_NULL, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWRANGE    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = sizeof(struct iw_range), 
        .flags          = IW_DESCR_FLAG_DUMP, 
    }, 
    [SIOCSIWPRIV    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_NULL, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWPRIV    - SIOCIWFIRST] = { // (handled directly by us) 
        .header_type    = IW_HEADER_TYPE_NULL, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCSIWSTATS    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_NULL, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWSTATS    - SIOCIWFIRST] = { // (handled directly by us) 
        .header_type    = IW_HEADER_TYPE_NULL, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = IW_DESCR_FLAG_DUMP, 
    }, 
    [SIOCSIWSPY    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = sizeof(struct sockaddr), 
        .min_tokens     = 0, 
        .max_tokens     = IW_MAX_SPY, 
        .flags          = 0, 
    }, 
    [SIOCGIWSPY    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = sizeof(struct sockaddr) + 
                          sizeof(struct iw_quality), 
        .min_tokens     = 0, 
        .max_tokens     = IW_MAX_SPY, 
        .flags          = 0, 
    }, 
    [SIOCSIWTHRSPY    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = sizeof(struct iw_thrspy), 
        .min_tokens     = 1, 
        .max_tokens     = 1, 
        .flags          = 0, 
    }, 
    [SIOCGIWTHRSPY    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = sizeof(struct iw_thrspy), 
        .min_tokens     = 1, 
        .max_tokens     = 1, 
        .flags          = 0, 
    }, 
    [SIOCSIWAP    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_ADDR, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWAP    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_ADDR, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = IW_DESCR_FLAG_DUMP, 
    }, 
    [SIOCSIWMLME    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = sizeof(struct iw_mlme), 
        .max_tokens     = sizeof(struct iw_mlme), 
        .flags          = 0, 
    }, 
    [SIOCGIWAPLIST    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = sizeof(struct sockaddr) + 
                          sizeof(struct iw_quality), 
        .min_tokens     = 0, 
        .max_tokens     = IW_MAX_AP, 
        .flags          = IW_DESCR_FLAG_NOMAX, 
    }, 
    [SIOCSIWSCAN    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = sizeof(struct iw_scan_req), 
        .flags          = 0, 
    }, 
    [SIOCGIWSCAN    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_SCAN_MAX_DATA, 
        .flags          = IW_DESCR_FLAG_NOMAX, 
    }, 
    [SIOCSIWESSID    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_ESSID_MAX_SIZE + 1, 
        .flags          = IW_DESCR_FLAG_EVENT, 
    }, 
    [SIOCGIWESSID    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_ESSID_MAX_SIZE + 1, 
        .flags          = IW_DESCR_FLAG_DUMP, 
    }, 
    [SIOCSIWNICKN    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_ESSID_MAX_SIZE + 1, 
        .flags          = 0, 
    }, 
    [SIOCGIWNICKN    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_ESSID_MAX_SIZE + 1, 
        .flags          = 0, 
    }, 
// PATCH: MAKE ERROR THROWN WITHOUT THESE ARRAY ELEMENTS!!! 
    [0x8B1E    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [0x8B1F    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
// 
    [SIOCSIWRATE    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWRATE    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCSIWRTS    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWRTS    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCSIWFRAG    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWFRAG    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCSIWTXPOW    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWTXPOW    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCSIWRETRY    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWRETRY    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCSIWENCODE    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_ENCODING_TOKEN_MAX, 
        .flags          = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT, 
    }, 
    [SIOCGIWENCODE    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_ENCODING_TOKEN_MAX, 
        .flags          = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT, 
    }, 
    [SIOCSIWPOWER    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWPOWER    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCSIWMODUL    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWMODUL    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCSIWGENIE    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_GENERIC_IE_MAX, 
        .flags          = 0, 
    }, 
    [SIOCGIWGENIE    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_GENERIC_IE_MAX, 
        .flags          = 0, 
    }, 
    [SIOCSIWAUTH    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCGIWAUTH    - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_PARAM, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [SIOCSIWENCODEEXT - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = sizeof(struct iw_encode_ext), 
        .max_tokens     = sizeof(struct iw_encode_ext) + 
                          IW_ENCODING_TOKEN_MAX, 
        .flags          = 0, 
    }, 
    [SIOCGIWENCODEEXT - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = sizeof(struct iw_encode_ext), 
        .max_tokens     = sizeof(struct iw_encode_ext) + 
                          IW_ENCODING_TOKEN_MAX, 
        .flags          = 0, 
    }, 
    [SIOCSIWPMKSA - SIOCIWFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = sizeof(struct iw_pmksa), 
        .max_tokens     = sizeof(struct iw_pmksa), 
        .flags          = 0, 
    }, 
}; 
 
const unsigned int standard_ioctl_num = (sizeof(standard_ioctl_descr) / 
                        sizeof(struct iw_ioctl_description)); 
 
// 
// Meta-data about all the additional standard Wireless Extension events 
// we know about. 
// 
// 
const struct iw_ioctl_description standard_event_descr[] = { 
    [IWEVTXDROP    - IWEVFIRST] = { 
        .header_type    = IW_HEADER_TYPE_ADDR, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [IWEVQUAL    - IWEVFIRST] = { 
        .header_type    = IW_HEADER_TYPE_QUAL, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [IWEVCUSTOM    - IWEVFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_CUSTOM_MAX, 
        .flags          = 0, 
    }, 
    [IWEVREGISTERED    - IWEVFIRST] = { 
        .header_type    = IW_HEADER_TYPE_ADDR, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [IWEVEXPIRED    - IWEVFIRST] = { 
        .header_type    = IW_HEADER_TYPE_ADDR, 
        .token_type     = 0, 
        .token_size     = 0, 
        .min_tokens     = 0, 
        .max_tokens     = 0, 
        .flags          = 0, 
    }, 
    [IWEVGENIE    - IWEVFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_GENERIC_IE_MAX, 
        .flags          = 0, 
    }, 
    [IWEVMICHAELMICFAILURE    - IWEVFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = sizeof(struct iw_michaelmicfailure), 
        .flags          = 0, 
    }, 
    [IWEVASSOCREQIE    - IWEVFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_GENERIC_IE_MAX, 
        .flags          = 0, 
    }, 
    [IWEVASSOCRESPIE    - IWEVFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = IW_GENERIC_IE_MAX, 
        .flags          = 0, 
    }, 
    [IWEVPMKIDCAND    - IWEVFIRST] = { 
        .header_type    = IW_HEADER_TYPE_POINT, 
        .token_type     = 0, 
        .token_size     = 1, 
        .min_tokens     = 0, 
        .max_tokens     = sizeof(struct iw_pmkid_cand), 
        .flags          = 0, 
    }, 
}; 
 
const unsigned int standard_event_num = (sizeof(standard_event_descr) / 
    sizeof(struct iw_ioctl_description)); 
 
// Size (in bytes) of various events 
const int event_type_size[] = { 
    IW_EV_LCP_PK_LEN,    // IW_HEADER_TYPE_NULL 
    0, 
    IW_EV_CHAR_PK_LEN,    // IW_HEADER_TYPE_CHAR 
    0, 
    IW_EV_UINT_PK_LEN,    // IW_HEADER_TYPE_UINT 
    IW_EV_FREQ_PK_LEN,    // IW_HEADER_TYPE_FREQ 
    IW_EV_ADDR_PK_LEN,    // IW_HEADER_TYPE_ADDR 
    0, 
    IW_EV_POINT_PK_LEN,    // Without variable payload 
    IW_EV_PARAM_PK_LEN,    // IW_HEADER_TYPE_PARAM 
    IW_EV_QUAL_PK_LEN,    // IW_HEADER_TYPE_QUAL * 
}; 
 
int iw_extract_event_stream( iw_event_stream *stream,    /* Stream of events */ 
            struct iw_event *    iwe,    /* Extracted event */ 
            int            we_version) 
{ 
  const struct iw_ioctl_description *    descr = NULL; 
  int        event_type = 0; 
  unsigned int    event_len = 1;        /* Invalid */ 
  char *    pointer; 
  /* Don't "optimise" the following variable, it will crash */ 
  unsigned    cmd_index;        /* *MUST* be unsigned */ 
 
  /* Check for end of stream */ 
  if((stream->current + IW_EV_LCP_PK_LEN) > stream->end) 
    return(0); 
 
#ifdef DEBUG 
  printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n", 
     stream->current, stream->value, stream->end); 
#endif 
 
  /* Extract the event header (to get the event id). 
   * Note : the event may be unaligned, therefore copy... */ 
  memcpy((char *) iwe, stream->current, IW_EV_LCP_PK_LEN); 
 
#ifdef DEBUG 
  printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n", 
     iwe->cmd, iwe->len); 
#endif 
 
  /* Check invalid events */ 
  if(iwe->len <= IW_EV_LCP_PK_LEN) 
    return(-1); 
 
  /* Get the type and length of that event */ 
  if(iwe->cmd <= SIOCIWLAST) 
    { 
      cmd_index = iwe->cmd - SIOCIWFIRST; 
      if(cmd_index < standard_ioctl_num) 
    descr = &(standard_ioctl_descr[cmd_index]); 
    } 
  else 
    { 
      cmd_index = iwe->cmd - IWEVFIRST; 
      if(cmd_index < standard_event_num) 
    descr = &(standard_event_descr[cmd_index]); 
    } 
  if(descr != NULL) 
    event_type = descr->header_type; 
  /* Unknown events -> event_type=0 => IW_EV_LCP_PK_LEN */ 
  event_len = event_type_size[event_type]; 
  /* Fixup for earlier version of WE */ 
  if((we_version <= 18) && (event_type == IW_HEADER_TYPE_POINT)) 
    event_len += IW_EV_POINT_OFF; 
 
  /* Check if we know about this event */ 
  if(event_len <= IW_EV_LCP_PK_LEN) 
    { 
      /* Skip to next event */ 
      stream->current += iwe->len; 
      return(2); 
    } 
  event_len -= IW_EV_LCP_PK_LEN; 
 
  /* Set pointer on data */ 
  if(stream->value != NULL) 
    pointer = stream->value;            /* Next value in event */ 
  else 
    pointer = stream->current + IW_EV_LCP_PK_LEN;    /* First value in event */ 
 
#ifdef DEBUG 
  printf("DBG - event_type = %d, event_len = %d, pointer = %p\n", 
     event_type, event_len, pointer); 
#endif 
 
  /* Copy the rest of the event (at least, fixed part) */ 
  if((pointer + event_len) > stream->end) 
    { 
      /* Go to next event */ 
      stream->current += iwe->len; 
      return(-2); 
    } 
  /* Fixup for WE-19 and later : pointer no longer in the stream */ 
  /* Beware of alignement. Dest has local alignement, not packed */ 
  if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT)) 
    memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, 
       pointer, event_len); 
  else 
    memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len); 
 
  /* Skip event in the stream */ 
  pointer += event_len; 
 
  /* Special processing for iw_point events */ 
  if(event_type == IW_HEADER_TYPE_POINT) 
    { 
      /* Check the length of the payload */ 
      unsigned int    extra_len = iwe->len - (event_len + IW_EV_LCP_PK_LEN); 
      if(extra_len > 0) 
    { 
      /* Set pointer on variable part (warning : non aligned) */ 
      iwe->u.data.pointer = pointer; 
 
      /* Check that we have a descriptor for the command */ 
      if(descr == NULL) 
        /* Can't check payload -> unsafe... */ 
        iwe->u.data.pointer = NULL;    /* Discard paylod */ 
      else 
        { 
          /* Those checks are actually pretty hard to trigger, 
           * because of the checks done in the kernel... */ 
 
          unsigned int    token_len = iwe->u.data.length * descr->token_size; 
 
          /* Ugly fixup for alignement issues. 
           * If the kernel is 64 bits and userspace 32 bits, 
           * we have an extra 4+4 bytes. 
           * Fixing that in the kernel would break 64 bits userspace. */ 
          if((token_len != extra_len) && (extra_len >= 4)) 
        { 
          __u16        alt_dlen = *((__u16 *) pointer); 
          unsigned int    alt_token_len = alt_dlen * descr->token_size; 
          if((alt_token_len + 8) == extra_len) 
            { 
#ifdef DEBUG 
              printf("DBG - alt_token_len = %d\n", alt_token_len); 
#endif 
              /* Ok, let's redo everything */ 
              pointer -= event_len; 
              pointer += 4; 
              /* Dest has local alignement, not packed */ 
              memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, 
                 pointer, event_len); 
              pointer += event_len + 4; 
              iwe->u.data.pointer = pointer; 
              token_len = alt_token_len; 
            } 
        } 
 
          /* Discard bogus events which advertise more tokens than 
           * what they carry... */ 
          if(token_len > extra_len) 
        iwe->u.data.pointer = NULL;    /* Discard paylod */ 
          /* Check that the advertised token size is not going to 
           * produce buffer overflow to our caller... */ 
          if((iwe->u.data.length > descr->max_tokens) 
         && !(descr->flags & IW_DESCR_FLAG_NOMAX)) 
        iwe->u.data.pointer = NULL;    /* Discard paylod */ 
          /* Same for underflows... */ 
          if(iwe->u.data.length < descr->min_tokens) 
        iwe->u.data.pointer = NULL;    /* Discard paylod */ 
#ifdef DEBUG 
          printf("DBG - extra_len = %d, token_len = %d, token = %d, max = %d, min = %d\n", 
             extra_len, token_len, iwe->u.data.length, descr->max_tokens, descr->min_tokens); 
#endif 
        } 
    } 
      else 
    /* No data */ 
    iwe->u.data.pointer = NULL; 
 
      /* Go to next event */ 
      stream->current += iwe->len; 
    } 
  else 
    { 
      /* Ugly fixup for alignement issues. 
       * If the kernel is 64 bits and userspace 32 bits, 
       * we have an extra 4 bytes. 
       * Fixing that in the kernel would break 64 bits userspace. */ 
      if((stream->value == NULL) 
     && ((((iwe->len - IW_EV_LCP_PK_LEN) % event_len) == 4) 
         || ((iwe->len == 12) && ((event_type == IW_HEADER_TYPE_UINT) || 
                      (event_type == IW_HEADER_TYPE_QUAL))) )) 
    { 
#ifdef DEBUG 
      printf("DBG - alt iwe->len = %d\n", iwe->len - 4); 
#endif 
      pointer -= event_len; 
      pointer += 4; 
      /* Beware of alignement. Dest has local alignement, not packed */ 
      memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len); 
      pointer += event_len; 
    } 
 
      /* Is there more value in the event ? */ 
      if((pointer + event_len) <= (stream->current + iwe->len)) 
    /* Go to next value */ 
    stream->value = pointer; 
      else 
    { 
      /* Go to next event */ 
      stream->value = NULL; 
      stream->current += iwe->len; 
    } 
    } 
  return(1); 
}