Merged the hostap_2.6 updates, and the Leap of Faith work, from the hostap_update...
[mech_eap.git] / libeap / wpaspy / wpaspy.py
diff --git a/libeap/wpaspy/wpaspy.py b/libeap/wpaspy/wpaspy.py
new file mode 100644 (file)
index 0000000..c2aace0
--- /dev/null
@@ -0,0 +1,131 @@
+#!/usr/bin/python
+#
+# wpa_supplicant/hostapd control interface using Python
+# Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import os
+import stat
+import socket
+import select
+
+counter = 0
+
+class Ctrl:
+    def __init__(self, path, port=9877):
+        global counter
+        self.started = False
+        self.attached = False
+        self.path = path
+        self.port = port
+
+        try:
+            mode = os.stat(path).st_mode
+            if stat.S_ISSOCK(mode):
+                self.udp = False
+            else:
+                self.udp = True
+        except:
+            self.udp = True
+
+        if not self.udp:
+            self.s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
+            self.dest = path
+            self.local = "/tmp/wpa_ctrl_" + str(os.getpid()) + '-' + str(counter)
+            counter += 1
+            self.s.bind(self.local)
+            try:
+                self.s.connect(self.dest)
+            except Exception, e:
+                self.s.close()
+                os.unlink(self.local)
+                raise
+        else:
+            try:
+                self.s = None
+                ai_list = socket.getaddrinfo(path, port, socket.AF_INET,
+                                             socket.SOCK_DGRAM)
+                for af, socktype, proto, cn, sockaddr in ai_list:
+                    self.sockaddr = sockaddr
+                    break
+                self.s = socket.socket(af, socktype)
+                self.s.settimeout(5)
+                self.s.sendto("GET_COOKIE", sockaddr)
+                reply, server = self.s.recvfrom(4096)
+                self.cookie = reply
+                self.port = port
+            except:
+                print "connect exception ", path, str(port)
+                if self.s != None:
+                    self.s.close()
+                raise
+        self.started = True
+
+    def __del__(self):
+        self.close()
+
+    def close(self):
+        if self.attached:
+            try:
+                self.detach()
+            except Exception, e:
+                # Need to ignore this allow the socket to be closed
+                self.attached = False
+                pass
+        if self.started:
+            self.s.close()
+            if not self.udp:
+                os.unlink(self.local)
+            self.started = False
+
+    def request(self, cmd, timeout=10):
+        if self.udp:
+            self.s.sendto(self.cookie + cmd, self.sockaddr)
+        else:
+            self.s.send(cmd)
+        [r, w, e] = select.select([self.s], [], [], timeout)
+        if r:
+            return self.s.recv(4096)
+        raise Exception("Timeout on waiting response")
+
+    def attach(self):
+        if self.attached:
+            return None
+        res = self.request("ATTACH")
+        if "OK" in res:
+            self.attached = True
+            return None
+        raise Exception("ATTACH failed")
+
+    def detach(self):
+        if not self.attached:
+            return None
+        while self.pending():
+            ev = self.recv()
+        res = self.request("DETACH")
+        if "FAIL" not in res:
+            self.attached = False
+            return None
+        raise Exception("DETACH failed")
+
+    def terminate(self):
+        if self.attached:
+            try:
+                self.detach()
+            except Exception, e:
+                # Need to ignore this to allow the socket to be closed
+                self.attached = False
+        self.request("TERMINATE")
+        self.close()
+
+    def pending(self, timeout=0):
+        [r, w, e] = select.select([self.s], [], [], timeout)
+        if r:
+            return True
+        return False
+
+    def recv(self):
+        res = self.s.recv(4096)
+        return res