123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- #!/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.
- from __future__ import print_function
- 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 as 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(b"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 as 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 type(cmd) == str:
- try:
- cmd2 = cmd.encode()
- cmd = cmd2
- except UnicodeDecodeError as e:
- pass
- 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:
- res = self.s.recv(4096).decode()
- try:
- r = str(res)
- except UnicodeDecodeError as e:
- r = res
- return r
- 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
- if self.s.fileno() == -1:
- self.attached = False
- 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 as 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).decode()
- try:
- r = str(res)
- except UnicodeDecodeError as e:
- r = res
- return r
|