nexmon – Rev 1

Subversion Repositories:
Rev:
/*
 *      Wireless Tools
 *
 *              Jean II - HPLB 97->99 - HPL 99->07
 *
 * Common header for the Wireless Extension library...
 *
 * This file is released under the GPL license.
 *     Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com>
 */

#ifndef IWLIB_H
#define IWLIB_H

/*#include "CHANGELOG.h"*/

/***************************** INCLUDES *****************************/

/* Standard headers */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <math.h>
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>              /* gethostbyname, getnetbyname */
#include <net/ethernet.h>       /* struct ether_addr */
#include <sys/time.h>           /* struct timeval */
#include <unistd.h>

/* This is our header selection. Try to hide the mess and the misery :-(
 * Don't look, you would go blind ;-)
 * Note : compatibility with *old* distributions has been removed,
 * you will need Glibc 2.2 and older to compile (which means 
 * Mandrake 8.0, Debian 2.3, RH 7.1 or older).
 */

/* Set of headers proposed by Dr. Michael Rietz <rietz@mail.amps.de>, 27.3.2 */
#include <net/if_arp.h>         /* For ARPHRD_ETHER */
#include <sys/socket.h>         /* For AF_INET & struct sockaddr */
#include <netinet/in.h>         /* For struct sockaddr_in */
#include <netinet/if_ether.h>

/* Fixup to be able to include kernel includes in userspace.
 * Basically, kill the sparse annotations... Jean II */
#ifndef __user
#define __user
#endif

#include <linux/types.h>                /* for "caddr_t" et al          */

/* Glibc systems headers are supposedly less problematic than kernel ones */
#include <sys/socket.h>                 /* for "struct sockaddr" et al  */
#include <net/if.h>                     /* for IFNAMSIZ and co... */

/* Private copy of Wireless extensions (in this directoty) */
#include "wireless.h"

/* Make gcc understant that when we say inline, we mean it.
 * I really hate when the compiler is trying to be more clever than me,
 * because in this case gcc is not able to figure out functions with a
 * single call site, so not only I have to tag those functions inline
 * by hand, but then it refuse to inline them properly.
 * Total saving for iwevent : 150B = 0.7%.
 * Fortunately, in gcc 3.4, they now automatically inline static functions
 * with a single call site. Hurrah !
 * Jean II */
#undef IW_GCC_HAS_BROKEN_INLINE
#if __GNUC__ == 3
#if __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4
#define IW_GCC_HAS_BROKEN_INLINE        1
#endif  /* __GNUC_MINOR__ */
#endif  /* __GNUC__ */
/* However, gcc 4.0 has introduce a new "feature", when compiling with
 * '-Os', it does not want to inline iw_ether_cmp() and friends.
 * So, we need to fix inline again !
 * Jean II */
#if __GNUC__ == 4
#define IW_GCC_HAS_BROKEN_INLINE        1
#endif  /* __GNUC__ */
/* Now, really fix the inline */
#ifdef IW_GCC_HAS_BROKEN_INLINE
#ifdef inline
#undef inline
#endif  /* inline */
#define inline          inline          __attribute__((always_inline))
#endif  /* IW_GCC_HAS_BROKEN_INLINE */

#ifdef __cplusplus
extern "C" {
#endif

/****************************** DEBUG ******************************/

//#define DEBUG 1

/************************ CONSTANTS & MACROS ************************/

/* Various versions information */
/* Recommended Wireless Extension version */
#define WE_VERSION      21
/* Maximum forward compatibility built in this version of WT */
#define WE_MAX_VERSION  22
/* Version of Wireless Tools */
#define WT_VERSION      29

/* Paths */
#define PROC_NET_WIRELESS       "/proc/net/wireless"
#define PROC_NET_DEV            "/proc/net/dev"

/* Some usefull constants */
#define KILO    1e3
#define MEGA    1e6
#define GIGA    1e9
/* For doing log10/exp10 without libm */
#define LOG10_MAGIC     1.25892541179

/* Backward compatibility for network headers */
#ifndef ARPHRD_IEEE80211
#define ARPHRD_IEEE80211 801            /* IEEE 802.11                  */
#endif /* ARPHRD_IEEE80211 */

#ifndef IW_EV_LCP_PK_LEN
/* Size of the Event prefix when packed in stream */
#define IW_EV_LCP_PK_LEN        (4)
/* Size of the various events when packed in stream */
#define IW_EV_CHAR_PK_LEN       (IW_EV_LCP_PK_LEN + IFNAMSIZ)
#define IW_EV_UINT_PK_LEN       (IW_EV_LCP_PK_LEN + sizeof(__u32))
#define IW_EV_FREQ_PK_LEN       (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq))
#define IW_EV_PARAM_PK_LEN      (IW_EV_LCP_PK_LEN + sizeof(struct iw_param))
#define IW_EV_ADDR_PK_LEN       (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr))
#define IW_EV_QUAL_PK_LEN       (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality))
#define IW_EV_POINT_PK_LEN      (IW_EV_LCP_PK_LEN + 4)

struct iw_pk_event
{
        __u16           len;                    /* Real lenght of this stuff */
        __u16           cmd;                    /* Wireless IOCTL */
        union iwreq_data        u;              /* IOCTL fixed payload */
} __attribute__ ((packed));
struct  iw_pk_point
{
  void __user   *pointer;       /* Pointer to the data  (in user space) */
  __u16         length;         /* number of fields or size in bytes */
  __u16         flags;          /* Optional params */
} __attribute__ ((packed));

#define IW_EV_LCP_PK2_LEN       (sizeof(struct iw_pk_event) - sizeof(union iwreq_data))
#define IW_EV_POINT_PK2_LEN     (IW_EV_LCP_PK2_LEN + sizeof(struct iw_pk_point) - IW_EV_POINT_OFF)

#endif  /* IW_EV_LCP_PK_LEN */

/****************************** TYPES ******************************/

/* Shortcuts */
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;

/* Structure for storing all wireless information for each device
 * This is a cut down version of the one above, containing only
 * the things *truly* needed to configure a card.
 * Don't add other junk, I'll remove it... */
typedef struct wireless_config
{
  char          name[IFNAMSIZ + 1];     /* Wireless/protocol name */
  int           has_nwid;
  iwparam       nwid;                   /* Network ID */
  int           has_freq;
  double        freq;                   /* Frequency/channel */
  int           freq_flags;
  int           has_key;
  unsigned char key[IW_ENCODING_TOKEN_MAX];     /* Encoding key used */
  int           key_size;               /* Number of bytes */
  int           key_flags;              /* Various flags */
  int           has_essid;
  int           essid_on;
  char          essid[IW_ESSID_MAX_SIZE + 1];   /* ESSID (extended network) */
  int           has_mode;
  int           mode;                   /* Operation mode */
} wireless_config;

/* Structure for storing all wireless information for each device
 * This is pretty exhaustive... */
typedef struct wireless_info
{
  struct wireless_config        b;      /* Basic information */

  int           has_sens;
  iwparam       sens;                   /* sensitivity */
  int           has_nickname;
  char          nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */
  int           has_ap_addr;
  sockaddr      ap_addr;                /* Access point address */
  int           has_bitrate;
  iwparam       bitrate;                /* Bit rate in bps */
  int           has_rts;
  iwparam       rts;                    /* RTS threshold in bytes */
  int           has_frag;
  iwparam       frag;                   /* Fragmentation threshold in bytes */
  int           has_power;
  iwparam       power;                  /* Power management parameters */
  int           has_txpower;
  iwparam       txpower;                /* Transmit Power in dBm */
  int           has_retry;
  iwparam       retry;                  /* Retry limit or lifetime */

  /* Stats */
  iwstats       stats;
  int           has_stats;
  iwrange       range;
  int           has_range;

  /* Auth params for WPA/802.1x/802.11i */
  int           auth_key_mgmt;
  int           has_auth_key_mgmt;
  int           auth_cipher_pairwise;
  int           has_auth_cipher_pairwise;
  int           auth_cipher_group;
  int           has_auth_cipher_group;
} wireless_info;

/* Structure for storing an entry of a wireless scan.
 * This is only a subset of all possible information, the flexible
 * structure of scan results make it impossible to capture all
 * information in such a static structure. */
typedef struct wireless_scan
{
  /* Linked list */
  struct wireless_scan *        next;

  /* Cell identifiaction */
  int           has_ap_addr;
  sockaddr      ap_addr;                /* Access point address */

  /* Other information */
  struct wireless_config        b;      /* Basic information */
  iwstats       stats;                  /* Signal strength */
  int           has_stats;
  iwparam       maxbitrate;             /* Max bit rate in bps */
  int           has_maxbitrate;
} wireless_scan;

/*
 * Context used for non-blocking scan.
 */
typedef struct wireless_scan_head
{
  wireless_scan *       result;         /* Result of the scan */
  int                   retry;          /* Retry level */
} wireless_scan_head;

/* Structure used for parsing event streams, such as Wireless Events
 * and scan results */
typedef struct stream_descr
{
  char *        end;            /* End of the stream */
  char *        current;        /* Current event in stream of events */
  char *        value;          /* Current value in event */
} stream_descr;

/* Prototype for handling display of each single interface on the
 * system - see iw_enum_devices() */
typedef int (*iw_enum_handler)(int      skfd,
                               char *   ifname,
                               char *   args[],
                               int      count);

/* Describe a modulation */
typedef struct iw_modul_descr
{
  unsigned int          mask;           /* Modulation bitmask */
  char                  cmd[8];         /* Short name */
  char *                verbose;        /* Verbose description */
} iw_modul_descr;

/**************************** PROTOTYPES ****************************/
/*
 * All the functions in iwcommon.c
 */

/* ---------------------- SOCKET SUBROUTINES -----------------------*/
int
        iw_sockets_open(void);
void
        iw_enum_devices(int             skfd,
                        iw_enum_handler fn,
                        char *          args[],
                        int             count);
/* --------------------- WIRELESS SUBROUTINES ----------------------*/
int
        iw_get_kernel_we_version(void);
int
        iw_print_version_info(const char *      toolname);
int
        iw_get_range_info(int           skfd,
                          const char *  ifname,
                          iwrange *     range);
int
        iw_get_priv_info(int            skfd,
                         const char *   ifname,
                         iwprivargs **  ppriv);
int
        iw_get_basic_config(int                 skfd,
                            const char *        ifname,
                            wireless_config *   info);
int
        iw_set_basic_config(int                 skfd,
                            const char *        ifname,
                            wireless_config *   info);
/* --------------------- PROTOCOL SUBROUTINES --------------------- */
int
        iw_protocol_compare(const char *        protocol1,
                            const char *        protocol2);
/* -------------------- FREQUENCY SUBROUTINES --------------------- */
void
        iw_float2freq(double    in,
                      iwfreq *  out);
double
        iw_freq2float(const iwfreq *    in);
void
        iw_print_freq_value(char *      buffer,
                            int         buflen,
                            double      freq);
void
        iw_print_freq(char *    buffer,
                      int       buflen,
                      double    freq,
                      int       channel,
                      int       freq_flags);
int
        iw_freq_to_channel(double                       freq,
                           const struct iw_range *      range);
int
        iw_channel_to_freq(int                          channel,
                           double *                     pfreq,
                           const struct iw_range *      range);
void
        iw_print_bitrate(char * buffer,
                         int    buflen,
                         int    bitrate);
/* ---------------------- POWER SUBROUTINES ----------------------- */
int
        iw_dbm2mwatt(int        in);
int
        iw_mwatt2dbm(int        in);
void
        iw_print_txpower(char *                 buffer,
                         int                    buflen,
                         struct iw_param *      txpower);
/* -------------------- STATISTICS SUBROUTINES -------------------- */
int
        iw_get_stats(int                skfd,
                     const char *       ifname,
                     iwstats *          stats,
                     const iwrange *    range,
                     int                has_range);
void
        iw_print_stats(char *           buffer,
                       int              buflen,
                       const iwqual *   qual,
                       const iwrange *  range,
                       int              has_range);
/* --------------------- ENCODING SUBROUTINES --------------------- */
void
        iw_print_key(char *                     buffer,
                     int                        buflen,
                     const unsigned char *      key,
                     int                        key_size,
                     int                        key_flags);
int
        iw_in_key(const char *          input,
                  unsigned char *       key);
int
        iw_in_key_full(int              skfd,
                       const char *     ifname,
                       const char *     input,
                       unsigned char *  key,
                       __u16 *          flags);
/* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */
void
        iw_print_pm_value(char *        buffer,
                          int           buflen,
                          int           value,
                          int           flags,
                          int           we_version);
void
        iw_print_pm_mode(char *         buffer,
                         int            buflen,
                         int            flags);
/* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */
void
        iw_print_retry_value(char *     buffer,
                             int        buflen,
                             int        value,
                             int        flags,
                             int        we_version);
/* ----------------------- TIME SUBROUTINES ----------------------- */
void
        iw_print_timeval(char *                         buffer,
                         int                            buflen,
                         const struct timeval *         time,
                         const struct timezone *        tz);
/* --------------------- ADDRESS SUBROUTINES ---------------------- */
int
        iw_check_mac_addr_type(int              skfd,
                               const char *     ifname);
int
        iw_check_if_addr_type(int               skfd,
                              const char *      ifname);
#if 0
int
        iw_check_addr_type(int          skfd,
                           const char * ifname);
#endif
#if 0
int
        iw_get_mac_addr(int                     skfd,
                        const char *            name,
                        struct ether_addr *     eth,
                        unsigned short *        ptype);
#endif
char *
        iw_mac_ntop(const unsigned char *       mac,
                    int                         maclen,
                    char *                      buf,
                    int                         buflen);
void
        iw_ether_ntop(const struct ether_addr * eth,
                      char *                    buf);
char *
        iw_sawap_ntop(const struct sockaddr *   sap,
                      char *                    buf);
int
        iw_mac_aton(const char *        orig,
                    unsigned char *     mac,
                    int                 macmax);
int
        iw_ether_aton(const char* bufp, struct ether_addr* eth);
int
        iw_in_inet(char *bufp, struct sockaddr *sap);
int
        iw_in_addr(int                  skfd,
                   const char *         ifname,
                   char *               bufp,
                   struct sockaddr *    sap);
/* ----------------------- MISC SUBROUTINES ------------------------ */
int
        iw_get_priv_size(int            args);

/* ---------------------- EVENT SUBROUTINES ---------------------- */
void
        iw_init_event_stream(struct stream_descr *      stream,
                             char *                     data,
                             int                        len);
int
        iw_extract_event_stream(struct stream_descr *   stream,
                                struct iw_event *       iwe,
                                int                     we_version);
/* --------------------- SCANNING SUBROUTINES --------------------- */
int
        iw_process_scan(int                     skfd,
                        char *                  ifname,
                        int                     we_version,
                        wireless_scan_head *    context);
int
        iw_scan(int                     skfd,
                char *                  ifname,
                int                     we_version,
                wireless_scan_head *    context);

/**************************** VARIABLES ****************************/

/* Modes as human readable strings */
extern const char * const       iw_operation_mode[];
#define IW_NUM_OPER_MODE        7
#define IW_NUM_OPER_MODE_EXT    8

/* Modulations as human readable strings */
extern const struct iw_modul_descr      iw_modul_list[];
#define IW_SIZE_MODUL_LIST      16

/************************* INLINE FUNTIONS *************************/
/*
 * Functions that are so simple that it's more efficient inlining them
 */

/*
 * Note : I've defined wrapper for the ioctl request so that
 * it will be easier to migrate to other kernel API if needed
 */

/*------------------------------------------------------------------*/
/*
 * Wrapper to push some Wireless Parameter in the driver
 */
static inline int
iw_set_ext(int                  skfd,           /* Socket to the kernel */
           const char *         ifname,         /* Device name */
           int                  request,        /* WE ID */
           struct iwreq *       pwrq)           /* Fixed part of the request */
{
  /* Set device name */
  strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
  /* Do the request */
  return(ioctl(skfd, request, pwrq));
}

/*------------------------------------------------------------------*/
/*
 * Wrapper to extract some Wireless Parameter out of the driver
 */
static inline int
iw_get_ext(int                  skfd,           /* Socket to the kernel */
           const char *         ifname,         /* Device name */
           int                  request,        /* WE ID */
           struct iwreq *       pwrq)           /* Fixed part of the request */
{
  /* Set device name */
  strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
  /* Do the request */
  return(ioctl(skfd, request, pwrq));
}

/*------------------------------------------------------------------*/
/*
 * Close the socket used for ioctl.
 */
static inline void
iw_sockets_close(int    skfd)
{
  close(skfd);
}

/*------------------------------------------------------------------*/
/*
 * Display an Ethernet Socket Address in readable format.
 */
static inline char *
iw_saether_ntop(const struct sockaddr *sap, char* bufp)
{
  iw_ether_ntop((const struct ether_addr *) sap->sa_data, bufp);
  return bufp;
}
/*------------------------------------------------------------------*/
/*
 * Input an Ethernet Socket Address and convert to binary.
 */
static inline int
iw_saether_aton(const char *bufp, struct sockaddr *sap)
{
  sap->sa_family = ARPHRD_ETHER;
  return iw_ether_aton(bufp, (struct ether_addr *) sap->sa_data);
}

/*------------------------------------------------------------------*/
/*
 * Create an Ethernet broadcast address
 */
static inline void
iw_broad_ether(struct sockaddr *sap)
{
  sap->sa_family = ARPHRD_ETHER;
  memset((char *) sap->sa_data, 0xFF, ETH_ALEN);
}

/*------------------------------------------------------------------*/
/*
 * Create an Ethernet NULL address
 */
static inline void
iw_null_ether(struct sockaddr *sap)
{
  sap->sa_family = ARPHRD_ETHER;
  memset((char *) sap->sa_data, 0x00, ETH_ALEN);
}

/*------------------------------------------------------------------*/
/*
 * Compare two ethernet addresses
 */
static inline int
iw_ether_cmp(const struct ether_addr* eth1, const struct ether_addr* eth2)
{
  return memcmp(eth1, eth2, sizeof(*eth1));
}

#ifdef __cplusplus
}
#endif

#endif  /* IWLIB_H */