hostapd.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #!/usr/bin/python
  2. #
  3. # Python class for controlling hostapd
  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 time
  10. import logging
  11. import wpaspy
  12. logger = logging.getLogger()
  13. hapd_ctrl = '/var/run/hostapd'
  14. hapd_global = '/var/run/hostapd-global'
  15. class HostapdGlobal:
  16. def __init__(self):
  17. self.ctrl = wpaspy.Ctrl(hapd_global)
  18. def add(self, ifname):
  19. res = self.ctrl.request("ADD " + ifname + " " + hapd_ctrl)
  20. if not "OK" in res:
  21. raise Exception("Could not add hostapd interface " + ifname)
  22. def add_iface(self, ifname, confname):
  23. res = self.ctrl.request("ADD " + ifname + " config=" + confname)
  24. if not "OK" in res:
  25. raise Exception("Could not add hostapd interface")
  26. def add_bss(self, phy, confname, ignore_error=False):
  27. res = self.ctrl.request("ADD bss_config=" + phy + ":" + confname)
  28. if not "OK" in res:
  29. if not ignore_error:
  30. raise Exception("Could not add hostapd BSS")
  31. def remove(self, ifname):
  32. self.ctrl.request("REMOVE " + ifname)
  33. def relog(self):
  34. self.ctrl.request("RELOG")
  35. class Hostapd:
  36. def __init__(self, ifname):
  37. self.ifname = ifname
  38. self.ctrl = wpaspy.Ctrl(os.path.join(hapd_ctrl, ifname))
  39. self.mon = wpaspy.Ctrl(os.path.join(hapd_ctrl, ifname))
  40. self.mon.attach()
  41. def request(self, cmd):
  42. logger.debug(self.ifname + ": CTRL: " + cmd)
  43. return self.ctrl.request(cmd)
  44. def ping(self):
  45. return "PONG" in self.request("PING")
  46. def set(self, field, value):
  47. logger.debug(self.ifname + ": SET " + field + "=" + value)
  48. if not "OK" in self.request("SET " + field + " " + value):
  49. raise Exception("Failed to set hostapd parameter " + field)
  50. def set_defaults(self):
  51. self.set("driver", "nl80211")
  52. self.set("hw_mode", "g")
  53. self.set("channel", "1")
  54. self.set("ieee80211n", "1")
  55. self.set("logger_stdout", "-1")
  56. self.set("logger_stdout_level", "0")
  57. def set_open(self, ssid):
  58. self.set_defaults()
  59. self.set("ssid", ssid)
  60. def set_wpa2_psk(self, ssid, passphrase):
  61. self.set_defaults()
  62. self.set("ssid", ssid)
  63. self.set("wpa_passphrase", passphrase)
  64. self.set("wpa", "2")
  65. self.set("wpa_key_mgmt", "WPA-PSK")
  66. self.set("rsn_pairwise", "CCMP")
  67. def set_wpa_psk(self, ssid, passphrase):
  68. self.set_defaults()
  69. self.set("ssid", ssid)
  70. self.set("wpa_passphrase", passphrase)
  71. self.set("wpa", "1")
  72. self.set("wpa_key_mgmt", "WPA-PSK")
  73. self.set("wpa_pairwise", "TKIP")
  74. def set_wpa_psk_mixed(self, ssid, passphrase):
  75. self.set_defaults()
  76. self.set("ssid", ssid)
  77. self.set("wpa_passphrase", passphrase)
  78. self.set("wpa", "3")
  79. self.set("wpa_key_mgmt", "WPA-PSK")
  80. self.set("wpa_pairwise", "TKIP")
  81. self.set("rsn_pairwise", "CCMP")
  82. def set_wep(self, ssid, key):
  83. self.set_defaults()
  84. self.set("ssid", ssid)
  85. self.set("wep_key0", key)
  86. def enable(self):
  87. if not "OK" in self.ctrl.request("ENABLE"):
  88. raise Exception("Failed to enable hostapd interface " + self.ifname)
  89. def disable(self):
  90. if not "OK" in self.ctrl.request("ENABLE"):
  91. raise Exception("Failed to disable hostapd interface " + self.ifname)
  92. def dump_monitor(self):
  93. while self.mon.pending():
  94. ev = self.mon.recv()
  95. logger.debug(self.ifname + ": " + ev)
  96. def wait_event(self, events, timeout):
  97. count = 0
  98. while count < timeout * 10:
  99. count = count + 1
  100. time.sleep(0.1)
  101. while self.mon.pending():
  102. ev = self.mon.recv()
  103. logger.debug(self.ifname + ": " + ev)
  104. for event in events:
  105. if event in ev:
  106. return ev
  107. return None
  108. def get_status(self):
  109. res = self.request("STATUS")
  110. lines = res.splitlines()
  111. vals = dict()
  112. for l in lines:
  113. [name,value] = l.split('=', 1)
  114. vals[name] = value
  115. return vals
  116. def get_status_field(self, field):
  117. vals = self.get_status()
  118. if field in vals:
  119. return vals[field]
  120. return None
  121. def add_ap(ifname, params):
  122. logger.info("Starting AP " + ifname)
  123. hapd_global = HostapdGlobal()
  124. hapd_global.remove(ifname)
  125. hapd_global.add(ifname)
  126. hapd = Hostapd(ifname)
  127. if not hapd.ping():
  128. raise Exception("Could not ping hostapd")
  129. hapd.set_defaults()
  130. fields = [ "ssid", "wpa_passphrase", "nas_identifier", "wpa_key_mgmt",
  131. "wpa",
  132. "wpa_pairwise", "rsn_pairwise", "auth_server_addr" ]
  133. for field in fields:
  134. if field in params:
  135. hapd.set(field, params[field])
  136. for f,v in params.items():
  137. if f in fields:
  138. continue
  139. if isinstance(v, list):
  140. for val in v:
  141. hapd.set(f, val)
  142. else:
  143. hapd.set(f, v)
  144. hapd.enable()
  145. return hapd
  146. def add_bss(phy, ifname, confname, ignore_error=False):
  147. logger.info("Starting BSS phy=" + phy + " ifname=" + ifname)
  148. hapd_global = HostapdGlobal()
  149. hapd_global.add_bss(phy, confname, ignore_error)
  150. hapd = Hostapd(ifname)
  151. if not hapd.ping():
  152. raise Exception("Could not ping hostapd")
  153. def add_iface(ifname, confname):
  154. logger.info("Starting interface " + ifname)
  155. hapd_global = HostapdGlobal()
  156. hapd_global.add_iface(ifname, confname)
  157. hapd = Hostapd(ifname)
  158. if not hapd.ping():
  159. raise Exception("Could not ping hostapd")
  160. def remove_bss(ifname):
  161. logger.info("Removing BSS " + ifname)
  162. hapd_global = HostapdGlobal()
  163. hapd_global.remove(ifname)
  164. def wpa2_params(ssid=None, passphrase=None):
  165. params = { "wpa": "2",
  166. "wpa_key_mgmt": "WPA-PSK",
  167. "rsn_pairwise": "CCMP" }
  168. if ssid:
  169. params["ssid"] = ssid
  170. if passphrase:
  171. params["wpa_passphrase"] = passphrase
  172. return params
  173. def wpa_params(ssid=None, passphrase=None):
  174. params = { "wpa": "1",
  175. "wpa_key_mgmt": "WPA-PSK",
  176. "wpa_pairwise": "TKIP" }
  177. if ssid:
  178. params["ssid"] = ssid
  179. if passphrase:
  180. params["wpa_passphrase"] = passphrase
  181. return params
  182. def wpa_mixed_params(ssid=None, passphrase=None):
  183. params = { "wpa": "3",
  184. "wpa_key_mgmt": "WPA-PSK",
  185. "wpa_pairwise": "TKIP",
  186. "rsn_pairwise": "CCMP" }
  187. if ssid:
  188. params["ssid"] = ssid
  189. if passphrase:
  190. params["wpa_passphrase"] = passphrase
  191. return params
  192. def radius_params():
  193. params = { "auth_server_addr": "127.0.0.1",
  194. "auth_server_port": "1812",
  195. "auth_server_shared_secret": "radius",
  196. "nas_identifier": "nas.w1.fi" }
  197. return params
  198. def wpa2_eap_params(ssid=None):
  199. params = radius_params()
  200. params["wpa"] = "2"
  201. params["wpa_key_mgmt"] = "WPA-EAP"
  202. params["rsn_pairwise"] = "CCMP"
  203. params["ieee8021x"] = "1"
  204. if ssid:
  205. params["ssid"] = ssid
  206. return params