⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iw-json.c.svn-base

📁 嵌入式无线路由系统openwrt的web配置工具
💻 SVN-BASE
字号:
/*
 * iw-info. Outputs wireless interface list in JSON format.
 *
 * Based on Wireless Tools, see 
 * <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html/>
 *
 * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
 * Copyright (C) 2008 OpenRB.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 1 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __user
#define __user
#endif

#ifndef IW_QUAL_RCPI
#define IW_QUAL_RCPI 0x80
#endif

#define KILO 1e3
#define MEGA 1e6
#define GIGA 1e9
#define IW_NUM_OPER_MODE 7
#define PROC_NET_WIRELESS "/proc/net/wireless"
#define LOG10_MAGIC 1.25892541179

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <sys/types.h>
#include <linux/types.h>
#include <net/ethernet.h>
#include <wireless.h>

typedef struct iw_statistics iwstats;
typedef struct iw_range iwrange;
typedef struct iw_param iwparam;
typedef struct iw_freq iwfreq;
typedef struct iw_quality iwqual;
typedef struct iw_priv_args iwprivargs;
typedef struct sockaddr sockaddr;

typedef struct wireless_config {
  char name[IFNAMSIZ + 1];
  int has_nwid;
  iwparam nwid;
  int has_freq;
  double freq;
  int freq_flags;
  int has_key;
  unsigned char key[IW_ENCODING_TOKEN_MAX];
  int key_size;
  int key_flags;
  int has_essid;
  int essid_on;
  char essid[IW_ESSID_MAX_SIZE + 1];
  int has_mode;
  int mode;
} wireless_config;

typedef struct wireless_info {
  struct wireless_config b;

  int has_sens;
  iwparam sens;
  int has_nickname;
  char nickname[IW_ESSID_MAX_SIZE + 1];
  int has_ap_addr;
  sockaddr ap_addr;
  int has_bitrate;
  iwparam bitrate;
  int has_power;
  iwparam power;

  int has_txpower;
  iwparam txpower;

  int has_stats;
  iwstats stats;
  int has_range;
  iwrange	range;
} wireless_info;

const char * const iw_operation_mode[] = {
  "auto",
  "adhoc",
  "sta",
  "ap",
  "repeater",
  "secondary",
  "monitor",
  "unknown"
};

inline int iw_get_ext(int skfd, const char * ifname, int request, struct iwreq * pwrq) {
  strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
  return(ioctl(skfd, request, pwrq));
}

inline int iw_ether_cmp(const struct ether_addr* eth1, const struct ether_addr* eth2) {
 return memcmp(eth1, eth2, sizeof(*eth1));
}

inline char * iw_get_ifname(char * name, int nsize, char * buf) {
  char * end;

  while (isspace(*buf)) {
    buf++;
  }
  
  end = strstr(buf, ": ");
  if((end == NULL) || (((end - buf) + 1) > nsize)) {
    return NULL;
  }

  memcpy(name, buf, (end - buf));
  name[end - buf] = '\0';

  return end;
}

int iw_get_range_info(int skfd,  const char * ifname, iwrange * range) {
  struct iwreq wrq;
  char buffer[sizeof(iwrange) * 2];

  /* Cleanup */
  bzero(buffer, sizeof(buffer));

  wrq.u.data.pointer = (caddr_t) buffer;
  wrq.u.data.length = sizeof(buffer);
  wrq.u.data.flags = 0;
  if (iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0) {
    return -1;
  }

  memcpy((char *) range, buffer, sizeof(iwrange));
  return 0;
}

int iw_get_stats(int skfd, const char * ifname, iwstats * stats, const iwrange * range) {
  struct iwreq wrq;
  wrq.u.data.pointer = (caddr_t) stats;
  wrq.u.data.length = sizeof(struct iw_statistics);
  wrq.u.data.flags = 1;
  strncpy(wrq.ifr_name, ifname, IFNAMSIZ);

  if (iw_get_ext(skfd, ifname, SIOCGIWSTATS, &wrq) < 0) {
    return -1;
  }
  
  return 0;
}

int iw_sockets_open(void) {
  static const int families[] = {
    AF_INET, AF_IPX, AF_AX25, AF_APPLETALK
  };
  unsigned int i;
  int sock;

  for(i = 0; i < sizeof(families)/sizeof(int); ++i) {
    sock = socket(families[i], SOCK_DGRAM, 0);
    if(sock >= 0) {
      return sock;
    }
  }

  return -1;
}

double iw_freq2float(const iwfreq * in) {
  int i;
  double res = (double) in->m;
  for(i = 0; i < in->e; i++) {
    res *= 10;
  }
  return res;
}

int iw_channel_to_freq(int channel, double * pfreq, const struct iw_range * range) {
 int has_freq = 0;
 int k;

  /* Check if the driver support only channels or if it has frequencies */
  for(k = 0; k < range->num_frequency; k++) {
    if((range->freq[k].e != 0) || (range->freq[k].m > (int) KILO)) {
      has_freq = 1;
    }	
  }
  
  if (!has_freq) {
    return -1;
  }

  /* Find the correct frequency in the list */
  for(k = 0; k < range->num_frequency; k++) {
    if(range->freq[k].i == channel) {
      *pfreq = iw_freq2float(&(range->freq[k]));
      return channel;
	   }
  }

  return -2;
}

int iw_mwatt2dbm(int in) {
  double fin = (double) in;
  int res = 0;

  while (fin > 10.0) {
    res += 10;
    fin /= 10.0;
  }
  while(fin > 1.000001) {
    res += 1;
    fin /= LOG10_MAGIC;
  }

  return res;
}

int iw_get_basic_config(int skfd, const char * ifname, wireless_config * info) {
  struct iwreq wrq;
  memset((char *) info, 0, sizeof(struct wireless_config));

  /* Get wireless name */
  if (iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) {
    return -1;
  }
  else {
    strncpy(info->name, wrq.u.name, IFNAMSIZ);
    info->name[IFNAMSIZ] = '\0';
  }

  /* Get network ID */
  if (iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) >= 0) {
    info->has_nwid = 1;
    memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam));
  }

  /* Get frequency / channel */
  if (iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0) {
    info->has_freq = 1;
    info->freq = iw_freq2float(&(wrq.u.freq));
    info->freq_flags = wrq.u.freq.flags;
  }

  /* Get encryption information */
  wrq.u.data.pointer = (caddr_t) info->key;
  wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
  wrq.u.data.flags = 0;
  if (iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0) {
    info->has_key = 1;
    info->key_size = wrq.u.data.length;
    info->key_flags = wrq.u.data.flags;
  }

  /* Get ESSID */
  wrq.u.essid.pointer = (caddr_t) info->essid;
  wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
  wrq.u.essid.flags = 0;
  if (iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) >= 0) {
    info->has_essid = 1;
    info->essid_on = wrq.u.data.flags;
  }

  /* Get operation mode */
  if (iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0) {
    info->has_mode = 1;
    /* Note : event->u.mode is unsigned, no need to check <= 0 */
    if (wrq.u.mode < IW_NUM_OPER_MODE) {
      info->mode = wrq.u.mode;
    }
    else {
      info->mode = IW_NUM_OPER_MODE;
    }
  }

  return 0;
}

void iw_print_escaped(const char * raw) {
  int i, len = strlen(raw);
  char c;
  putchar('"');
  
  for (i = 0; i < len; i++) {
    c = raw[i];
    if (c > 31 && c < 127) {
      if (c == '"' || c == '\\') {
        putchar('\\');
      }
      putchar(c);
    }
  }
  
  putchar('"');
}

int get_info(int skfd, char * ifname, struct wireless_info * info) {
  struct iwreq wrq;

  memset((char *) info, 0, sizeof(struct wireless_info));

  if (iw_get_basic_config(skfd, ifname, &(info->b)) < 0) {
    struct ifreq ifr;

    strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
    return (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0) ? -ENODEV : -ENOTSUP;
  }

  if(iw_get_range_info(skfd, ifname, &(info->range)) >= 0) {
    info->has_range = 1;
  }

  /* Get AP address */
  if (iw_get_ext(skfd, ifname, SIOCGIWAP, &wrq) >= 0) {
    info->has_ap_addr = 1;
    memcpy(&(info->ap_addr), &(wrq.u.ap_addr), sizeof (sockaddr));
  }

  /* Get bit rate */
  if (iw_get_ext(skfd, ifname, SIOCGIWRATE, &wrq) >= 0) {
    info->has_bitrate = 1;
    memcpy(&(info->bitrate), &(wrq.u.bitrate), sizeof(iwparam));
  }

  /* Get stats */
  if (iw_get_stats(skfd, ifname, &(info->stats), &info->range) >= 0) {
    info->has_stats = 1;
  }

  /* Get NickName */
  wrq.u.essid.pointer = (caddr_t) info->nickname;
  wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
  wrq.u.essid.flags = 0;

  if (iw_get_ext(skfd, ifname, SIOCGIWNICKN, &wrq) >= 0 && wrq.u.data.length > 1) {
    info->has_nickname = 1;
  }

  /* tx power */
  if (info->has_range && iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) {
    info->has_txpower = 1;
    memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam));
  }

  return 0;
}

char * get_ieee(const char * bname) {
  char buf[ IFNAMSIZ + 1];
  char * res;
  
  int i = 1, s = 9;
  buf[0] = '"';
  
  while (i < (IFNAMSIZ - 2) && bname[s] ) {
    buf[i++] = bname[s++];
  }
  
  if (i == 1) {
    sprintf (buf, "null");
  }
  else {
    buf[i++] = '"';
    buf[i] = '\0';
  }
  
  res = (char *) malloc(strlen(buf) + 1);
  return strcpy(res, buf);
}

void display_info(struct wireless_info * info, char * ifname) {
  printf("\"%s\": {\"ieee\": %s", ifname, get_ieee(info->b.name) );

  /* Display ESSID */
  if (info->b.has_essid && info->b.essid_on) {
    printf(", \"ssid\": ");
    iw_print_escaped(info->b.essid);
  }

  /* Display NickName */
  if (info->has_nickname && info->nickname) {
    printf(", \"nickname\": ");
    iw_print_escaped(info->nickname);
  }

  /* Display the current mode of operation */
  if (info->b.has_mode) {
    printf(", \"mode\": \"%s\"", iw_operation_mode[info->b.mode]);
  }

  /* Display frequency / channel */
  if (info->b.has_freq) {
    double freq = info->b.freq;
    int channel = -1;
    
    if (info->has_range && (freq < KILO)) {
      channel = iw_channel_to_freq((int) freq, &freq, &info->range);
    }
    
    printf(", \"freq\": %g", (freq < KILO ? freq : freq / MEGA));
  }

  /* Display the address of the current Access Point */
  if (info->has_ap_addr) {
    if ((info->b.has_mode) && (info->b.mode == IW_MODE_ADHOC)) {
      printf(", \"cell\": ");
    }
    else {
      printf(", \"ap\": ");
    }
    
    const struct ether_addr ether_zero = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
    const struct ether_addr ether_bcast = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
    const struct ether_addr * ether_wap = (const struct ether_addr *) info->ap_addr.sa_data;

    if (!iw_ether_cmp(ether_wap, &ether_zero) || !iw_ether_cmp(ether_wap, &ether_bcast)) {
      printf("null");
    }
    else {
      printf("\"%02X:%02X:%02X:%02X:%02X:%02X\"",
             ether_wap->ether_addr_octet[0], ether_wap->ether_addr_octet[1], ether_wap->ether_addr_octet[2],
             ether_wap->ether_addr_octet[3], ether_wap->ether_addr_octet[4], ether_wap->ether_addr_octet[5]);
    }
  }

  /* Display the currently used/set bit-rate */
  if (info->has_bitrate) {
    printf(", \"bitrate\": %.2f", info->bitrate.value / MEGA);
  }

  /* Display the Transmit Power */
  if (info->has_txpower && !info->txpower.disabled) {
    int dbm;

    if (info->txpower.flags & IW_TXPOW_MWATT) {
      dbm = iw_mwatt2dbm(info->txpower.value);
    }
    else {
      dbm = info->txpower.value;
    }
      
    printf(", \"txpower\": %d", dbm);
  }

  /* Display encryption information */
  if (info->b.has_key) {
    if ((info->b.key_flags & IW_ENCODE_DISABLED) || (info->b.key_size == 0)) {
      printf(", \"security\": null");
    }
    else {
      if (info->b.key_flags & IW_ENCODE_RESTRICTED) {
        printf(", \"security\": \"restricted\"");
      }
      else if (info->b.key_flags & IW_ENCODE_OPEN) {
        printf(", \"security\": \"open\"");
      }
    }
  }

  /* Display statistics */
  if (info->has_stats) {
    if (info->has_range && ((info->stats.qual.level != 0) || (info->stats.qual.updated & (IW_QUAL_DBM | IW_QUAL_RCPI)))) {
      if (!(info->stats.qual.updated & IW_QUAL_QUAL_INVALID)) {
	       printf(", \"quality\": %d, \"maxquality\": %d", info->stats.qual.qual, info->range.max_qual.qual);
      }
    }
    else {
      printf(", \"quality\": %d", info->stats.qual.qual);
    }
  }

  printf("}");
}

int print_info(int skfd, char * ifname) {
  struct wireless_info info;
  int rc = get_info(skfd, ifname, &info);

  if (!rc) {
    display_info(&info, ifname);
  }

  return rc;
}

int main(void) {
  char buff[1024];
  FILE * fh;
  int skfd, first = 1;

  /* Create a channel to the NET kernel. */
  if ((skfd = iw_sockets_open()) < 0) {
    perror("socket");
    exit(-1);
  }
  
  printf("{");
  
  fh = fopen(PROC_NET_WIRELESS, "r");

  if (fh != NULL) {
    /* Success : use data from /proc/net/wireless */
    fgets(buff, sizeof(buff), fh);
    fgets(buff, sizeof(buff), fh);

    /* Read each device line */
    while (fgets(buff, sizeof(buff), fh)) {
      char name[IFNAMSIZ + 1];
      char *s;

      if ((buff[0] == '\0') || (buff[1] == '\0')) {
        continue;
      }

      s = iw_get_ifname(name, sizeof(name), buff);
      if (s) {
        if (first) {
          first = 0;
        }
        else {
          printf(", ");        
        }

        print_info(skfd, name);
        
      }
    }

    fclose(fh);
  }
  
  printf("}");
  
  close(skfd);
  return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -