wpaspy.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/python
  2. #
  3. # wpa_supplicant/hostapd control interface using Python
  4. # Copyright (c) 2013, Jouni Malinen <j@w1.fi>
  5. #
  6. # This software may be distributed under the terms of the BSD license.
  7. # See README for more details.
  8. import os
  9. import stat
  10. import socket
  11. import select
  12. counter = 0
  13. class Ctrl:
  14. def __init__(self, path, port=9877):
  15. global counter
  16. self.started = False
  17. self.attached = False
  18. self.path = path
  19. self.port = port
  20. try:
  21. mode = os.stat(path).st_mode
  22. if stat.S_ISSOCK(mode):
  23. self.udp = False
  24. else:
  25. self.udp = True
  26. except:
  27. self.udp = True
  28. if not self.udp:
  29. self.s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
  30. self.dest = path
  31. self.local = "/tmp/wpa_ctrl_" + str(os.getpid()) + '-' + str(counter)
  32. counter += 1
  33. self.s.bind(self.local)
  34. try:
  35. self.s.connect(self.dest)
  36. except Exception, e:
  37. self.s.close()
  38. os.unlink(self.local)
  39. raise
  40. else:
  41. try:
  42. ai_list = socket.getaddrinfo(path, port, socket.AF_INET,
  43. socket.SOCK_DGRAM)
  44. for af, socktype, proto, cn, sockaddr in ai_list:
  45. self.sockaddr = sockaddr
  46. break
  47. self.s = socket.socket(af, socktype)
  48. self.s.settimeout(5)
  49. self.s.sendto("GET_COOKIE", sockaddr)
  50. reply, server = self.s.recvfrom(4096)
  51. self.cookie = reply
  52. self.port = port
  53. except:
  54. print "connect exception ", path, str(port)
  55. if self.s != None:
  56. self.s.close()
  57. raise
  58. self.started = True
  59. def __del__(self):
  60. self.close()
  61. def close(self):
  62. if self.attached:
  63. try:
  64. self.detach()
  65. except Exception, e:
  66. # Need to ignore this allow the socket to be closed
  67. self.attached = False
  68. pass
  69. if self.started:
  70. self.s.close()
  71. if not self.udp:
  72. os.unlink(self.local)
  73. self.started = False
  74. def request(self, cmd, timeout=10):
  75. if self.udp:
  76. self.s.sendto(self.cookie + cmd, self.sockaddr)
  77. else:
  78. self.s.send(cmd)
  79. [r, w, e] = select.select([self.s], [], [], timeout)
  80. if r:
  81. return self.s.recv(4096)
  82. raise Exception("Timeout on waiting response")
  83. def attach(self):
  84. if self.attached:
  85. return None
  86. res = self.request("ATTACH")
  87. if "OK" in res:
  88. self.attached = True
  89. return None
  90. raise Exception("ATTACH failed")
  91. def detach(self):
  92. if not self.attached:
  93. return None
  94. while self.pending():
  95. ev = self.recv()
  96. res = self.request("DETACH")
  97. if "FAIL" not in res:
  98. self.attached = False
  99. return None
  100. raise Exception("DETACH failed")
  101. def terminate(self):
  102. if self.attached:
  103. try:
  104. self.detach()
  105. except Exception, e:
  106. # Need to ignore this to allow the socket to be closed
  107. self.attached = False
  108. self.request("TERMINATE")
  109. self.close()
  110. def pending(self, timeout=0):
  111. [r, w, e] = select.select([self.s], [], [], timeout)
  112. if r:
  113. return True
  114. return False
  115. def recv(self):
  116. res = self.s.recv(4096)
  117. return res