使用ioctl SIOCGIWSCAN进行wifi扫描

时间:2018-12-05 13:12:46

标签: ioctl

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

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

我似乎是一个很大的char []数据块,但后面一定有某种结构。

谢谢

2 个答案:

答案 0 :(得分:1)

回答第1部分,共2部分。

我已将完整答案分两部分发布,因为我碰到了SO字符数限制,试图将它一分为二!

注意,除了我的其他文章所包含的C ++修订版之外,在某个嵌入式设备堆栈上,我还必须在#include <sys/socket.h>之前添加#include <linux/wireless.h>。否则,编译器没有为sockaddr ...

定义

与其他许多Linux wifi查询/请求不同,SIOCGIWSCAN产生数据的“流”。请记住,“扫描”将检测范围内所有可用的wifi接入点,并返回大量信息。因此,数据没有固定大小,也没有直接转换为简单结构的方法。

解释并提供导致此问题的所有细节将花费很长时间,并且涉及大量代码。 (请注意,要在此处发布这么多的内容是一场斗争。)因此,这里有一个示例,说明如何仅解析您专门询问的数据。

以下示例的注释:

  • resultBuffer是指向char数组的指针,该数组已使用标志SIOCGIWSCAN(即1)填充了IW_DESCR_FLAG_DUMP的结果。
  • 已经解决了E2BIG错误的可能性,以便在流中返回大量数据(例如10个或更多访问点)的情况下,动态调整该缓冲区的大小。
  • wifiRequest是用于请求的iwreq结构。
  • weVersion是活动接口上的无线扩展驱动程序的版本(通过另一个先前的请求查询)

示例:

// Create and initialize an event stream
// binding the scan results buffer to it
struct iw_event_stream eventStream;
memset( &eventStream, 0, sizeof(struct iw_event_stream) );
eventStream.current = resultBuffer;
eventStream.end = &resultBuffer[ wifiRequest.u.data.length ];

// Loop though the stream, parsing each event, and gathering essids
// (i.e. access point names).  Note, iw_extract_event_stream is where 
// the real nastiness takes place...
struct iw_event event;
while( iw_extract_event_stream( &eventStream, &event, weVersion ) > 0 )
{
    if( event.cmd == SIOCGIWESSID )
    {
        // fetch the AP name via
        // (char *)event.u.essid.pointer and event.u.essid.length ...
    }
}

然后,这是大多数Linux发行版中包含的标准“ iwlist”实用程序后面的源代码的经过精简和略微修改的部分(请参阅:https://github.com/HewlettPackard/wireless-tools/blob/master/wireless_tools/iwlib.c)。我尝试将其缩减并清理,因为我发现可以使用该来源(或相关来源)中的许多示例,但是当涉及到这一点时,与仅仅复制和粘贴相比,我发现这比值得的麻烦更多所有这些(然后根据需要简单地打补丁/调整)。您可能希望将此隐藏在项目中的另一个文件中,而不是直接将其混合到您自己的代码中。

struct iw_event_stream {
    char *end;
    char *current;
    char *value;
};

// Type of headers we know about (basically union iwreq_data)
#define IW_HEADER_TYPE_NULL 0   // Not available
#define IW_HEADER_TYPE_CHAR 2   // char [IFNAMSIZ]
#define IW_HEADER_TYPE_UINT 4   // __u32
#define IW_HEADER_TYPE_FREQ 5   // struct iw_freq
#define IW_HEADER_TYPE_ADDR 6   // struct sockaddr
#define IW_HEADER_TYPE_POINT    8   // struct iw_point
#define IW_HEADER_TYPE_PARAM    9   // struct iw_param
#define IW_HEADER_TYPE_QUAL 10  // struct iw_quality

// Handling flags
// Most are not implemented. I just use them as a reminder of some
// cool features we might need one day ;-)
#define IW_DESCR_FLAG_NONE  0x0000  // Obvious
// Wrapper level flags
#define IW_DESCR_FLAG_DUMP  0x0001  // Not part of the dump command
#define IW_DESCR_FLAG_EVENT 0x0002  // Generate an event on SET
#define IW_DESCR_FLAG_RESTRICT  0x0004  // GET : request is ROOT only
                // SET : Omit payload from generated iwevent
#define IW_DESCR_FLAG_NOMAX 0x0008  // GET : no limit on request size
// Driver level flags
#define IW_DESCR_FLAG_WAIT  0x0100  // Wait for driver event

struct iw_ioctl_description
{
    __u8    header_type;        // NULL, iw_point or other
    __u8    token_type;     // Future
    __u16   token_size;     // Granularity of payload
    __u16   min_tokens;     // Min acceptable token number
    __u16   max_tokens;     // Max acceptable token number
    __u32   flags;          // Special handling of the request
};

// 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,
    },
    [SIOCGIWNAME    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_CHAR,
        .flags      = IW_DESCR_FLAG_DUMP,
    },
    [SIOCSIWNWID    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
        .flags      = IW_DESCR_FLAG_EVENT,
    },
    [SIOCGIWNWID    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
        .flags      = IW_DESCR_FLAG_DUMP,
    },
    [SIOCSIWFREQ    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_FREQ,
        .flags      = IW_DESCR_FLAG_EVENT,
    },
    [SIOCGIWFREQ    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_FREQ,
        .flags      = IW_DESCR_FLAG_DUMP,
    },
    [SIOCSIWMODE    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_UINT,
        .flags      = IW_DESCR_FLAG_EVENT,
    },
    [SIOCGIWMODE    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_UINT,
        .flags      = IW_DESCR_FLAG_DUMP,
    },
    [SIOCSIWSENS    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCGIWSENS    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCSIWRANGE   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_NULL,
    },
    [SIOCGIWRANGE   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = sizeof(struct iw_range),
        .flags      = IW_DESCR_FLAG_DUMP,
    },
    [SIOCSIWPRIV    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_NULL,
    },
    [SIOCGIWPRIV    - SIOCIWFIRST] = { // (handled directly by us)
        .header_type    = IW_HEADER_TYPE_NULL,
    },
    [SIOCSIWSTATS   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_NULL,
    },
    [SIOCGIWSTATS   - SIOCIWFIRST] = { // (handled directly by us)
        .header_type    = IW_HEADER_TYPE_NULL,
        .flags      = IW_DESCR_FLAG_DUMP,
    },
    [SIOCSIWSPY - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = sizeof(struct sockaddr),
        .max_tokens = IW_MAX_SPY,
    },
    [SIOCGIWSPY - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = sizeof(struct sockaddr) +
                  sizeof(struct iw_quality),
        .max_tokens = IW_MAX_SPY,
    },
    [SIOCSIWTHRSPY  - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = sizeof(struct iw_thrspy),
        .min_tokens = 1,
        .max_tokens = 1,
    },
    [SIOCGIWTHRSPY  - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = sizeof(struct iw_thrspy),
        .min_tokens = 1,
        .max_tokens = 1,
    },
    [SIOCSIWAP  - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_ADDR,
    },
    [SIOCGIWAP  - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_ADDR,
        .flags      = IW_DESCR_FLAG_DUMP,
    },
    [SIOCSIWMLME    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .min_tokens = sizeof(struct iw_mlme),
        .max_tokens = sizeof(struct iw_mlme),
    },
    [SIOCGIWAPLIST  - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = sizeof(struct sockaddr) +
                  sizeof(struct iw_quality),
        .max_tokens = IW_MAX_AP,
        .flags      = IW_DESCR_FLAG_NOMAX,
    },
    [SIOCSIWSCAN    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .min_tokens = 0,
        .max_tokens = sizeof(struct iw_scan_req),
    },
    [SIOCGIWSCAN    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_SCAN_MAX_DATA,
        .flags      = IW_DESCR_FLAG_NOMAX,
    },
    [SIOCSIWESSID   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_ESSID_MAX_SIZE + 1,
        .flags      = IW_DESCR_FLAG_EVENT,
    },
    [SIOCGIWESSID   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_ESSID_MAX_SIZE + 1,
        .flags      = IW_DESCR_FLAG_DUMP,
    },
    [SIOCSIWNICKN   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_ESSID_MAX_SIZE + 1,
    },
    [SIOCGIWNICKN   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_ESSID_MAX_SIZE + 1,
    },
// PATCH: MAKE ERROR THROWN WITHOUT THESE ARRAY ELEMENTS!!!
    [0x8B1E - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [0x8B1F - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
//
    [SIOCSIWRATE    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCGIWRATE    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCSIWRTS - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCGIWRTS - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCSIWFRAG    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCGIWFRAG    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCSIWTXPOW   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCGIWTXPOW   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCSIWRETRY   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCGIWRETRY   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCSIWENCODE  - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_ENCODING_TOKEN_MAX,
        .flags      = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,
    },
    [SIOCGIWENCODE  - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_ENCODING_TOKEN_MAX,
        .flags      = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,
    },
    [SIOCSIWPOWER   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCGIWPOWER   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCSIWMODUL   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCGIWMODUL   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCSIWGENIE   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_GENERIC_IE_MAX,
    },
    [SIOCGIWGENIE   - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_GENERIC_IE_MAX,
    },
    [SIOCSIWAUTH    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCGIWAUTH    - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_PARAM,
    },
    [SIOCSIWENCODEEXT - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .min_tokens = sizeof(struct iw_encode_ext),
        .max_tokens = sizeof(struct iw_encode_ext) +
                  IW_ENCODING_TOKEN_MAX,
    },
    [SIOCGIWENCODEEXT - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .min_tokens = sizeof(struct iw_encode_ext),
        .max_tokens = sizeof(struct iw_encode_ext) +
                  IW_ENCODING_TOKEN_MAX,
    },
    [SIOCSIWPMKSA - SIOCIWFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .min_tokens = sizeof(struct iw_pmksa),
        .max_tokens = sizeof(struct iw_pmksa),
    },
};

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,
    },
    [IWEVQUAL   - IWEVFIRST] = {
        .header_type    = IW_HEADER_TYPE_QUAL,
    },
    [IWEVCUSTOM - IWEVFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_CUSTOM_MAX,
    },
    [IWEVREGISTERED - IWEVFIRST] = {
        .header_type    = IW_HEADER_TYPE_ADDR,
    },
    [IWEVEXPIRED    - IWEVFIRST] = {
        .header_type    = IW_HEADER_TYPE_ADDR,
    },
    [IWEVGENIE  - IWEVFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_GENERIC_IE_MAX,
    },
    [IWEVMICHAELMICFAILURE  - IWEVFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = sizeof(struct iw_michaelmicfailure),
    },
    [IWEVASSOCREQIE - IWEVFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_GENERIC_IE_MAX,
    },
    [IWEVASSOCRESPIE    - IWEVFIRST] = {
        .header_type    = IW_HEADER_TYPE_POINT,
        .token_size = 1,
        .max_tokens = IW_GENERIC_IE_MAX,
    },
    [IWEVPMKIDCAND  - IWEVFIRST] = {
            .header_type    = IW_HEADER_TYPE_POINT,
            .token_size = 1,
            .max_tokens = sizeof(struct iw_pmkid_cand),
    },
};

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);
}

答案 1 :(得分:1)

回答第2部分,共2部分。进行了修订,以实现便捷/ C ++兼容性。

linuxwifistream.h

  <div class="dropdown-div">
    <div class="input-field">
      <select>
        <option value="1" class="dropdown-text"><a class="dropdown-text-default" data-url="#General">General</a></option>
        <option value="2"><a class="dropdown-text" data-url="#Option1">Option1</a></option>
        <option value="3"><a class="dropdown-text" data-url="#Option2">Option2</a></option>
        <option value="4"><a class="dropdown-text" data-url="#Option3">Option3</a></option>
        <option value="5"><a class="dropdown-text" data-url="#Option4">Option4</a></option>
      </select>
    </div>
  </div>


  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.99.0/js/materialize.min.js"></script>
  <script type="text/javascript">
  $(document).ready(function() {
    $('select').material_select();
  });
  </script>

linuxwifistream.cpp

#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