59f22eb330241942f8bd6371014be57ca30690ca
[pyiw] / pyiw.c
1 /* ------------------------------------------------------------------------------------------------
2 jeremy@emperorlinux.com
3
4 This module was inspired by (and uses) the iw library that comes with the Linux Wireless Tools
5 package. The scanning portions of this module are moderately modified versions of those already
6 found in iwlist.c; however, in the future I plan to clean them up (especially the goto, wtf?)
7
8 Please run "pydoc pyiw" for more thorough, nicely formatted information on this module.
9
10 TODO: DO NOT USE DICTIONARY ACCESS! THIS IS RETARDED! :)
11
12 TODO: Refine WirelessInterface_Scan(). Right now there's a goto in there that makes me feel
13       pretty uncomfortable. This is probably the first thing I'll work on when I have time.
14
15 TODO: Add better (more robust) support for setting the various parameters on the interface.
16       The wireless world has changed a lot since I worked on this last, and there's room
17       for me to certainly clean things up.
18 ------------------------------------------------------------------------------------------------ */
19
20 #include <Python.h>
21 #include <structmember.h>
22 #include <iwlib.h>
23
24 #define PYIW_VERSION_MAJOR  0
25 #define PYIW_VERSION_MINOR  3
26 #define PYIW_VERSION_BUGFIX 3
27 #define PYIW_VERSION_STRING "0.3.3"
28
29 /* --------------------------------------------------------------------------- WirelessInterface */
30 typedef struct {
31         PyObject_HEAD
32         wireless_info info;
33         char*         ifname;
34         int           sock;
35 } WirelessInterface;
36
37 typedef enum {
38         PYIW_KE_ESSID,
39         PYIW_KE_WEP,
40         PYIW_KE_WPA,
41         PYIW_KE_MODE,
42         PYIW_KE_CHANNEL,
43         PYIW_KE_FREQUENCY,
44         PYIW_KE_PROTOCOL,
45         PYIW_KE_QUALITY,
46         PYIW_KE_BITRATE,
47         PYIW_KE_AP_MAC,
48         PYIW_KE_LEVEL,
49         PYIW_KE_NOISE,
50         PYIW_KE_TXPOWER
51 } WirelessInterfaceKeyEnum;
52
53 typedef struct {
54         WirelessInterfaceKeyEnum keys[3];
55         PyObject*                objs[3];
56         int                      num;
57 } WirelessInterfaceScanData;
58         
59 static char* WirelessInterfaceKeys[] = {
60         "essid",
61         "wep",
62         "wpa",
63         "mode",
64         "channel",
65         "frequency",
66         "protocol",
67         "quality",
68         "bitrate",
69         "ap_mac",
70         "level",
71         "noise",
72         "txpower"
73 };
74
75 int WirelessInterfaceNumKeys(void) {
76         return sizeof(WirelessInterfaceKeys) / sizeof(char*);
77 }
78
79 /* ------------------------------------------------------------------------ Function Definitions */
80 typedef struct iw_event           iwevent;
81 typedef struct iwreq              iwreq;
82 typedef struct ifreq              ifreq;
83 typedef struct timeval            timeval;
84 typedef WirelessInterface         wiface;
85 typedef WirelessInterfaceScanData wifacesd;
86
87 static PyObject* pyiw_version    (PyObject*, PyObject*);
88 static PyObject* pyiw_iw_version (PyObject*, PyObject*);
89 static PyObject* pyiw_we_version (PyObject*, PyObject*);
90
91 static int       WirelessInterface_init    (wiface*, PyObject*, PyObject*);
92 static void      WirelessInterface_dealloc (wiface*);
93 static void      WirelessInterface_refresh (wiface*);
94 static int       WirelessInterface_len     (PyObject*);
95 static PyObject* WirelessInterface_mapget  (PyObject*, PyObject*);
96 static int       WirelessInterface_mapset  (PyObject*, PyObject*, PyObject*);
97 static PyObject* WirelessInterface_seqitem (PyObject*, int);
98
99 static PyObject* WirelessInterface_Scan     (wiface*);
100 static int       WirelessInterface_ScanItem (iwevent*, iwrange*, wifacesd*);
101
102 static int Py_SetValInt    (PyObject*, int*, int, int);
103 static int Py_SetValDouble (PyObject*, double*, double, double);
104 static int Py_SetValString (PyObject*, char*, int);
105
106 static PyObject* PyIWError;
107
108 /* ----------------------------------------------------------------------------- PYIW_DOC_STRING */
109 static char* PYIW_DOC_STRING =
110         "PYIW defines a single class, WirelessInterface, that must be instantiated\n"
111         "with the name of the real wireless interface you wish to operate on. If\n"
112         "the interface you specify doesn't exist, or if it doesn't support wireless\n"
113         "extensions, object creation will fail and pyiw.error will be raised.. As an\n" 
114         "important side note: PYIW requires at least Wireless Extensions 17. It may\n"
115         "work in other cases, depending on how much has changed in future versions.\n\n"
116         "The WirelessInterface object behaves very similarly to a dictionary and has\n"
117         "the following keys (note that values that can be reassigned are indicated\n"
118         "with the text RW); changed take effect immediately:\n\n"
119         "- essid     (RW) [string]: The AP's ESSID.\n"
120         "- wep       (RW) [string]: The currently used key; must be root.\n"
121         "- wpa            [bool  ]: Whether or not WPA was detected.\n"
122         "- mode      (RW) [int   ]: Auto, Ad-Hoc, Mangaged, Master,\n"
123         "                           Repeater, Secondary, Monitor\n"
124         "- channel   (RW) [double]: US standard channels 1-12. (index 0-11)\n"
125         "- frequency      [double]: The GHz freq level.\n"
126         "- protocol       [string]: The name representing A, B, or G WiFi.\n"
127         "- quality        [int   ]: Signal quality, 1-100%.\n"
128         "- level          [int   ]: Signal level (dBm).\n"
129         "- noise          [int   ]: Noise level (dBm).\n"
130         "- txpower        [int   ]: Transmit power (dBm).\n"
131         "- bitrate        [int   ]: Number of BPS; 1:1 ratio.\n"
132         "- ap_mac         [string]: The address of the current AP.\n\n"
133         "--- EXAMPLE USAGE --------------------------------------\n\n"
134         "try:\n"
135         "       wi = pyiw.WirelessInterface(\"wlan0\")\n\n"
136         "except pyiw.error, error:\n"
137         "       print error\n"
138         "       sys.exit(1)\n\n"
139         "for param in wi:\n"
140         "       print param, \"-->\", wi[param]\n\n"
141         "wi[\"channel\"] = 6.0\n"
142         "wi[\"essid\"  ] = \"Xenomorph\"\n"
143         "wi[\"mode\"   ] = 3\n"
144         "wi[\"wep\"    ] = \"AD0F44310CEF\"\n\n"
145         "nets = wi.Scan()\n\n"
146         "for net in nets:\n"
147         "       print net[\"essid\"]\n"
148 ;
149
150 /* -------------------------------------------------------------------------------- Py_SetValInt */
151 static int Py_SetValInt(PyObject* arg, int* val, int min, int max) {
152         if(PyInt_Check(arg)) {
153                 int tmp = (int)(PyInt_AsLong(arg));
154
155                 if(tmp >= min && tmp <= max) {  
156                         (*val) = tmp;
157                         
158                         return 0;
159                 }
160
161                 else {
162                         PyErr_SetString(PyExc_ValueError, "Int too big/small in SetValInt");
163                         
164                         return -1;
165                 }
166         }
167                 
168         else {
169                 PyErr_SetString(PyExc_TypeError, "Non-int argument passed to ArgToInt");
170                 
171                 return -1;
172         }
173 }
174
175 /* ----------------------------------------------------------------------------- Py_SetValDouble */
176 static int Py_SetValDouble(PyObject* arg, double* val, double min, double max) {
177         if(PyFloat_Check(arg)) {
178                 double tmp = PyFloat_AsDouble(arg);
179                 
180                 if(tmp >= min && tmp <= max) {
181                         (*val) = tmp;
182                         
183                         return 0;
184                 }
185
186                 else {
187                         PyErr_SetString(PyExc_ValueError, "Double too big/small in SetValDouble");
188                         
189                         return -1;
190                 }
191         }
192                 
193         else {
194                 PyErr_SetString(PyExc_TypeError, "Non-double argument passed to ArgToDouble");
195                 
196                 return -1;
197         }
198 }
199
200 /* ----------------------------------------------------------------------------- Py_SetValString */
201 static int Py_SetValString(PyObject* arg, char* val, int maxsize) {
202         if(PyString_Check(arg)) {
203                 strncpy(val, PyString_AsString(arg), maxsize);
204                 
205                 return 0;
206         }
207
208         else {
209                 PyErr_SetString(PyExc_TypeError, "Non-string argument passed to ArgToString");
210                 
211                 return -1;
212         }
213 }
214
215 /* ---------------------------------------------------------------------- WirelessInterface_init */
216 static int WirelessInterface_init(wiface* self, PyObject* args, PyObject* kargs) {
217         const char*  ifname;
218         const size_t ifnamesize;
219
220         memset(&(self->info), 0, sizeof(wireless_info));
221         
222         self->ifname = NULL;
223         self->sock   = 0;
224         
225         if(PyArg_ParseTuple(args, "s#", &ifname, &ifnamesize)) {        
226                 self->sock = iw_sockets_open();
227
228                 if(self->sock != -1) {
229                         ifreq frq;
230
231                         self->ifname = malloc(ifnamesize + 1);
232
233                         strncpy(self->ifname, ifname, ifnamesize + 1);
234                         strncpy(frq.ifr_name, self->ifname, IFNAMSIZ);
235                         
236                         if(!ioctl(self->sock, SIOCGIFFLAGS, &frq)) {
237                                 frq.ifr_flags |= IFF_UP | IFF_RUNNING;
238                         
239                                 ioctl(self->sock, SIOCSIFFLAGS, &frq);
240                         
241                                 WirelessInterface_refresh(self);
242                                 
243                                 return 0;
244                         }
245
246                         else PyErr_SetString(PyIWError, "Failed to find device");
247                 }
248
249                 else PyErr_SetString(PyIWError, "Failed to connect to libiw");
250         }
251
252         return -1;
253 }
254
255 /* ------------------------------------------------------------------- WirelessInterface_dealloc */
256 static void WirelessInterface_dealloc(wiface* self) {
257         if(self->ifname) free(self->ifname);
258
259         iw_sockets_close(self->sock);
260         self->ob_type->tp_free((PyObject*)(self));
261 }
262
263 /* ------------------------------------------------------------------- WirelessInterface_refresh */
264 static void WirelessInterface_refresh(wiface* self) {
265         iwreq wrq;
266         
267         iw_get_basic_config(self->sock, self->ifname, &(self->info.b));
268         iw_get_range_info(self->sock, self->ifname, &(self->info.range));
269
270         iw_get_ext(self->sock, self->ifname, SIOCGIWRATE, &wrq);
271         memcpy(&(self->info.bitrate), &wrq.u.bitrate, sizeof(iwparam));
272
273         iw_get_ext(self->sock, self->ifname, SIOCGIWAP, &wrq);
274         memcpy(&(self->info.ap_addr), &wrq.u.ap_addr, sizeof (sockaddr));
275
276         iw_get_stats(
277                 self->sock, self->ifname, &(self->info.stats), 
278                 &(self->info.range), self->info.has_range
279         );
280 }
281
282 /* ----------------------------------------------------------------------- WirelessInterface_len */
283 static int WirelessInterface_len(PyObject* self) {
284         return WirelessInterfaceNumKeys();
285 }
286
287 /* -------------------------------------------------------------------- WirelessInterface_mapget */
288 static PyObject* WirelessInterface_mapget(PyObject* self, PyObject* arg) {
289         if(PyString_Check(arg)) {
290                 wiface* wi  = (wiface*)(self);
291                 char*   key = PyString_AsString(arg);
292                 
293                 static char buf[128];
294
295                 WirelessInterface_refresh(wi);
296                 
297                 /* ESSID */
298                 if(!strncmp(key, "essid", 5)) return Py_BuildValue(
299                         "s", wi->info.b.essid
300                 );
301
302                 /* WEP */
303                 else if(!strncmp(key, "wep", 3)) {
304                         iw_print_key(
305                                 buf, 
306                                 sizeof(buf) / sizeof(char),
307                                 wi->info.b.key,
308                                 wi->info.b.key_size,
309                                 wi->info.b.key_flags
310                         );
311                         
312                         if(!strncmp(buf, "00", 2)) return Py_BuildValue("s", "MUST_BE_ROOT");
313                         else return Py_BuildValue("s", buf);
314                 }
315
316                 /* WPA */
317                 else if(!strncmp(key, "wpa", 3)) return Py_BuildValue(
318                         "s", "Unsupported in pyiw version " PYIW_VERSION_STRING
319                 );
320
321                 /* PROTOCOL */
322                 else if(!strncmp(key, "protocol", 8)) return Py_BuildValue(
323                         "s", wi->info.b.name
324                 );
325                 
326                 /* FREQUENCY */
327                 else if(!strncmp(key, "frequency", 9)) {
328                         double freq = wi->info.b.freq;
329                 
330                         if(freq <= 14.0) iw_channel_to_freq((int)(freq), &freq, &(wi->info.range));
331                         
332                         return Py_BuildValue("d", freq);
333                 }
334
335                 /* CHANNEL */
336                 else if(!strncmp(key, "channel", 7)) {
337                         double freq = wi->info.b.freq;
338
339                         if(freq >= 14.0) {
340                                 freq = (double)(iw_freq_to_channel(freq, &(wi->info.range)));
341                         }
342                                 
343                         return Py_BuildValue("d", freq);
344                 }
345                 
346                 /* MODE */
347                 else if(!strncmp(key, "mode", 7)) return Py_BuildValue(
348                         "s", iw_operation_mode[wi->info.b.mode]
349                 );
350                 
351                 /* BITRATE */
352                 else if(!strncmp(key, "bitrate", 7)) return Py_BuildValue(
353                         "i", wi->info.bitrate.value
354                 );
355                 
356                 /* TXPOWER */
357                 else if(!strncmp(key, "txpower", 7)) return Py_BuildValue(
358                         "i", wi->info.txpower.value
359                 );
360                 
361                 /* QUALITY */
362                 else if(!strncmp(key, "quality", 7)) return Py_BuildValue(
363                         "i", wi->info.stats.qual.qual
364                 );
365                 
366                 /* LEVEL */
367                 else if(!strncmp(key, "level", 5)) return Py_BuildValue(
368                         "i", wi->info.stats.qual.level - 0x100
369                 );
370                 
371                 /* NOISE */
372                 else if(!strncmp(key, "noise", 5)) return Py_BuildValue(
373                         "i", wi->info.stats.qual.noise - 0x100
374                 );
375                 
376                 /* AP_MAC */
377                 else if(!strncmp(key, "ap_mac", 6)) {
378                         /* iw_pr_ether(buf, wi->info.ap_addr.sa_data); */
379                         /* iw_ether_ntop((const struct ether_addr *) addr, bufp); */
380                         iw_ether_ntop(
381                                 (const struct ether_addr*)(wi->info.ap_addr.sa_data), 
382                                 buf
383                         );
384                         
385                         return Py_BuildValue("s", buf);
386                 }
387                 
388                 else {
389                         PyErr_SetString(PyExc_ValueError, "Bad key in WirelessInterface_mapget");
390                         return NULL;
391                 }
392         }
393
394         else {
395                 PyErr_SetString(PyExc_TypeError, "Bad key type in WirelessInterface_mapget");
396                 return NULL;
397         }
398 }
399 /* -------------------------------------------------------------------- WirelessInterface_mapset */
400 static int WirelessInterface_mapset(PyObject* self, PyObject* arg, PyObject* val) {
401         if(PyString_Check(arg)) {
402                 wiface*      wi  = (wiface*)(self);
403                 char*        key = PyString_AsString(arg);
404                 int          ret = 0;
405                 struct iwreq wreq;
406                 
407                 memset(&wreq, 0, sizeof(struct iwreq));
408                 
409                 /* ESSID */
410                 if(!strncmp(key, "essid", 5)) {
411                         if(!Py_SetValString(val, wi->info.b.essid, sizeof(wi->info.b.essid))) {
412                                 wreq.u.essid.flags   = 1;
413                                 wreq.u.essid.pointer = wi->info.b.essid;
414                                 wreq.u.essid.length  = strlen(wi->info.b.essid) + 1;
415
416                                 #ifdef _PYIW_DEBUG_
417                                 printf("PYIW DEBUG: iw_set_ext (ESSID) with %s\n", wi->info.b.essid);
418                                 #endif
419                                 
420                                 ret = iw_set_ext(wi->sock, wi->ifname, SIOCSIWESSID, &wreq);
421                         
422                                 #ifdef _PYIW_DEBUG_
423                                 printf("PYIW DEBUG: iw_set_ext (ESSID) returned %d\n", ret);
424                                 #endif
425                                 
426                                 return 0;
427                         }
428
429                         else return -1;
430                 }
431                 
432                 /* WEP */
433                 else if(!strncmp(key, "wep", 3)) {
434                         if(PyString_Check(arg)) {
435                                 int len;
436                                 
437                                 memset(wi->info.b.key, 0, IW_ENCODING_TOKEN_MAX);
438                                 
439                                 len = iw_in_key(
440                                         PyString_AsString(val), wi->info.b.key
441                                 );
442                                 
443                                 wreq.u.data.length  = len;
444                                 wreq.u.data.pointer = wi->info.b.key;
445                                 
446                                 ret = iw_set_ext(wi->sock, wi->ifname, SIOCSIWENCODE, &wreq);
447
448                                 wi->info.b.has_key  = 1;
449                                 wi->info.b.key_size = len;
450
451                                 #ifdef _PYIW_DEBUG_
452                                 printf("PYIW DEBUG: iw_in_key returned: %d\n", len);
453                                 printf("PYIW DEBUG: iw_set_ext (ENCODE) returned: %d\n", ret);
454                                 #endif
455                                 
456                                 return 0;
457                         }
458
459                         else {
460                                 PyErr_SetString(PyExc_TypeError, "Key must be a string");
461                                 return -1;
462                         }
463                 }
464
465                 /* CHANNEL */
466                 else if(!strncmp(key, "channel", 7)) {
467                         if(!Py_SetValDouble(val, &(wi->info.b.freq), 1.0, 12.0)) {
468                                 iw_float2freq(wi->info.b.freq, &(wreq.u.freq));
469
470                                 if(iw_set_ext(wi->sock, wi->ifname, SIOCSIWFREQ, &wreq)) return -1;
471                                 
472                                 else return 0;
473                         }
474
475                         else return -1;
476                 }
477                 
478                 /* MODE */
479                 else if(!strncmp(key, "mode", 4)) return Py_SetValInt(
480                         val, &(wi->info.b.mode), 0, 6
481                 );
482                 
483                 else {
484                         PyErr_SetString(PyExc_ValueError, "Bad key in WirelessInterface_mapset");
485                         return -1;
486                 }
487         }
488
489         else {
490                 PyErr_SetString(PyExc_TypeError, "Bad key type in WirelessInterface_mapset");
491                 return -1;
492         }
493 }
494
495 /* ------------------------------------------------------------------- WirelessInterface_seqitem */
496 static PyObject* WirelessInterface_seqitem(PyObject* self, int index) {
497         if(index >= 0 && index < WirelessInterfaceNumKeys()) return Py_BuildValue(
498                 "s", WirelessInterfaceKeys[index]
499         );
500
501         else return NULL;
502 }
503
504 /* ---------------------------------------------------------------------- WirelessInterface_Scan */
505 static PyObject* WirelessInterface_Scan(wiface* self) {
506         iwreq          wrq;
507         unsigned char* buffer     = NULL;
508         int            buflen     = IW_SCAN_MAX_DATA;
509         iwrange        range;
510         int            has_range;
511         timeval        tv;
512         int            timeout    = 10000000;
513         PyObject*      scan_list  = NULL;
514
515         has_range = (iw_get_range_info(self->sock, self->ifname, &range) >= 0);
516
517         tv.tv_sec          = 0;
518         tv.tv_usec         = 250000;
519         wrq.u.data.pointer = NULL;
520         wrq.u.data.flags   = 0;
521         wrq.u.data.length  = 0;
522
523         if(iw_set_ext(self->sock, self->ifname, SIOCSIWSCAN, &wrq) < 0) {
524                 if(errno != EPERM) {
525                         PyErr_SetString(PyIWError, "Interface doesn't support scanning");
526                         
527                         return NULL;
528                 }
529                 
530                 tv.tv_usec = 0;
531         }
532
533         timeout -= tv.tv_usec;
534
535         while(1) {
536                 fd_set rfds;
537                 int    last_fd;
538                 int    ret;
539
540                 FD_ZERO(&rfds);
541                 last_fd = -1;
542
543                 ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
544
545                 if(ret < 0) {
546                         if(errno == EAGAIN || errno == EINTR) continue;
547                         
548                         else {
549                                 PyErr_SetString(PyIWError, "Unknown scanning error");
550                                 
551                                 return NULL;
552                         }
553                 }
554
555                 if(!ret) {
556                         unsigned char* newbuf;
557
558                         realloc:
559                         newbuf = realloc(buffer, buflen);
560                         
561                         if(!newbuf) {
562                                 if(buffer) free(buffer);
563                                 
564                                 PyErr_SetString(PyIWError, "Memory allocation failure in scan");
565                                 
566                                 return NULL;
567                         }
568                         
569                         buffer = newbuf;
570
571                         wrq.u.data.pointer = buffer;
572                         wrq.u.data.flags   = 0;
573                         wrq.u.data.length  = buflen;
574                         
575                         if(iw_get_ext(self->sock, self->ifname, SIOCGIWSCAN, &wrq) < 0) {
576                                 if((errno == E2BIG)) {
577                                         if(wrq.u.data.length > buflen) buflen = wrq.u.data.length;
578                                         else buflen *= 2;
579
580                                         goto realloc;
581                                 }
582
583                                 if(errno == EAGAIN) {
584                                         tv.tv_sec   = 0;
585                                         tv.tv_usec  = 100000;
586                                         timeout    -= tv.tv_usec;
587                                         
588                                         if(timeout > 0) continue;
589                                 }
590
591                                 free(buffer);
592                                 
593                                 PyErr_SetString(PyIWError, "Unable to read scan data");
594
595                                 return NULL;
596                         }
597                         
598                         else break;
599                 }
600         }
601
602         if(wrq.u.data.length)   {
603                 iwevent      iwe;
604                 stream_descr stream;
605                 int          ret;
606                 PyObject*    scan_dict = NULL;
607                 
608                 scan_list = PyList_New(0);
609                 
610                 iw_init_event_stream(&stream, (char*)(buffer), wrq.u.data.length);
611                 
612                 do {
613                         ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled);
614                 
615                         if(ret > 0) {
616                                 wifacesd sd;
617                                 int sr = WirelessInterface_ScanItem(&iwe, &range, &sd);
618
619                                 if(sr) {
620                                         int i;
621                                         
622                                         if(scan_dict) {
623                                                 PyList_Append(scan_list, scan_dict);    
624                                                 Py_DECREF(scan_dict);
625                                         }
626
627                                         scan_dict = PyDict_New();
628
629                                         for(i = 0; i < WirelessInterfaceNumKeys(); i++) {
630                                                 PyMapping_SetItemString(
631                                                         scan_dict,
632                                                         WirelessInterfaceKeys[i],
633                                                         Py_BuildValue("")
634                                                 );
635                                         }
636                                 }
637                                         
638                                 if(sd.num) {
639                                         int i;
640
641                                         for(i = 0; i < sd.num; i++) {
642                                                 PyMapping_SetItemString(
643                                                         scan_dict, 
644                                                         WirelessInterfaceKeys[sd.keys[i]], 
645                                                         sd.objs[i]
646                                                 );
647                                                 
648                                                 Py_DECREF(sd.objs[i]);
649                                         }
650                                 }
651                         }
652                 }
653                 
654                 while(ret > 0);
655
656                 PyList_Append(scan_list, scan_dict);
657                 Py_XDECREF(scan_dict);
658         }
659         
660         else return Py_BuildValue("[]");
661
662         free(buffer);
663
664         return scan_list;
665 }
666
667 /* ------------------------------------------------------------------ WirelessInterface_ScanItem */
668 static int WirelessInterface_ScanItem(iwevent* event, iwrange* range, wifacesd* data) {
669         static char buf[128];
670         
671         memset(data, 0, sizeof(wifacesd));
672         
673         switch(event->cmd) {
674                 case SIOCGIWAP: {
675                         iw_ether_ntop(
676                                 (const struct ether_addr*)(event->u.ap_addr.sa_data), 
677                                 buf
678                         );              
679                         
680                         data->keys[0] = PYIW_KE_AP_MAC;
681                         data->objs[0] = Py_BuildValue("s", buf);
682                         data->num     = 1;
683                         
684                         return 1;
685                 }       
686
687                 case SIOCGIWFREQ: {
688                         double freq = iw_freq2float(&(event->u.freq));
689                         int    channel;
690                         
691                         if(freq <= 14.0) channel = iw_channel_to_freq((int)(freq), &freq, range);
692                         else channel = iw_freq_to_channel(freq, range);
693                         
694                         data->keys[0] = PYIW_KE_FREQUENCY;
695                         data->keys[1] = PYIW_KE_CHANNEL;
696                         data->objs[0] = Py_BuildValue("d", freq);
697                         data->objs[1] = Py_BuildValue("i", channel);
698                         data->num     = 2;
699                         
700                         return 0;
701                 }
702                 
703                 case SIOCGIWMODE: {
704                         data->keys[0] = PYIW_KE_MODE;
705                         data->objs[0] = Py_BuildValue("s", iw_operation_mode[event->u.mode]);
706                         data->num     = 1;
707
708                         return 0;
709                 }
710
711                 case SIOCGIWNAME: {
712                         data->keys[0] = PYIW_KE_PROTOCOL;
713                         data->objs[0] = Py_BuildValue("s", event->u.name);
714                         data->num     = 1;
715
716                         return 0;
717                 }
718                                   
719                 case SIOCGIWESSID: {
720                         memcpy(buf, event->u.essid.pointer, event->u.essid.length);
721                         buf[event->u.essid.length] = 0x0;
722                          
723                         data->keys[0] = PYIW_KE_ESSID;
724                         data->objs[0] = Py_BuildValue("s", buf);
725                         data->num     = 1;
726
727                         return 0;
728                 }
729
730                 case SIOCGIWENCODE: {
731                         PyObject* pybool;
732                         
733                         if(event->u.data.flags & IW_ENCODE_DISABLED) pybool = Py_False;
734                         else pybool = Py_True;
735                                 
736                         Py_INCREF(pybool);
737                         
738                         data->keys[0] = PYIW_KE_WEP;
739                         data->objs[0] = pybool;
740                         data->num     = 1;
741
742                         return 0;
743                 }
744
745                 case SIOCGIWRATE: {
746                         data->keys[0] = PYIW_KE_BITRATE;
747                         data->objs[0] = Py_BuildValue("i", event->u.bitrate.value);
748                         data->num     = 1;
749                                           
750                         return 0;
751                 }
752
753                 case SIOCGIWTXPOW: {
754                         data->keys[0] = PYIW_KE_TXPOWER;
755                         data->objs[0] = Py_BuildValue("i", event->u.txpower.value);
756                         data->num     = 1;
757                                           
758                         return 0;
759                 }
760
761                 case IWEVQUAL: {
762                         data->keys[0] = PYIW_KE_QUALITY;
763                         data->keys[1] = PYIW_KE_LEVEL;
764                         data->keys[2] = PYIW_KE_NOISE;
765                         data->objs[0] = Py_BuildValue("i", event->u.qual.qual);
766                         data->objs[1] = Py_BuildValue("i", event->u.qual.level - 0x100);
767                         data->objs[2] = Py_BuildValue("i", event->u.qual.noise - 0x100);
768                         data->num     = 3;
769
770                         return 0;
771                 }
772         
773                 case IWEVGENIE: {
774                         PyObject* pytrue = Py_True;
775                         Py_INCREF(pytrue);
776                                         
777                         data->keys[0] = PYIW_KE_WPA;
778                         data->objs[0] = pytrue;
779                         data->num     = 1;
780
781                         return 0;
782                 }
783                                
784                 case IWEVCUSTOM: {
785                         memcpy(buf, event->u.data.pointer, event->u.data.length);
786                         buf[event->u.data.length] = 0x0;
787                         
788                         if(strstr(buf, "wpa_ie")) {
789                                 PyObject* pytrue = Py_True;
790                                 Py_INCREF(pytrue);
791
792                                 data->keys[0] = PYIW_KE_WPA;
793                                 data->objs[0] = pytrue;
794                                 data->num     = 1;
795                         }
796
797                         memset(buf, 0, sizeof(buf));
798                 }
799                 
800                 default: return 0;
801         }
802 }
803
804 /* -------------------------------------------------------------------- Member/Method Structures */
805 static PyMethodDef module_methods[] = {
806         { 
807                 "version", pyiw_version, METH_NOARGS,
808                 "Returns the current PyIW version."
809         },
810         {
811                 "iw_version", pyiw_iw_version, METH_NOARGS,
812                 "Returns the current Wireless Extnesions (libiw WE) version."
813         },
814         {
815                 "we_version", pyiw_we_version, METH_NOARGS,
816                 "Returns the current Wireless Extensions (kernel-level WE) version."
817         },
818         { NULL, NULL, 0, NULL }
819 };
820
821 static PyMethodDef WirelessInterface_methods[] = {
822         {
823                 "Scan", (PyCFunction)(WirelessInterface_Scan), METH_NOARGS,
824                 "This function will attempt to scan any local AP's and return a tuple\n"
825                 "of objectes representing the data contained therein."
826         },
827         { NULL, NULL, 0, NULL }
828 };
829
830 static PyMappingMethods WirelessInterface_mapping_methods = {
831         WirelessInterface_len,    /* length */
832         WirelessInterface_mapget, /* getitem */
833         WirelessInterface_mapset  /* setitem */
834 };
835
836 static PySequenceMethods WirelessInterface_sequence_methods = {
837         WirelessInterface_len,     /* sq_length */
838         0,                         /* sq_concat */
839         0,                         /* sq_repeat */
840         WirelessInterface_seqitem, /* sq_item */
841         0,                         /* sq_slice */
842         0,                         /* sq_ass_item */
843         0,                         /* sq_ass_slice */
844         0,                         /* sq_contains */
845         0,                         /* sq_inplace_concat */
846         0                          /* sq_inplace_repeat */
847 };
848
849 /* -------------------------------------------------------------------- PyType_WirelessInterface */
850 static PyTypeObject PyType_WirelessInterface = {
851         PyObject_HEAD_INIT(NULL)
852         0,                                        /* ob_size */
853         "pyiw.WirelessInterface",                 /* tp_name */
854         sizeof(WirelessInterface),                /* tp_basicsize */
855         0,                                        /* tp_itemsize */
856         (destructor)(WirelessInterface_dealloc),  /* tp_dealloc */
857         0,                                        /* tp_print */
858         0,                                        /* tp_getattr */
859         0,                                        /* tp_setattr */
860         0,                                        /* tp_compare */
861         0,                                        /* tp_repr */
862         0,                                        /* tp_as_number */
863         &WirelessInterface_sequence_methods,      /* tp_as_sequence */
864         &WirelessInterface_mapping_methods,       /* tp_as_mapping */
865         0,                                        /* tp_hash */
866         0,                                        /* tp_call */
867         0,                                        /* tp_str */
868         0,                                        /* tp_getattro */
869         0,                                        /* tp_setattro */
870         0,                                        /* tp_as_buffer */
871         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
872         0,                                        /* tp_doc */
873         0,                                        /* tp_traverse */
874         0,                                        /* tp_clear */
875         0,                                        /* tp_richcompare */
876         0,                                        /* tp_weaklistoffset */
877         0,                                        /* tp_iter */
878         0,                                        /* tp_iternext */
879         WirelessInterface_methods,                /* tp_methods */
880         0,                                        /* tp_members */
881         0,                                        /* tp_getset */
882         0,                                        /* tp_base */
883         0,                                        /* tp_dict */
884         0,                                        /* tp_descr_get */
885         0,                                        /* tp_descr_set */
886         0,                                        /* tp_dictoffset */
887         (initproc)(WirelessInterface_init),       /* tp_init */
888         0,                                        /* tp_alloc */
889         PyType_GenericNew,                        /* tp_new */
890         0,                                        /* tp_free */
891         0,                                        /* tp_is_gc */
892         0,                                        /* tp_bases */
893         0,                                        /* tp_mro */
894         0,                                        /* tp_cache */
895         0,                                        /* tp_subclasses */
896         0,                                        /* tp_weaklist */
897         0                                         /* tp_del */
898 };
899
900 /* ------------------------------------------------------------------------------------ initpyiw */
901 PyMODINIT_FUNC initpyiw(void) {
902         PyObject* module;
903         
904         PyType_Ready(&PyType_WirelessInterface);
905
906         module    = Py_InitModule3("pyiw", module_methods, PYIW_DOC_STRING);
907         PyIWError = PyErr_NewException("pyiw.error", NULL, NULL);
908
909         Py_INCREF(&PyType_WirelessInterface);
910         Py_INCREF(PyIWError);
911         
912         PyModule_AddObject(module, "WirelessInterface", (PyObject*)(&PyType_WirelessInterface));
913         PyModule_AddObject(module, "error", PyIWError);
914 }
915
916 static PyObject* pyiw_version(PyObject* u1, PyObject* u2) {
917         return Py_BuildValue("(iii)", 
918                 PYIW_VERSION_MAJOR,
919                 PYIW_VERSION_MINOR,
920                 PYIW_VERSION_BUGFIX
921         );
922 }
923
924 static PyObject* pyiw_iw_version(PyObject* u1, PyObject* u2) {
925         return Py_BuildValue("i", WE_VERSION);
926 }
927
928 static PyObject* pyiw_we_version(PyObject* u1, PyObject* u2) {
929         return Py_BuildValue("i", iw_get_kernel_we_version());
930 }