wpaspy.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. self.s = None
  43. ai_list = socket.getaddrinfo(path, port, socket.AF_INET,
  44. socket.SOCK_DGRAM)
  45. for af, socktype, proto, cn, sockaddr in ai_list:
  46. self.sockaddr = sockaddr
  47. break
  48. self.s = socket.socket(af, socktype)
  49. self.s.settimeout(5)
  50. self.s.sendto("GET_COOKIE", sockaddr)
  51. reply, server = self.s.recvfrom(4096)
  52. self.cookie = reply
  53. self.port = port
  54. except:
  55. print "connect exception ", path, str(port)
  56. if self.s != None:
  57. self.s.close()
  58. raise
  59. self.started = True
  60. def __del__(self):
  61. self.close()
  62. def close(self):
  63. if self.attached:
  64. try:
  65. self.detach()
  66. except Exception, e:
  67. # Need to ignore this allow the socket to be closed
  68. self.attached = False
  69. pass
  70. if self.started:
  71. self.s.close()
  72. if not self.udp:
  73. os.unlink(self.local)
  74. self.started = False
  75. def request(self, cmd, timeout=10):
  76. if self.udp:
  77. self.s.sendto(self.cookie + cmd, self.sockaddr)
  78. else:
  79. self.s.send(cmd)
  80. [r, w, e] = select.select([self.s], [], [], timeout)
  81. if r:
  82. return self.s.recv(4096)
  83. raise Exception("Timeout on waiting response")
  84. def attach(self):
  85. if self.attached:
  86. return None
  87. res = self.request("ATTACH")
  88. if "OK" in res:
  89. self.attached = True
  90. return None
  91. raise Exception("ATTACH failed")
  92. def detach(self):
  93. if not self.attached:
  94. return None
  95. while self.pending():
  96. ev = self.recv()
  97. res = self.request("DETACH")
  98. if "FAIL" not in res:
  99. self.attached = False
  100. return None
  101. raise Exception("DETACH failed")
  102. def terminate(self):
  103. if self.attached:
  104. try:
  105. self.detach()
  106. except Exception, e:
  107. # Need to ignore this to allow the socket to be closed
  108. self.attached = False
  109. self.request("TERMINATE")
  110. self.close()
  111. def pending(self, timeout=0):
  112. [r, w, e] = select.select([self.s], [], [], timeout)
  113. if r:
  114. return True
  115. return False
  116. def recv(self):
  117. res = self.s.recv(4096)
  118. return res