4 * Jean II - HPLB 97->99 - HPL 99->04
6 * Common header for the Wireless Extension library...
8 * This file is released under the GPL license.
9 * Copyright (c) 1997-2004 Jean Tourrilhes <jt@hpl.hp.com>
15 /*#include "CHANGELOG.h"*/
17 /***************************** INCLUDES *****************************/
19 /* Standard headers */
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
30 #include <netdb.h> /* gethostbyname, getnetbyname */
31 #include <net/ethernet.h> /* struct ether_addr */
32 #include <sys/time.h> /* struct timeval */
35 /* This is our header selection. Try to hide the mess and the misery :-(
36 * Don't look, you would go blind ;-) */
38 #ifndef LINUX_VERSION_CODE
39 #include <linux/version.h>
42 /* Kernel headers 2.4.X + Glibc 2.2 - Mandrake 8.0, Debian 2.3, RH 7.1
43 * Kernel headers 2.2.X + Glibc 2.2 - Slackware 8.0 */
44 #if defined(__GLIBC__) \
46 && __GLIBC_MINOR__ >= 2 \
47 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
48 //#define GLIBC22_HEADERS
49 #define GENERIC_HEADERS
51 /* Kernel headers 2.4.X + Glibc 2.1 - Debian 2.2 upgraded, RH 7.0
52 * Kernel headers 2.2.X + Glibc 2.1 - Debian 2.2, RH 6.1 */
53 #elif defined(__GLIBC__) \
55 && __GLIBC_MINOR__ == 1 \
56 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
57 //#define GLIBC_HEADERS
58 #define GENERIC_HEADERS
60 /* Kernel headers 2.2.X + Glibc 2.0 - Debian 2.1 */
61 #elif defined(__GLIBC__) \
63 && __GLIBC_MINOR__ == 0 \
64 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0) \
65 && LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
67 #define KLUDGE_HEADERS
69 /* Note : is it really worth supporting kernel 2.0.X, knowing that
70 * we require WE v9, which is only available in 2.2.X and higher ?
71 * I guess one could use 2.0.x with an upgraded wireless.h... */
73 /* Kernel headers 2.0.X + Glibc 2.0 - Debian 2.0, RH 5 */
74 #elif defined(__GLIBC__) \
76 && __GLIBC_MINOR__ == 0 \
77 && LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) \
78 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0)
81 /* Kernel headers 2.0.X + libc5 - old systems */
82 #elif defined(_LINUX_C_LIB_VERSION_MAJOR) \
83 && _LINUX_C_LIB_VERSION_MAJOR == 5 \
84 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0) \
85 && LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
88 /* Unsupported combination */
90 #error "Your kernel/libc combination is not supported"
93 #ifdef GENERIC_HEADERS
94 /* Proposed by Dr. Michael Rietz <rietz@mail.amps.de>, 27.3.2 */
95 /* If this works for all, it might be more stable on the long term - Jean II */
96 #include <net/if_arp.h> /* For ARPHRD_ETHER */
97 #include <sys/socket.h> /* For AF_INET & struct sockaddr */
98 #include <netinet/in.h> /* For struct sockaddr_in */
99 #include <netinet/if_ether.h>
100 #endif /* GENERIC_HEADERS */
102 #ifdef GLIBC22_HEADERS
103 /* Added by Ross G. Miller <Ross_Miller@baylor.edu>, 3/28/01 */
104 #include <linux/if_arp.h> /* For ARPHRD_ETHER */
105 #include <linux/socket.h> /* For AF_INET & struct sockaddr */
106 #include <sys/socket.h>
107 #endif /* GLIBC22_HEADERS */
109 #ifdef KLUDGE_HEADERS
110 #include <socketbits.h>
111 #endif /* KLUDGE_HEADERS */
114 #include <linux/if_arp.h> /* For ARPHRD_ETHER */
115 #include <linux/socket.h> /* For AF_INET & struct sockaddr */
116 #include <linux/in.h> /* For struct sockaddr_in */
117 #endif /* KLUDGE_HEADERS || GLIBC_HEADERS */
120 #include <sys/socket.h> /* For AF_INET & struct sockaddr & socket() */
121 #include <linux/if_arp.h> /* For ARPHRD_ETHER */
122 #include <linux/in.h> /* For struct sockaddr_in */
123 #endif /* LIBC5_HEADERS */
125 /* Those 3 headers were previously included in wireless.h */
126 #include <linux/types.h> /* for "caddr_t" et al */
127 #include <linux/socket.h> /* for "struct sockaddr" et al */
128 #include <linux/if.h> /* for IFNAMSIZ and co... */
130 /* Private copy of Wireless extensions */
131 #include <wireless.h>
133 /* Make gcc understant that when we say inline, we mean it.
134 * I really hate when the compiler is trying to be more clever than me,
135 * because in this case gcc is not able to figure out functions with a
136 * single call site, so not only I have to tag those functions inline
137 * by hand, but then it refuse to inline them properly.
138 * Total saving for iwevent : 150B = 0.7%.
139 * Fortunately, in gcc 3.4, they now automatically inline static functions
140 * with a single call site. Hurrah !
143 #if __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4
144 #define inline inline __attribute__((always_inline))
146 #endif /* __GNUC__ */
152 /****************************** DEBUG ******************************/
155 /************************ CONSTANTS & MACROS ************************/
157 /* Various versions information */
158 /* Recommended Wireless Extension version */
159 #define WE_VERSION 17
160 /* Version of Wireless Tools */
161 #define WT_VERSION 27
164 #define PROC_NET_WIRELESS "/proc/net/wireless"
165 #define PROC_NET_DEV "/proc/net/dev"
167 /* Some usefull constants */
171 /* For doing log10/exp10 without libm */
172 #define LOG10_MAGIC 1.25892541179
174 /* Backward compatibility for Wireless Extension 9 */
175 #ifndef IW_POWER_MODIFIER
176 #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */
177 #define IW_POWER_MIN 0x0001 /* Value is a minimum */
178 #define IW_POWER_MAX 0x0002 /* Value is a maximum */
179 #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
180 #endif /* IW_POWER_MODIFIER */
182 #ifndef IW_ENCODE_NOKEY
183 #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not here */
184 #define IW_ENCODE_MODE 0xF000 /* Modes defined below */
185 #endif /* IW_ENCODE_NOKEY */
186 #ifndef IW_ENCODE_TEMP
187 #define IW_ENCODE_TEMP 0x0400 /* Temporary key */
188 #endif /* IW_ENCODE_TEMP */
190 /* More backward compatibility */
191 #ifndef SIOCSIWCOMMIT
192 #define SIOCSIWCOMMIT SIOCSIWNAME
193 #endif /* SIOCSIWCOMMIT */
195 /* Still more backward compatibility */
196 #ifndef IW_FREQ_FIXED
197 #define IW_FREQ_FIXED 0x01
198 #endif /* IW_FREQ_FIXED */
200 /****************************** TYPES ******************************/
203 typedef struct iw_statistics iwstats;
204 typedef struct iw_range iwrange;
205 typedef struct iw_param iwparam;
206 typedef struct iw_freq iwfreq;
207 typedef struct iw_quality iwqual;
208 typedef struct iw_priv_args iwprivargs;
209 typedef struct sockaddr sockaddr;
211 /* Structure for storing all wireless information for each device
212 * This is a cut down version of the one above, containing only
213 * the things *truly* needed to configure a card.
214 * Don't add other junk, I'll remove it... */
215 typedef struct wireless_config
217 char name[IFNAMSIZ + 1]; /* Wireless/protocol name */
219 iwparam nwid; /* Network ID */
221 double freq; /* Frequency/channel */
224 unsigned char key[IW_ENCODING_TOKEN_MAX]; /* Encoding key used */
225 int key_size; /* Number of bytes */
226 int key_flags; /* Various flags */
229 char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID (extended network) */
231 int mode; /* Operation mode */
234 /* Structure for storing all wireless information for each device
235 * This is pretty exhaustive... */
236 typedef struct wireless_info
238 struct wireless_config b; /* Basic information */
241 iwparam sens; /* sensitivity */
243 char nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */
245 sockaddr ap_addr; /* Access point address */
247 iwparam bitrate; /* Bit rate in bps */
249 iwparam rts; /* RTS threshold in bytes */
251 iwparam frag; /* Fragmentation threshold in bytes */
253 iwparam power; /* Power management parameters */
255 iwparam txpower; /* Transmit Power in dBm */
257 iwparam retry; /* Retry limit or lifetime */
266 /* Structure for storing an entry of a wireless scan.
267 * This is only a subset of all possible information, the flexible
268 * structure of scan results make it impossible to capture all
269 * information in such a static structure. */
270 typedef struct wireless_scan
273 struct wireless_scan * next;
275 /* Cell identifiaction */
277 sockaddr ap_addr; /* Access point address */
279 /* Other information */
280 struct wireless_config b; /* Basic information */
281 iwstats stats; /* Signal strength */
286 * Context used for non-blocking scan.
288 typedef struct wireless_scan_head
290 wireless_scan * result; /* Result of the scan */
291 int retry; /* Retry level */
292 } wireless_scan_head;
294 /* Structure used for parsing event streams, such as Wireless Events
295 * and scan results */
296 typedef struct stream_descr
298 char * end; /* End of the stream */
299 char * current; /* Current event in stream of events */
300 char * value; /* Current value in event */
303 /* Prototype for handling display of each single interface on the
304 * system - see iw_enum_devices() */
305 typedef int (*iw_enum_handler)(int skfd,
310 /**************************** PROTOTYPES ****************************/
312 * All the functions in iwcommon.c
315 /* ---------------------- SOCKET SUBROUTINES -----------------------*/
317 iw_sockets_open(void);
319 iw_enum_devices(int skfd,
323 /* --------------------- WIRELESS SUBROUTINES ----------------------*/
325 iw_get_kernel_we_version(void);
327 iw_print_version_info(const char * toolname);
329 iw_get_range_info(int skfd,
333 iw_get_priv_info(int skfd,
335 iwprivargs ** ppriv);
337 iw_get_basic_config(int skfd,
339 wireless_config * info);
341 iw_set_basic_config(int skfd,
343 wireless_config * info);
344 /* --------------------- PROTOCOL SUBROUTINES --------------------- */
346 iw_protocol_compare(const char * protocol1,
347 const char * protocol2);
348 /* -------------------- FREQUENCY SUBROUTINES --------------------- */
350 iw_float2freq(double in,
353 iw_freq2float(const iwfreq * in);
355 iw_print_freq_value(char * buffer,
359 iw_print_freq(char * buffer,
365 iw_freq_to_channel(double freq,
366 const struct iw_range * range);
368 iw_channel_to_freq(int channel,
370 const struct iw_range * range);
372 iw_print_bitrate(char * buffer,
375 /* ---------------------- POWER SUBROUTINES ----------------------- */
377 iw_dbm2mwatt(int in);
379 iw_mwatt2dbm(int in);
381 iw_print_txpower(char * buffer,
383 struct iw_param * txpower);
384 /* -------------------- STATISTICS SUBROUTINES -------------------- */
386 iw_get_stats(int skfd,
389 const iwrange * range,
392 iw_print_stats(char * buffer,
395 const iwrange * range,
397 /* --------------------- ENCODING SUBROUTINES --------------------- */
399 iw_print_key(char * buffer,
401 const unsigned char * key,
405 iw_in_key(const char * input,
406 unsigned char * key);
408 iw_in_key_full(int skfd,
413 /* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */
415 iw_print_pm_value(char * buffer,
420 iw_print_pm_mode(char * buffer,
423 /* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */
425 iw_print_retry_value(char * buffer,
429 /* ----------------------- TIME SUBROUTINES ----------------------- */
431 iw_print_timeval(char * buffer,
433 const struct timeval * time);
434 /* --------------------- ADDRESS SUBROUTINES ---------------------- */
436 iw_check_mac_addr_type(int skfd,
439 iw_check_if_addr_type(int skfd,
443 iw_check_addr_type(int skfd,
447 iw_get_mac_addr(int skfd,
449 struct ether_addr * eth,
450 unsigned short * ptype);
452 iw_ether_ntop(const struct ether_addr* eth, char* buf);
454 iw_ether_ntoa(const struct ether_addr* eth);
456 iw_ether_aton(const char* bufp, struct ether_addr* eth);
458 iw_in_inet(char *bufp, struct sockaddr *sap);
463 struct sockaddr * sap);
464 /* ----------------------- MISC SUBROUTINES ------------------------ */
466 iw_get_priv_size(int args);
468 /* ---------------------- EVENT SUBROUTINES ---------------------- */
470 iw_init_event_stream(struct stream_descr * stream,
474 iw_extract_event_stream(struct stream_descr * stream,
475 struct iw_event * iwe,
477 /* --------------------- SCANNING SUBROUTINES --------------------- */
479 iw_process_scan(int skfd,
482 wireless_scan_head * context);
487 wireless_scan_head * context);
489 /**************************** VARIABLES ****************************/
491 /* Modes as human readable strings */
492 extern const char * const iw_operation_mode[];
493 #define IW_NUM_OPER_MODE 7
495 /************************* INLINE FUNTIONS *************************/
497 * Functions that are so simple that it's more efficient inlining them
501 * Note : I've defined wrapper for the ioctl request so that
502 * it will be easier to migrate to other kernel API if needed
505 /*------------------------------------------------------------------*/
507 * Wrapper to push some Wireless Parameter in the driver
510 iw_set_ext(int skfd, /* Socket to the kernel */
511 const char * ifname, /* Device name */
512 int request, /* WE ID */
513 struct iwreq * pwrq) /* Fixed part of the request */
515 /* Set device name */
516 strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
518 return(ioctl(skfd, request, pwrq));
521 /*------------------------------------------------------------------*/
523 * Wrapper to extract some Wireless Parameter out of the driver
526 iw_get_ext(int skfd, /* Socket to the kernel */
527 const char * ifname, /* Device name */
528 int request, /* WE ID */
529 struct iwreq * pwrq) /* Fixed part of the request */
531 /* Set device name */
532 strncpy(pwrq->ifr_name, ifname, IFNAMSIZ);
534 return(ioctl(skfd, request, pwrq));
537 /*------------------------------------------------------------------*/
539 * Close the socket used for ioctl.
542 iw_sockets_close(int skfd)
547 /*------------------------------------------------------------------*/
548 /* Backwards compatability
549 * Actually, those form are much easier to use when dealing with
550 * struct sockaddr... */
552 iw_pr_ether(char* bufp, const unsigned char* addr)
554 iw_ether_ntop((const struct ether_addr *) addr, bufp);
557 /* Backwards compatability */
559 iw_in_ether(const char *bufp, struct sockaddr *sap)
561 sap->sa_family = ARPHRD_ETHER;
562 return iw_ether_aton(bufp, (struct ether_addr *) sap->sa_data) ? 0 : -1;
565 /*------------------------------------------------------------------*/
567 * Create an Ethernet broadcast address
570 iw_broad_ether(struct sockaddr *sap)
572 sap->sa_family = ARPHRD_ETHER;
573 memset((char *) sap->sa_data, 0xFF, ETH_ALEN);
576 /*------------------------------------------------------------------*/
578 * Create an Ethernet NULL address
581 iw_null_ether(struct sockaddr *sap)
583 sap->sa_family = ARPHRD_ETHER;
584 memset((char *) sap->sa_data, 0x00, ETH_ALEN);