wpaspy.py 3.7 KB

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