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