Browse Source

2020.03.13 / Folus Wen

Actions:
1. EVSE/GPL add hostapd 2.6
2. EVSE/Modularization/Module.c AP configuration method change from uaputl to hostapd.

Files:
1. As follow commit history

Image version: D0.00.XX.XXXX.XX
Image checksum: XXXXXXXX

Hardware PWB P/N : XXXXXXX
Hardware Version : XXXXXXX
FolusWen 5 years ago
parent
commit
9a24054c97
100 changed files with 36355 additions and 2 deletions
  1. 5 2
      EVSE/GPL/Makefile
  2. BIN
      EVSE/GPL/hostapd-2.6.tar.gz
  3. 171 0
      EVSE/GPL/hostapd-2.6/CONTRIBUTIONS
  4. 22 0
      EVSE/GPL/hostapd-2.6/COPYING
  5. 56 0
      EVSE/GPL/hostapd-2.6/README
  6. 346 0
      EVSE/GPL/hostapd-2.6/hostapd/.config
  7. 1001 0
      EVSE/GPL/hostapd-2.6/hostapd/Android.mk
  8. 1144 0
      EVSE/GPL/hostapd-2.6/hostapd/ChangeLog
  9. 1122 0
      EVSE/GPL/hostapd-2.6/hostapd/Makefile
  10. 366 0
      EVSE/GPL/hostapd-2.6/hostapd/README
  11. 352 0
      EVSE/GPL/hostapd-2.6/hostapd/README-WPS
  12. 201 0
      EVSE/GPL/hostapd-2.6/hostapd/android.config
  13. 3618 0
      EVSE/GPL/hostapd-2.6/hostapd/config_file.c
  14. 29 0
      EVSE/GPL/hostapd-2.6/hostapd/config_file.d
  15. 17 0
      EVSE/GPL/hostapd-2.6/hostapd/config_file.h
  16. 3755 0
      EVSE/GPL/hostapd-2.6/hostapd/ctrl_iface.c
  17. 49 0
      EVSE/GPL/hostapd-2.6/hostapd/ctrl_iface.d
  18. 39 0
      EVSE/GPL/hostapd-2.6/hostapd/ctrl_iface.h
  19. 345 0
      EVSE/GPL/hostapd-2.6/hostapd/defconfig
  20. 150 0
      EVSE/GPL/hostapd-2.6/hostapd/eap_register.c
  21. 10 0
      EVSE/GPL/hostapd-2.6/hostapd/eap_register.d
  22. 14 0
      EVSE/GPL/hostapd-2.6/hostapd/eap_register.h
  23. 77 0
      EVSE/GPL/hostapd-2.6/hostapd/eap_testing.txt
  24. 18 0
      EVSE/GPL/hostapd-2.6/hostapd/hapd_module_tests.c
  25. 1109 0
      EVSE/GPL/hostapd-2.6/hostapd/hlr_auc_gw.c
  26. 15 0
      EVSE/GPL/hostapd-2.6/hostapd/hlr_auc_gw.milenage_db
  27. 104 0
      EVSE/GPL/hostapd-2.6/hostapd/hlr_auc_gw.txt
  28. BIN
      EVSE/GPL/hostapd-2.6/hostapd/hostapd
  29. 59 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.8
  30. 6 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.accept
  31. 20 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.android.rc
  32. 1996 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.conf
  33. 5 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.deny
  34. 103 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.eap_user
  35. 26 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.eap_user_sqlite
  36. 4 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.radius_clients
  37. 9 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.sim_db
  38. 9 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.vlan
  39. 9 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd.wpa_psk
  40. BIN
      EVSE/GPL/hostapd-2.6/hostapd/hostapd_cli
  41. 89 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd_cli.1
  42. 1807 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd_cli.c
  43. 14 0
      EVSE/GPL/hostapd-2.6/hostapd/hostapd_cli.d
  44. 9 0
      EVSE/GPL/hostapd-2.6/hostapd/logwatch/README
  45. 65 0
      EVSE/GPL/hostapd-2.6/hostapd/logwatch/hostapd
  46. 10 0
      EVSE/GPL/hostapd-2.6/hostapd/logwatch/hostapd.conf
  47. 900 0
      EVSE/GPL/hostapd-2.6/hostapd/main.c
  48. 34 0
      EVSE/GPL/hostapd-2.6/hostapd/main.d
  49. 47 0
      EVSE/GPL/hostapd-2.6/hostapd/nt_password_hash.c
  50. 40 0
      EVSE/GPL/hostapd-2.6/hostapd/wired.conf
  51. 342 0
      EVSE/GPL/hostapd-2.6/hostapd/wps-ap-nfc.py
  52. BIN
      EVSE/GPL/hostapd-2.6/release/usr/local/bin/hostapd
  53. BIN
      EVSE/GPL/hostapd-2.6/release/usr/local/bin/hostapd_cli
  54. 12 0
      EVSE/GPL/hostapd-2.6/src/Makefile
  55. 67 0
      EVSE/GPL/hostapd-2.6/src/ap/Makefile
  56. 544 0
      EVSE/GPL/hostapd-2.6/src/ap/accounting.c
  57. 29 0
      EVSE/GPL/hostapd-2.6/src/ap/accounting.d
  58. 45 0
      EVSE/GPL/hostapd-2.6/src/ap/accounting.h
  59. 948 0
      EVSE/GPL/hostapd-2.6/src/ap/acs.c
  60. 27 0
      EVSE/GPL/hostapd-2.6/src/ap/acs.h
  61. 1033 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_config.c
  62. 29 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_config.d
  63. 737 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_config.h
  64. 874 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_drv_ops.c
  65. 24 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_drv_ops.d
  66. 350 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_drv_ops.h
  67. 312 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_list.c
  68. 25 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_list.d
  69. 58 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_list.h
  70. 181 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_mlme.c
  71. 24 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_mlme.d
  72. 34 0
      EVSE/GPL/hostapd-2.6/src/ap/ap_mlme.h
  73. 239 0
      EVSE/GPL/hostapd-2.6/src/ap/authsrv.c
  74. 32 0
      EVSE/GPL/hostapd-2.6/src/ap/authsrv.d
  75. 15 0
      EVSE/GPL/hostapd-2.6/src/ap/authsrv.h
  76. 1375 0
      EVSE/GPL/hostapd-2.6/src/ap/beacon.c
  77. 28 0
      EVSE/GPL/hostapd-2.6/src/ap/beacon.d
  78. 33 0
      EVSE/GPL/hostapd-2.6/src/ap/beacon.h
  79. 65 0
      EVSE/GPL/hostapd-2.6/src/ap/bss_load.c
  80. 23 0
      EVSE/GPL/hostapd-2.6/src/ap/bss_load.d
  81. 17 0
      EVSE/GPL/hostapd-2.6/src/ap/bss_load.h
  82. 641 0
      EVSE/GPL/hostapd-2.6/src/ap/ctrl_iface_ap.c
  83. 32 0
      EVSE/GPL/hostapd-2.6/src/ap/ctrl_iface_ap.d
  84. 36 0
      EVSE/GPL/hostapd-2.6/src/ap/ctrl_iface_ap.h
  85. 1068 0
      EVSE/GPL/hostapd-2.6/src/ap/dfs.c
  86. 22 0
      EVSE/GPL/hostapd-2.6/src/ap/dfs.d
  87. 30 0
      EVSE/GPL/hostapd-2.6/src/ap/dfs.h
  88. 179 0
      EVSE/GPL/hostapd-2.6/src/ap/dhcp_snoop.c
  89. 30 0
      EVSE/GPL/hostapd-2.6/src/ap/dhcp_snoop.h
  90. 1403 0
      EVSE/GPL/hostapd-2.6/src/ap/drv_callbacks.c
  91. 32 0
      EVSE/GPL/hostapd-2.6/src/ap/drv_callbacks.d
  92. 282 0
      EVSE/GPL/hostapd-2.6/src/ap/eap_user_db.c
  93. 26 0
      EVSE/GPL/hostapd-2.6/src/ap/eap_user_db.d
  94. 1507 0
      EVSE/GPL/hostapd-2.6/src/ap/gas_serv.c
  95. 83 0
      EVSE/GPL/hostapd-2.6/src/ap/gas_serv.h
  96. 3284 0
      EVSE/GPL/hostapd-2.6/src/ap/hostapd.c
  97. 41 0
      EVSE/GPL/hostapd-2.6/src/ap/hostapd.d
  98. 542 0
      EVSE/GPL/hostapd-2.6/src/ap/hostapd.h
  99. 177 0
      EVSE/GPL/hostapd-2.6/src/ap/hs20.c
  100. 22 0
      EVSE/GPL/hostapd-2.6/src/ap/hs20.h

+ 5 - 2
EVSE/GPL/Makefile

@@ -75,10 +75,13 @@ WPA :
 	cd wpa_supplicant-2.6/wpa_supplicant;make install DESTDIR=$(shell pwd)/wpa_supplicant-2.6/release
 	cp wpa_supplicant-2.6/release/usr/local/sbin/wpa_supplicant ../rootfs/root/
 	cp wpa_supplicant-2.6/wpa_supplicant/wpa_supplicant.conf ../rootfs/root/
-	
+	cd hostapd-2.6/hostapd;make CC=$(CROSS_COMPILE)gcc
+	cd hostapd-2.6/hostapd;make install DESTDIR=$(shell pwd)/hostapd-2.6/release
+	cp hostapd-2.6/release/release/usr/local/bin/hostapd ../rootfs/usr/bin/
+
 WirelessTool :
 	echo "wireless_tools.29"
-	make -C wireless_tools.29 CC=$(CROSS_COMPILE)gcc 
+	make -C wireless_tools.29 CC=$(CROSS_COMPILE)gcc
 	cp -f wireless_tools.29/libiw.so.29 ../rootfs/lib/
 	cp -f wireless_tools.29/iwconfig ../rootfs/root/
 	cp -f wireless_tools.29/iwlist ../rootfs/root/

BIN
EVSE/GPL/hostapd-2.6.tar.gz


+ 171 - 0
EVSE/GPL/hostapd-2.6/CONTRIBUTIONS

@@ -0,0 +1,171 @@
+Contributions to hostap.git
+---------------------------
+
+This software is distributed under a permissive open source license to
+allow it to be used in any projects, whether open source or proprietary.
+Contributions to the project are welcome and it is important to maintain
+clear record of contributions and terms under which they are licensed.
+To help with this, following procedure is used to allow acceptance and
+recording of the terms.
+
+All contributions are expected to be licensed under the modified BSD
+license (see below). Acknowledgment of the terms is tracked through
+inclusion of Signed-off-by tag in the contributions at the end of the
+commit log message. This tag indicates that the contributor agrees with
+the Developer Certificate of Origin (DCO) version 1.1 terms (see below;
+also available from http://developercertificate.org/).
+
+
+The current requirements for contributions to hostap.git
+--------------------------------------------------------
+
+To indicate your acceptance of Developer's Certificate of Origin 1.1
+terms, please add the following line to the end of the commit message
+for each contribution you make to the project:
+
+Signed-off-by: Your Name <your@email.example.org>
+
+using your real name. Pseudonyms or anonymous contributions cannot
+unfortunately be accepted.
+
+
+The preferred method of submitting the contribution to the project is by
+email to the hostap mailing list:
+hostap@lists.infradead.org
+Note that the list may require subscription before accepting message
+without moderation. You can subscribe to the list at this address:
+http://lists.infradead.org/mailman/listinfo/hostap
+
+The message should contain an inlined patch against the current
+development branch (i.e., the master branch of
+git://w1.fi/hostap.git). Please make sure the software you use for
+sending the patch does not corrupt whitespace. If that cannot be fixed
+for some reason, it is better to include an attached version of the
+patch file than just send a whitespace damaged version in the message
+body.
+
+The patches should be separate logical changes rather than doing
+everything in a single patch. In other words, please keep cleanup, new
+features, and bug fixes all in their own patches. Each patch needs a
+commit log that describes the changes (what the changes fix, what
+functionality is added, why the changes are useful, etc.).
+
+Please try to follow the coding style used in the project.
+
+In general, the best way of generating a suitable formatted patch file
+is by committing the changes to a cloned git repository and using git
+format-patch. The patch can then be sent, e.g., with git send-email.
+
+
+History of license and contributions terms
+------------------------------------------
+
+Until February 11, 2012, in case of most files in hostap.git, "under the
+open source license indicated in the file" means that the contribution
+is licensed both under GPL v2 and modified BSD license (see below) and
+the choice between these licenses is given to anyone who redistributes
+or uses the software. As such, the contribution has to be licensed under
+both options to allow this choice.
+
+As of February 11, 2012, the project has chosen to use only the BSD
+license option for future distribution. As such, the GPL v2 license
+option is no longer used and the contributions are not required to be
+licensed until GPL v2. In case of most files in hostap.git, "under the
+open source license indicated in the file" means that the contribution
+is licensed under the modified BSD license (see below).
+
+Until February 13, 2014, the project used an extended version of the DCO
+that included the identical items (a) through (d) from DCO 1.1 and an
+additional item (e):
+
+(e) The contribution can be licensed under the modified BSD license
+    as shown below even in case of files that are currently licensed
+    under other terms.
+
+This was used during the period when some of the files included the old
+license terms. Acceptance of this extended DCO version was indicated
+with a Signed-hostap tag in the commit message. This additional item (e)
+was used to collect explicit approval to license the contribution with
+only the modified BSD license (see below), i.e., without the GPL v2
+option. This was done to allow simpler licensing terms to be used in the
+future. It should be noted that the modified BSD license is compatible
+with GNU GPL and as such, this possible move to simpler licensing option
+does not prevent use of this software in GPL projects.
+
+
+===[ start quote from http://developercertificate.org/ ]=======================
+
+Developer Certificate of Origin
+Version 1.1
+
+Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
+660 York Street, Suite 102,
+San Francisco, CA 94110 USA
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+
+Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+    have the right to submit it under the open source license
+    indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+    of my knowledge, is covered under an appropriate open source
+    license and I have the right under that license to submit that
+    work with modifications, whether created in whole or in part
+    by me, under the same open source license (unless I am
+    permitted to submit under a different license), as indicated
+    in the file; or
+
+(c) The contribution was provided directly to me by some other
+    person who certified (a), (b) or (c) and I have not modified
+    it.
+
+(d) I understand and agree that this project and the contribution
+    are public and that a record of the contribution (including all
+    personal information I submit with it, including my sign-off) is
+    maintained indefinitely and may be redistributed consistent with
+    this project or the open source license(s) involved.
+
+===[ end quote from http://developercertificate.org/ ]=========================
+
+
+The license terms used for hostap.git files
+-------------------------------------------
+
+Modified BSD license (no advertisement clause):
+
+Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. Neither the name(s) of the above-listed copyright holder(s) nor the
+   names of its contributors may be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 22 - 0
EVSE/GPL/hostapd-2.6/COPYING

@@ -0,0 +1,22 @@
+wpa_supplicant and hostapd
+--------------------------
+
+Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+
+See the README file for the current license terms.
+
+This software was previously distributed under BSD/GPL v2 dual license
+terms that allowed either of those license alternatives to be
+selected. As of February 11, 2012, the project has chosen to use only
+the BSD license option for future distribution. As such, the GPL v2
+license option is no longer used. It should be noted that the BSD
+license option (the one with advertisement clause removed) is compatible
+with GPL and as such, does not prevent use of this software in projects
+that use GPL.
+
+Some of the files may still include pointers to GPL version 2 license
+terms. However, such copyright and license notifications are maintained
+only for attribution purposes and any distribution of this software
+after February 11, 2012 is no longer under the GPL v2 option.

+ 56 - 0
EVSE/GPL/hostapd-2.6/README

@@ -0,0 +1,56 @@
+wpa_supplicant and hostapd
+--------------------------
+
+Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+These programs are licensed under the BSD license (the one with
+advertisement clause removed).
+
+If you are submitting changes to the project, please see CONTRIBUTIONS
+file for more instructions.
+
+
+This package may include either wpa_supplicant, hostapd, or both. See
+README file respective subdirectories (wpa_supplicant/README or
+hostapd/README) for more details.
+
+Source code files were moved around in v0.6.x releases and compared to
+earlier releases, the programs are now built by first going to a
+subdirectory (wpa_supplicant or hostapd) and creating build
+configuration (.config) and running 'make' there (for Linux/BSD/cygwin
+builds).
+
+
+License
+-------
+
+This software may be distributed, used, and modified under the terms of
+BSD license:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. Neither the name(s) of the above-listed copyright holder(s) nor the
+   names of its contributors may be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 346 - 0
EVSE/GPL/hostapd-2.6/hostapd/.config

@@ -0,0 +1,346 @@
+# Example hostapd build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cass, these lines should use += in order not
+# to override previous values of the variables.
+
+# Driver interface for Host AP driver
+CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for wired authenticator
+#CONFIG_DRIVER_WIRED=y
+
+# Driver interface for drivers using the nl80211 kernel interface
+CONFIG_DRIVER_NL80211=y
+CFLAGS += -I/opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/libnl-3.2.25/release/include/libnl3
+CONFIG_LIBNL32=y
+# QCA vendor extensions to nl80211
+#CONFIG_DRIVER_NL80211_QCA=y
+
+# driver_nl80211.c requires libnl. If you are compiling it yourself
+# you may need to point hostapd to your version of libnl.
+#
+#CFLAGS += -I$<path to libnl include files>
+#LIBS += -L$<path to libnl library files>
+
+# Use libnl v2.0 (or 3.0) libraries.
+#CONFIG_LIBNL20=y
+
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
+#CONFIG_LIBNL32=y
+
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+#LIBS_p += -L/usr/local/lib
+#LIBS_c += -L/usr/local/lib
+
+# Driver interface for no driver (e.g., RADIUS server only)
+#CONFIG_DRIVER_NONE=y
+
+# IEEE 802.11F/IAPP
+CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+CONFIG_IEEE80211W=y
+
+# Integrated EAP server
+CONFIG_EAP=y
+
+# EAP Re-authentication Protocol (ERP) in integrated EAP server
+CONFIG_ERP=y
+
+# EAP-MD5 for the integrated EAP server
+CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP server
+CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP server
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP server
+CONFIG_EAP_PEAP=y
+
+# EAP-GTC for the integrated EAP server
+CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP server
+CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP server
+#CONFIG_EAP_SIM=y
+
+# EAP-AKA for the integrated EAP server
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' for the integrated EAP server
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# EAP-PAX for the integrated EAP server
+#CONFIG_EAP_PAX=y
+
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-pwd for the integrated EAP server (secure authentication with a password)
+#CONFIG_EAP_PWD=y
+
+# EAP-SAKE for the integrated EAP server
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK for the integrated EAP server
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-FAST for the integrated EAP server
+# Note: If OpenSSL is used as the TLS library, OpenSSL 1.0 or newer is needed
+# for EAP-FAST support. Older OpenSSL releases would need to be patched, e.g.,
+# with openssl-0.9.8x-tls-extensions.patch, to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# Wi-Fi Protected Setup (WPS)
+#CONFIG_WPS=y
+# Enable UPnP support for external WPS Registrars
+#CONFIG_WPS_UPNP=y
+# Enable WPS support with NFC config method
+#CONFIG_WPS_NFC=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# Trusted Network Connect (EAP-TNC)
+#CONFIG_EAP_TNC=y
+
+# EAP-EKE for the integrated EAP server
+#CONFIG_EAP_EKE=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# RADIUS authentication server. This provides access to the integrated EAP
+# server from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
+
+# Build IPv6 support for RADIUS operations
+CONFIG_IPV6=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
+# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
+#CONFIG_DRIVER_RADIUS_ACL=y
+
+# IEEE 802.11n (High Throughput) support
+#CONFIG_IEEE80211N=y
+
+# Wireless Network Management (IEEE Std 802.11v-2011)
+# Note: This is experimental and not complete implementation.
+#CONFIG_WNM=y
+
+# IEEE 802.11ac (Very High Throughput) support
+#CONFIG_IEEE80211AC=y
+
+# Remove debugging code that is printing out debug messages to stdout.
+# This can be used to reduce the size of the hostapd considerably if debugging
+# code is not needed.
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Add support for writing debug log to a file: -f /tmp/hostapd.log
+# Disabled by default.
+#CONFIG_DEBUG_FILE=y
+
+# Add support for sending all debug messages (regardless of debug verbosity)
+# to the Linux kernel tracing facility. This helps debug the entire stack by
+# making it easy to record everything happening from the driver up into the
+# same file, e.g., using trace-cmd.
+#CONFIG_DEBUG_LINUX_TRACING=y
+
+# Remove support for RADIUS accounting
+#CONFIG_NO_ACCOUNTING=y
+
+# Remove support for RADIUS
+#CONFIG_NO_RADIUS=y
+
+# Remove support for VLANs
+#CONFIG_NO_VLAN=y
+
+# Enable support for fully dynamic VLANs. This enables hostapd to
+# automatically create bridge and VLAN interfaces if necessary.
+#CONFIG_FULL_DYNAMIC_VLAN=y
+
+# Use netlink-based kernel API for VLAN operations instead of ioctl()
+# Note: This requires libnl 3.1 or newer.
+#CONFIG_VLAN_NETLINK=y
+
+# Remove support for dumping internal state through control interface commands
+# This can be used to reduce binary size at the cost of disabling a debugging
+# option.
+#CONFIG_NO_DUMP_STATE=y
+
+# Enable tracing code for developer debugging
+# This tracks use of memory allocations and other registrations and reports
+# incorrect use with a backtrace of call (or allocation) location.
+#CONFIG_WPA_TRACE=y
+# For BSD, comment out these.
+#LIBS += -lexecinfo
+#LIBS_p += -lexecinfo
+#LIBS_c += -lexecinfo
+
+# Use libbfd to get more details for developer debugging
+# This enables use of libbfd to get more detailed symbols for the backtraces
+# generated by CONFIG_WPA_TRACE=y.
+#CONFIG_WPA_TRACE_BFD=y
+# For BSD, comment out these.
+#LIBS += -lbfd -liberty -lz
+#LIBS_p += -lbfd -liberty -lz
+#LIBS_c += -lbfd -liberty -lz
+
+# hostapd depends on strong random number generation being available from the
+# operating system. os_get_random() function is used to fetch random data when
+# needed, e.g., for key generation. On Linux and BSD systems, this works by
+# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
+# properly initialized before hostapd is started. This is important especially
+# on embedded devices that do not have a hardware random number generator and
+# may by default start up with minimal entropy available for random number
+# generation.
+#
+# As a safety net, hostapd is by default trying to internally collect
+# additional entropy for generating random data to mix in with the data
+# fetched from the OS. This by itself is not considered to be very strong, but
+# it may help in cases where the system pool is not initialized properly.
+# However, it is very strongly recommended that the system pool is initialized
+# with enough entropy either by using hardware assisted random number
+# generator or by storing state over device reboots.
+#
+# hostapd can be configured to maintain its own entropy store over restarts to
+# enhance random number generation. This is not perfect, but it is much more
+# secure than using the same sequence of random numbers after every reboot.
+# This can be enabled with -e<entropy file> command line option. The specified
+# file needs to be readable and writable by hostapd.
+#
+# If the os_get_random() is known to provide strong random data (e.g., on
+# Linux/BSD, the board in question is known to have reliable source of random
+# data from /dev/urandom), the internal hostapd random pool can be disabled.
+# This will save some in binary size and CPU use. However, this should only be
+# considered for builds that are known to be used on devices that meet the
+# requirements described above.
+#CONFIG_NO_RANDOM_POOL=y
+
+# Should we use poll instead of select? Select is used by default.
+#CONFIG_ELOOP_POLL=y
+
+# Should we use epoll instead of select? Select is used by default.
+#CONFIG_ELOOP_EPOLL=y
+
+# Should we use kqueue instead of select? Select is used by default.
+#CONFIG_ELOOP_KQUEUE=y
+
+# Select TLS implementation
+# openssl = OpenSSL (default)
+# gnutls = GnuTLS
+# internal = Internal TLSv1 implementation (experimental)
+# none = Empty template
+#CONFIG_TLS=openssl
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
+# can be enabled to get a stronger construction of messages when block ciphers
+# are used.
+#CONFIG_TLSV11=y
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
+# can be enabled to enable use of stronger crypto algorithms.
+#CONFIG_TLSV12=y
+
+# If CONFIG_TLS=internal is used, additional library and include paths are
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
+# and drawbacks of this option.
+#CONFIG_INTERNAL_LIBTOMMATH=y
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
+#LTM_PATH=/usr/src/libtommath-0.39
+#CFLAGS += -I$(LTM_PATH)
+#LIBS += -L$(LTM_PATH)
+#LIBS_p += -L$(LTM_PATH)
+#endif
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
+# can be configured to include faster routines for exptmod, sqr, and div to
+# speed up DH and RSA calculation considerably
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
+
+# Interworking (IEEE 802.11u)
+# This can be used to enable functionality to improve interworking with
+# external networks.
+#CONFIG_INTERWORKING=y
+
+# Hotspot 2.0
+#CONFIG_HS20=y
+
+# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
+#CONFIG_SQLITE=y
+
+# Enable Fast Session Transfer (FST)
+#CONFIG_FST=y
+
+# Enable CLI commands for FST testing
+#CONFIG_FST_TEST=y
+
+# Testing options
+# This can be used to enable some testing options (see also the example
+# configuration file) that are really useful only for testing clients that
+# connect to this hostapd. These options allow, for example, to drop a
+# certain percentage of probe requests or auth/(re)assoc frames.
+#
+#CONFIG_TESTING_OPTIONS=y
+
+# Automatic Channel Selection
+# This will allow hostapd to pick the channel automatically when channel is set
+# to "acs_survey" or "0". Eventually, other ACS algorithms can be added in
+# similar way.
+#
+# Automatic selection is currently only done through initialization, later on
+# we hope to do background checks to keep us moving to more ideal channels as
+# time goes by. ACS is currently only supported through the nl80211 driver and
+# your driver must have survey dump capability that is filled by the driver
+# during scanning.
+#
+# You can customize the ACS survey algorithm with the hostapd.conf variable
+# acs_num_scans.
+#
+# Supported ACS drivers:
+# * ath9k
+# * ath5k
+# * ath10k
+#
+# For more details refer to:
+# http://wireless.kernel.org/en/users/Documentation/acs
+#
+#CONFIG_ACS=y
+
+# Multiband Operation support
+# These extentions facilitate efficient use of multiple frequency bands
+# available to the AP and the devices that may associate with it.
+#CONFIG_MBO=y
+
+# Client Taxonomy
+# Has the AP retain the Probe Request and (Re)Association Request frames from
+# a client, from which a signature can be produced which can identify the model
+# of client device like "Nexus 6P" or "iPhone 5s".
+#CONFIG_TAXONOMY=y

+ 1001 - 0
EVSE/GPL/hostapd-2.6/hostapd/Android.mk

@@ -0,0 +1,1001 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+WPA_BUILD_HOSTAPD := false
+ifneq ($(BOARD_HOSTAPD_DRIVER),)
+  WPA_BUILD_HOSTAPD := true
+  CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y
+endif
+
+ifeq ($(WPA_BUILD_HOSTAPD),true)
+
+include $(LOCAL_PATH)/android.config
+
+# To ignore possible wrong network configurations
+L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS
+
+L_CFLAGS += -DVERSION_STR_POSTFIX=\"-$(PLATFORM_VERSION)\"
+
+# Set Android log name
+L_CFLAGS += -DANDROID_LOG_NAME=\"hostapd\"
+
+# Disable unused parameter warnings
+L_CFLAGS += -Wno-unused-parameter
+
+# Set Android extended P2P functionality
+L_CFLAGS += -DANDROID_P2P
+
+ifeq ($(BOARD_HOSTAPD_PRIVATE_LIB),)
+L_CFLAGS += -DANDROID_LIB_STUB
+endif
+
+# Use Android specific directory for control interface sockets
+L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
+L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/system/hostapd\"
+
+# To force sizeof(enum) = 4
+ifeq ($(TARGET_ARCH),arm)
+L_CFLAGS += -mabi=aapcs-linux
+endif
+
+INCLUDES = $(LOCAL_PATH)
+INCLUDES += $(LOCAL_PATH)/src
+INCLUDES += $(LOCAL_PATH)/src/utils
+INCLUDES += system/security/keystore/include
+ifdef CONFIG_DRIVER_NL80211
+ifneq ($(wildcard external/libnl),)
+INCLUDES += external/libnl/include
+else
+INCLUDES += external/libnl-headers
+endif
+endif
+
+
+ifndef CONFIG_OS
+ifdef CONFIG_NATIVE_WINDOWS
+CONFIG_OS=win32
+else
+CONFIG_OS=unix
+endif
+endif
+
+ifeq ($(CONFIG_OS), internal)
+L_CFLAGS += -DOS_NO_C_LIB_DEFINES
+endif
+
+ifdef CONFIG_NATIVE_WINDOWS
+L_CFLAGS += -DCONFIG_NATIVE_WINDOWS
+LIBS += -lws2_32
+endif
+
+OBJS = main.c
+OBJS += config_file.c
+
+OBJS += src/ap/hostapd.c
+OBJS += src/ap/wpa_auth_glue.c
+OBJS += src/ap/drv_callbacks.c
+OBJS += src/ap/ap_drv_ops.c
+OBJS += src/ap/utils.c
+OBJS += src/ap/authsrv.c
+OBJS += src/ap/ieee802_1x.c
+OBJS += src/ap/ap_config.c
+OBJS += src/ap/eap_user_db.c
+OBJS += src/ap/ieee802_11_auth.c
+OBJS += src/ap/sta_info.c
+OBJS += src/ap/wpa_auth.c
+OBJS += src/ap/tkip_countermeasures.c
+OBJS += src/ap/ap_mlme.c
+OBJS += src/ap/wpa_auth_ie.c
+OBJS += src/ap/preauth_auth.c
+OBJS += src/ap/pmksa_cache_auth.c
+OBJS += src/ap/ieee802_11_shared.c
+OBJS += src/ap/beacon.c
+OBJS += src/ap/bss_load.c
+OBJS += src/ap/neighbor_db.c
+OBJS += src/ap/rrm.c
+OBJS_d =
+OBJS_p =
+LIBS =
+LIBS_c =
+HOBJS =
+LIBS_h =
+
+NEED_RC4=y
+NEED_AES=y
+NEED_MD5=y
+NEED_SHA1=y
+
+OBJS += src/drivers/drivers.c
+L_CFLAGS += -DHOSTAPD
+
+ifdef CONFIG_WPA_TRACE
+L_CFLAGS += -DWPA_TRACE
+OBJS += src/utils/trace.c
+HOBJS += src/utils/trace.c
+LDFLAGS += -rdynamic
+L_CFLAGS += -funwind-tables
+ifdef CONFIG_WPA_TRACE_BFD
+L_CFLAGS += -DWPA_TRACE_BFD
+LIBS += -lbfd
+LIBS_c += -lbfd
+LIBS_h += -lbfd
+endif
+endif
+
+OBJS += src/utils/eloop.c
+
+ifdef CONFIG_ELOOP_POLL
+L_CFLAGS += -DCONFIG_ELOOP_POLL
+endif
+
+ifdef CONFIG_ELOOP_EPOLL
+L_CFLAGS += -DCONFIG_ELOOP_EPOLL
+endif
+
+OBJS += src/utils/common.c
+OBJS += src/utils/wpa_debug.c
+OBJS += src/utils/wpabuf.c
+OBJS += src/utils/os_$(CONFIG_OS).c
+OBJS += src/utils/ip_addr.c
+
+OBJS += src/common/ieee802_11_common.c
+OBJS += src/common/wpa_common.c
+OBJS += src/common/hw_features_common.c
+
+OBJS += src/eapol_auth/eapol_auth_sm.c
+
+
+ifndef CONFIG_NO_DUMP_STATE
+# define HOSTAPD_DUMP_STATE to include support for dumping internal state
+# through control interface commands (undefine it, if you want to save in
+# binary size)
+L_CFLAGS += -DHOSTAPD_DUMP_STATE
+OBJS += src/eapol_auth/eapol_auth_dump.c
+endif
+
+ifdef CONFIG_NO_RADIUS
+L_CFLAGS += -DCONFIG_NO_RADIUS
+CONFIG_NO_ACCOUNTING=y
+else
+OBJS += src/radius/radius.c
+OBJS += src/radius/radius_client.c
+OBJS += src/radius/radius_das.c
+endif
+
+ifdef CONFIG_NO_ACCOUNTING
+L_CFLAGS += -DCONFIG_NO_ACCOUNTING
+else
+OBJS += src/ap/accounting.c
+endif
+
+ifdef CONFIG_NO_VLAN
+L_CFLAGS += -DCONFIG_NO_VLAN
+else
+OBJS += src/ap/vlan_init.c
+OBJS += src/ap/vlan_ifconfig.c
+OBJS += src/ap/vlan.c
+ifdef CONFIG_FULL_DYNAMIC_VLAN
+# Define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
+# and VLAN interfaces for the VLAN feature.
+L_CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
+OBJS += src/ap/vlan_full.c
+ifdef CONFIG_VLAN_NETLINK
+OBJS += src/ap/vlan_util.c
+else
+OBJS += src/ap/vlan_ioctl.c
+endif
+endif
+endif
+
+ifdef CONFIG_NO_CTRL_IFACE
+L_CFLAGS += -DCONFIG_NO_CTRL_IFACE
+else
+OBJS += src/common/ctrl_iface_common.c
+OBJS += ctrl_iface.c
+OBJS += src/ap/ctrl_iface_ap.c
+endif
+
+L_CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
+
+ifdef CONFIG_IAPP
+L_CFLAGS += -DCONFIG_IAPP
+OBJS += src/ap/iapp.c
+endif
+
+ifdef CONFIG_RSN_PREAUTH
+L_CFLAGS += -DCONFIG_RSN_PREAUTH
+CONFIG_L2_PACKET=y
+endif
+
+ifdef CONFIG_PEERKEY
+L_CFLAGS += -DCONFIG_PEERKEY
+OBJS += src/ap/peerkey_auth.c
+endif
+
+ifdef CONFIG_HS20
+NEED_AES_OMAC1=y
+CONFIG_PROXYARP=y
+endif
+
+ifdef CONFIG_PROXYARP
+CONFIG_L2_PACKET=y
+endif
+
+ifdef CONFIG_SUITEB
+L_CFLAGS += -DCONFIG_SUITEB
+NEED_SHA256=y
+NEED_AES_OMAC1=y
+endif
+
+ifdef CONFIG_SUITEB192
+L_CFLAGS += -DCONFIG_SUITEB192
+NEED_SHA384=y
+endif
+
+ifdef CONFIG_IEEE80211W
+L_CFLAGS += -DCONFIG_IEEE80211W
+NEED_SHA256=y
+NEED_AES_OMAC1=y
+endif
+
+ifdef CONFIG_IEEE80211R
+L_CFLAGS += -DCONFIG_IEEE80211R
+OBJS += src/ap/wpa_auth_ft.c
+NEED_SHA256=y
+NEED_AES_OMAC1=y
+NEED_AES_UNWRAP=y
+endif
+
+ifdef CONFIG_SAE
+L_CFLAGS += -DCONFIG_SAE
+OBJS += src/common/sae.c
+NEED_ECC=y
+NEED_DH_GROUPS=y
+endif
+
+ifdef CONFIG_WNM
+L_CFLAGS += -DCONFIG_WNM
+OBJS += src/ap/wnm_ap.c
+endif
+
+ifdef CONFIG_IEEE80211N
+L_CFLAGS += -DCONFIG_IEEE80211N
+endif
+
+ifdef CONFIG_IEEE80211AC
+L_CFLAGS += -DCONFIG_IEEE80211AC
+endif
+
+ifdef CONFIG_MBO
+L_CFLAGS += -DCONFIG_MBO
+OBJS += src/ap/mbo_ap.c
+endif
+
+ifdef CONFIG_FST
+L_CFLAGS += -DCONFIG_FST
+OBJS += src/fst/fst.c
+OBJS += src/fst/fst_group.c
+OBJS += src/fst/fst_iface.c
+OBJS += src/fst/fst_session.c
+OBJS += src/fst/fst_ctrl_aux.c
+ifdef CONFIG_FST_TEST
+L_CFLAGS += -DCONFIG_FST_TEST
+endif
+ifndef CONFIG_NO_CTRL_IFACE
+OBJS += src/fst/fst_ctrl_iface.c
+endif
+endif
+
+
+include $(LOCAL_PATH)/src/drivers/drivers.mk
+
+OBJS += $(DRV_AP_OBJS)
+L_CFLAGS += $(DRV_AP_CFLAGS)
+LDFLAGS += $(DRV_AP_LDFLAGS)
+LIBS += $(DRV_AP_LIBS)
+
+ifdef CONFIG_L2_PACKET
+ifdef CONFIG_DNET_PCAP
+ifdef CONFIG_L2_FREEBSD
+LIBS += -lpcap
+OBJS += src/l2_packet/l2_packet_freebsd.c
+else
+LIBS += -ldnet -lpcap
+OBJS += src/l2_packet/l2_packet_pcap.c
+endif
+else
+OBJS += src/l2_packet/l2_packet_linux.c
+endif
+else
+OBJS += src/l2_packet/l2_packet_none.c
+endif
+
+
+ifdef CONFIG_EAP_MD5
+L_CFLAGS += -DEAP_SERVER_MD5
+OBJS += src/eap_server/eap_server_md5.c
+CHAP=y
+endif
+
+ifdef CONFIG_EAP_TLS
+L_CFLAGS += -DEAP_SERVER_TLS
+OBJS += src/eap_server/eap_server_tls.c
+TLS_FUNCS=y
+endif
+
+ifdef CONFIG_EAP_UNAUTH_TLS
+L_CFLAGS += -DEAP_SERVER_UNAUTH_TLS
+ifndef CONFIG_EAP_TLS
+OBJS += src/eap_server/eap_server_tls.c
+TLS_FUNCS=y
+endif
+endif
+
+ifdef CONFIG_EAP_PEAP
+L_CFLAGS += -DEAP_SERVER_PEAP
+OBJS += src/eap_server/eap_server_peap.c
+OBJS += src/eap_common/eap_peap_common.c
+TLS_FUNCS=y
+CONFIG_EAP_MSCHAPV2=y
+endif
+
+ifdef CONFIG_EAP_TTLS
+L_CFLAGS += -DEAP_SERVER_TTLS
+OBJS += src/eap_server/eap_server_ttls.c
+TLS_FUNCS=y
+CHAP=y
+endif
+
+ifdef CONFIG_EAP_MSCHAPV2
+L_CFLAGS += -DEAP_SERVER_MSCHAPV2
+OBJS += src/eap_server/eap_server_mschapv2.c
+MS_FUNCS=y
+endif
+
+ifdef CONFIG_EAP_GTC
+L_CFLAGS += -DEAP_SERVER_GTC
+OBJS += src/eap_server/eap_server_gtc.c
+endif
+
+ifdef CONFIG_EAP_SIM
+L_CFLAGS += -DEAP_SERVER_SIM
+OBJS += src/eap_server/eap_server_sim.c
+CONFIG_EAP_SIM_COMMON=y
+NEED_AES_CBC=y
+endif
+
+ifdef CONFIG_EAP_AKA
+L_CFLAGS += -DEAP_SERVER_AKA
+OBJS += src/eap_server/eap_server_aka.c
+CONFIG_EAP_SIM_COMMON=y
+NEED_SHA256=y
+NEED_AES_CBC=y
+endif
+
+ifdef CONFIG_EAP_AKA_PRIME
+L_CFLAGS += -DEAP_SERVER_AKA_PRIME
+endif
+
+ifdef CONFIG_EAP_SIM_COMMON
+OBJS += src/eap_common/eap_sim_common.c
+# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
+# replaced with another file implementating the interface specified in
+# eap_sim_db.h.
+OBJS += src/eap_server/eap_sim_db.c
+NEED_FIPS186_2_PRF=y
+endif
+
+ifdef CONFIG_EAP_PAX
+L_CFLAGS += -DEAP_SERVER_PAX
+OBJS += src/eap_server/eap_server_pax.c src/eap_common/eap_pax_common.c
+endif
+
+ifdef CONFIG_EAP_PSK
+L_CFLAGS += -DEAP_SERVER_PSK
+OBJS += src/eap_server/eap_server_psk.c src/eap_common/eap_psk_common.c
+NEED_AES_OMAC1=y
+NEED_AES_ENCBLOCK=y
+NEED_AES_EAX=y
+endif
+
+ifdef CONFIG_EAP_SAKE
+L_CFLAGS += -DEAP_SERVER_SAKE
+OBJS += src/eap_server/eap_server_sake.c src/eap_common/eap_sake_common.c
+endif
+
+ifdef CONFIG_EAP_GPSK
+L_CFLAGS += -DEAP_SERVER_GPSK
+OBJS += src/eap_server/eap_server_gpsk.c src/eap_common/eap_gpsk_common.c
+ifdef CONFIG_EAP_GPSK_SHA256
+L_CFLAGS += -DEAP_GPSK_SHA256
+endif
+NEED_SHA256=y
+NEED_AES_OMAC1=y
+endif
+
+ifdef CONFIG_EAP_PWD
+L_CFLAGS += -DEAP_SERVER_PWD
+OBJS += src/eap_server/eap_server_pwd.c src/eap_common/eap_pwd_common.c
+NEED_SHA256=y
+endif
+
+ifdef CONFIG_EAP_EKE
+L_CFLAGS += -DEAP_SERVER_EKE
+OBJS += src/eap_server/eap_server_eke.c src/eap_common/eap_eke_common.c
+NEED_DH_GROUPS=y
+NEED_DH_GROUPS_ALL=y
+endif
+
+ifdef CONFIG_EAP_VENDOR_TEST
+L_CFLAGS += -DEAP_SERVER_VENDOR_TEST
+OBJS += src/eap_server/eap_server_vendor_test.c
+endif
+
+ifdef CONFIG_EAP_FAST
+L_CFLAGS += -DEAP_SERVER_FAST
+OBJS += src/eap_server/eap_server_fast.c
+OBJS += src/eap_common/eap_fast_common.c
+TLS_FUNCS=y
+NEED_T_PRF=y
+NEED_AES_UNWRAP=y
+endif
+
+ifdef CONFIG_WPS
+L_CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
+OBJS += src/utils/uuid.c
+OBJS += src/ap/wps_hostapd.c
+OBJS += src/eap_server/eap_server_wsc.c src/eap_common/eap_wsc_common.c
+OBJS += src/wps/wps.c
+OBJS += src/wps/wps_common.c
+OBJS += src/wps/wps_attr_parse.c
+OBJS += src/wps/wps_attr_build.c
+OBJS += src/wps/wps_attr_process.c
+OBJS += src/wps/wps_dev_attr.c
+OBJS += src/wps/wps_enrollee.c
+OBJS += src/wps/wps_registrar.c
+NEED_DH_GROUPS=y
+NEED_SHA256=y
+NEED_BASE64=y
+NEED_AES_CBC=y
+NEED_MODEXP=y
+CONFIG_EAP=y
+
+ifdef CONFIG_WPS_NFC
+L_CFLAGS += -DCONFIG_WPS_NFC
+OBJS += src/wps/ndef.c
+NEED_WPS_OOB=y
+endif
+
+ifdef NEED_WPS_OOB
+L_CFLAGS += -DCONFIG_WPS_OOB
+endif
+
+ifdef CONFIG_WPS_UPNP
+L_CFLAGS += -DCONFIG_WPS_UPNP
+OBJS += src/wps/wps_upnp.c
+OBJS += src/wps/wps_upnp_ssdp.c
+OBJS += src/wps/wps_upnp_web.c
+OBJS += src/wps/wps_upnp_event.c
+OBJS += src/wps/wps_upnp_ap.c
+OBJS += src/wps/upnp_xml.c
+OBJS += src/wps/httpread.c
+OBJS += src/wps/http_client.c
+OBJS += src/wps/http_server.c
+endif
+
+ifdef CONFIG_WPS_STRICT
+L_CFLAGS += -DCONFIG_WPS_STRICT
+OBJS += src/wps/wps_validate.c
+endif
+
+ifdef CONFIG_WPS_TESTING
+L_CFLAGS += -DCONFIG_WPS_TESTING
+endif
+
+endif
+
+ifdef CONFIG_EAP_IKEV2
+L_CFLAGS += -DEAP_SERVER_IKEV2
+OBJS += src/eap_server/eap_server_ikev2.c src/eap_server/ikev2.c
+OBJS += src/eap_common/eap_ikev2_common.c src/eap_common/ikev2_common.c
+NEED_DH_GROUPS=y
+NEED_DH_GROUPS_ALL=y
+NEED_MODEXP=y
+NEED_CIPHER=y
+endif
+
+ifdef CONFIG_EAP_TNC
+L_CFLAGS += -DEAP_SERVER_TNC
+OBJS += src/eap_server/eap_server_tnc.c
+OBJS += src/eap_server/tncs.c
+NEED_BASE64=y
+ifndef CONFIG_DRIVER_BSD
+LIBS += -ldl
+endif
+endif
+
+# Basic EAP functionality is needed for EAPOL
+OBJS += eap_register.c
+OBJS += src/eap_server/eap_server.c
+OBJS += src/eap_common/eap_common.c
+OBJS += src/eap_server/eap_server_methods.c
+OBJS += src/eap_server/eap_server_identity.c
+L_CFLAGS += -DEAP_SERVER_IDENTITY
+
+ifdef CONFIG_EAP
+L_CFLAGS += -DEAP_SERVER
+endif
+
+ifdef CONFIG_PKCS12
+L_CFLAGS += -DPKCS12_FUNCS
+endif
+
+ifdef MS_FUNCS
+OBJS += src/crypto/ms_funcs.c
+NEED_DES=y
+NEED_MD4=y
+endif
+
+ifdef CHAP
+OBJS += src/eap_common/chap.c
+endif
+
+ifdef TLS_FUNCS
+NEED_DES=y
+# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
+L_CFLAGS += -DEAP_TLS_FUNCS
+OBJS += src/eap_server/eap_server_tls_common.c
+NEED_TLS_PRF=y
+endif
+
+ifndef CONFIG_TLS
+CONFIG_TLS=openssl
+endif
+
+ifdef CONFIG_TLSV11
+L_CFLAGS += -DCONFIG_TLSV11
+endif
+
+ifdef CONFIG_TLSV12
+L_CFLAGS += -DCONFIG_TLSV12
+NEED_SHA256=y
+endif
+
+ifeq ($(CONFIG_TLS), openssl)
+ifdef TLS_FUNCS
+OBJS += src/crypto/tls_openssl.c
+OBJS += src/crypto/tls_openssl_ocsp.c
+LIBS += -lssl
+endif
+OBJS += src/crypto/crypto_openssl.c
+HOBJS += src/crypto/crypto_openssl.c
+ifdef NEED_FIPS186_2_PRF
+OBJS += src/crypto/fips_prf_openssl.c
+endif
+NEED_SHA256=y
+NEED_TLS_PRF_SHA256=y
+LIBS += -lcrypto
+LIBS_h += -lcrypto
+endif
+
+ifeq ($(CONFIG_TLS), gnutls)
+ifdef TLS_FUNCS
+OBJS += src/crypto/tls_gnutls.c
+LIBS += -lgnutls -lgpg-error
+endif
+OBJS += src/crypto/crypto_gnutls.c
+HOBJS += src/crypto/crypto_gnutls.c
+ifdef NEED_FIPS186_2_PRF
+OBJS += src/crypto/fips_prf_internal.c
+OBJS += src/crypto/sha1-internal.c
+endif
+LIBS += -lgcrypt
+LIBS_h += -lgcrypt
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+
+ifeq ($(CONFIG_TLS), internal)
+ifndef CONFIG_CRYPTO
+CONFIG_CRYPTO=internal
+endif
+ifdef TLS_FUNCS
+OBJS += src/crypto/crypto_internal-rsa.c
+OBJS += src/crypto/tls_internal.c
+OBJS += src/tls/tlsv1_common.c
+OBJS += src/tls/tlsv1_record.c
+OBJS += src/tls/tlsv1_cred.c
+OBJS += src/tls/tlsv1_server.c
+OBJS += src/tls/tlsv1_server_write.c
+OBJS += src/tls/tlsv1_server_read.c
+OBJS += src/tls/asn1.c
+OBJS += src/tls/rsa.c
+OBJS += src/tls/x509v3.c
+OBJS += src/tls/pkcs1.c
+OBJS += src/tls/pkcs5.c
+OBJS += src/tls/pkcs8.c
+NEED_SHA256=y
+NEED_BASE64=y
+NEED_TLS_PRF=y
+ifdef CONFIG_TLSV12
+NEED_TLS_PRF_SHA256=y
+endif
+NEED_MODEXP=y
+NEED_CIPHER=y
+L_CFLAGS += -DCONFIG_TLS_INTERNAL
+L_CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
+endif
+ifdef NEED_CIPHER
+NEED_DES=y
+OBJS += src/crypto/crypto_internal-cipher.c
+endif
+ifdef NEED_MODEXP
+OBJS += src/crypto/crypto_internal-modexp.c
+OBJS += src/tls/bignum.c
+endif
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
+OBJS += src/crypto/crypto_libtomcrypt.c
+LIBS += -ltomcrypt -ltfm
+LIBS_h += -ltomcrypt -ltfm
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+ifeq ($(CONFIG_CRYPTO), internal)
+OBJS += src/crypto/crypto_internal.c
+NEED_AES_DEC=y
+L_CFLAGS += -DCONFIG_CRYPTO_INTERNAL
+ifdef CONFIG_INTERNAL_LIBTOMMATH
+L_CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
+ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST
+L_CFLAGS += -DLTM_FAST
+endif
+else
+LIBS += -ltommath
+LIBS_h += -ltommath
+endif
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_DES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD4=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_SHA384=y
+CONFIG_INTERNAL_SHA512=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+ifeq ($(CONFIG_CRYPTO), cryptoapi)
+OBJS += src/crypto/crypto_cryptoapi.c
+OBJS_p += src/crypto/crypto_cryptoapi.c
+L_CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_RC4=y
+endif
+endif
+
+ifeq ($(CONFIG_TLS), none)
+ifdef TLS_FUNCS
+OBJS += src/crypto/tls_none.c
+L_CFLAGS += -DEAP_TLS_NONE
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD5=y
+endif
+OBJS += src/crypto/crypto_none.c
+OBJS_p += src/crypto/crypto_none.c
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_RC4=y
+endif
+
+ifndef TLS_FUNCS
+OBJS += src/crypto/tls_none.c
+ifeq ($(CONFIG_TLS), internal)
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_RC4=y
+endif
+endif
+
+AESOBJS = # none so far
+ifdef CONFIG_INTERNAL_AES
+AESOBJS += src/crypto/aes-internal.c src/crypto/aes-internal-enc.c
+endif
+
+ifneq ($(CONFIG_TLS), openssl)
+AESOBJS += src/crypto/aes-wrap.c
+endif
+ifdef NEED_AES_EAX
+AESOBJS += src/crypto/aes-eax.c
+NEED_AES_CTR=y
+endif
+ifdef NEED_AES_CTR
+AESOBJS += src/crypto/aes-ctr.c
+endif
+ifdef NEED_AES_ENCBLOCK
+AESOBJS += src/crypto/aes-encblock.c
+endif
+ifdef NEED_AES_OMAC1
+AESOBJS += src/crypto/aes-omac1.c
+endif
+ifdef NEED_AES_UNWRAP
+ifneq ($(CONFIG_TLS), openssl)
+NEED_AES_DEC=y
+AESOBJS += src/crypto/aes-unwrap.c
+endif
+endif
+ifdef NEED_AES_CBC
+NEED_AES_DEC=y
+ifneq ($(CONFIG_TLS), openssl)
+AESOBJS += src/crypto/aes-cbc.c
+endif
+endif
+ifdef NEED_AES_DEC
+ifdef CONFIG_INTERNAL_AES
+AESOBJS += src/crypto/aes-internal-dec.c
+endif
+endif
+ifdef NEED_AES
+OBJS += $(AESOBJS)
+endif
+
+SHA1OBJS =
+ifdef NEED_SHA1
+ifneq ($(CONFIG_TLS), openssl)
+SHA1OBJS += src/crypto/sha1.c
+endif
+SHA1OBJS += src/crypto/sha1-prf.c
+ifdef CONFIG_INTERNAL_SHA1
+SHA1OBJS += src/crypto/sha1-internal.c
+ifdef NEED_FIPS186_2_PRF
+SHA1OBJS += src/crypto/fips_prf_internal.c
+endif
+endif
+ifneq ($(CONFIG_TLS), openssl)
+SHA1OBJS += src/crypto/sha1-pbkdf2.c
+endif
+ifdef NEED_T_PRF
+SHA1OBJS += src/crypto/sha1-tprf.c
+endif
+ifdef NEED_TLS_PRF
+SHA1OBJS += src/crypto/sha1-tlsprf.c
+endif
+endif
+
+ifdef NEED_SHA1
+OBJS += $(SHA1OBJS)
+endif
+
+ifneq ($(CONFIG_TLS), openssl)
+OBJS += src/crypto/md5.c
+endif
+
+ifdef NEED_MD5
+ifdef CONFIG_INTERNAL_MD5
+OBJS += src/crypto/md5-internal.c
+HOBJS += src/crypto/md5-internal.c
+endif
+endif
+
+ifdef NEED_MD4
+ifdef CONFIG_INTERNAL_MD4
+OBJS += src/crypto/md4-internal.c
+endif
+endif
+
+ifdef NEED_DES
+ifdef CONFIG_INTERNAL_DES
+OBJS += src/crypto/des-internal.c
+endif
+endif
+
+ifdef CONFIG_NO_RC4
+L_CFLAGS += -DCONFIG_NO_RC4
+endif
+
+ifdef NEED_RC4
+ifdef CONFIG_INTERNAL_RC4
+ifndef CONFIG_NO_RC4
+OBJS += src/crypto/rc4.c
+endif
+endif
+endif
+
+ifdef NEED_SHA256
+L_CFLAGS += -DCONFIG_SHA256
+ifneq ($(CONFIG_TLS), openssl)
+OBJS += src/crypto/sha256.c
+endif
+OBJS += src/crypto/sha256-prf.c
+ifdef CONFIG_INTERNAL_SHA256
+OBJS += src/crypto/sha256-internal.c
+endif
+ifdef NEED_TLS_PRF_SHA256
+OBJS += src/crypto/sha256-tlsprf.c
+endif
+endif
+ifdef NEED_SHA384
+L_CFLAGS += -DCONFIG_SHA384
+OBJS += src/crypto/sha384-prf.c
+endif
+
+ifdef CONFIG_INTERNAL_SHA384
+L_CFLAGS += -DCONFIG_INTERNAL_SHA384
+OBJS += src/crypto/sha384-internal.c
+endif
+
+ifdef CONFIG_INTERNAL_SHA512
+L_CFLAGS += -DCONFIG_INTERNAL_SHA512
+OBJS += src/crypto/sha512-internal.c
+endif
+
+ifdef NEED_DH_GROUPS
+OBJS += src/crypto/dh_groups.c
+endif
+ifdef NEED_DH_GROUPS_ALL
+L_CFLAGS += -DALL_DH_GROUPS
+endif
+ifdef CONFIG_INTERNAL_DH_GROUP5
+ifdef NEED_DH_GROUPS
+OBJS += src/crypto/dh_group5.c
+endif
+endif
+
+ifdef NEED_ECC
+L_CFLAGS += -DCONFIG_ECC
+endif
+
+ifdef CONFIG_NO_RANDOM_POOL
+L_CFLAGS += -DCONFIG_NO_RANDOM_POOL
+else
+OBJS += src/crypto/random.c
+HOBJS += src/crypto/random.c
+HOBJS += src/utils/eloop.c
+HOBJS += $(SHA1OBJS)
+ifneq ($(CONFIG_TLS), openssl)
+HOBJS += src/crypto/md5.c
+endif
+endif
+
+ifdef CONFIG_RADIUS_SERVER
+L_CFLAGS += -DRADIUS_SERVER
+OBJS += src/radius/radius_server.c
+endif
+
+ifdef CONFIG_IPV6
+L_CFLAGS += -DCONFIG_IPV6
+endif
+
+ifdef CONFIG_DRIVER_RADIUS_ACL
+L_CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL
+endif
+
+ifdef NEED_BASE64
+OBJS += src/utils/base64.c
+endif
+
+ifdef NEED_AP_MLME
+OBJS += src/ap/wmm.c
+OBJS += src/ap/ap_list.c
+OBJS += src/ap/ieee802_11.c
+OBJS += src/ap/hw_features.c
+OBJS += src/ap/dfs.c
+L_CFLAGS += -DNEED_AP_MLME
+endif
+ifdef CONFIG_IEEE80211N
+OBJS += src/ap/ieee802_11_ht.c
+endif
+
+ifdef CONFIG_IEEE80211AC
+OBJS += src/ap/ieee802_11_vht.c
+endif
+
+ifdef CONFIG_P2P_MANAGER
+L_CFLAGS += -DCONFIG_P2P_MANAGER
+OBJS += src/ap/p2p_hostapd.c
+endif
+
+ifdef CONFIG_HS20
+L_CFLAGS += -DCONFIG_HS20
+OBJS += src/ap/hs20.c
+CONFIG_INTERWORKING=y
+endif
+
+ifdef CONFIG_INTERWORKING
+L_CFLAGS += -DCONFIG_INTERWORKING
+OBJS += src/common/gas.c
+OBJS += src/ap/gas_serv.c
+endif
+
+ifdef CONFIG_PROXYARP
+L_CFLAGS += -DCONFIG_PROXYARP
+OBJS += src/ap/x_snoop.c
+OBJS += src/ap/dhcp_snoop.c
+ifdef CONFIG_IPV6
+OBJS += src/ap/ndisc_snoop.c
+endif
+endif
+
+OBJS += src/drivers/driver_common.c
+
+ifdef CONFIG_ACS
+L_CFLAGS += -DCONFIG_ACS
+OBJS += src/ap/acs.c
+LIBS += -lm
+endif
+
+ifdef CONFIG_NO_STDOUT_DEBUG
+L_CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
+endif
+
+ifdef CONFIG_DEBUG_LINUX_TRACING
+L_CFLAGS += -DCONFIG_DEBUG_LINUX_TRACING
+endif
+
+ifdef CONFIG_DEBUG_FILE
+L_CFLAGS += -DCONFIG_DEBUG_FILE
+endif
+
+ifdef CONFIG_ANDROID_LOG
+L_CFLAGS += -DCONFIG_ANDROID_LOG
+endif
+
+OBJS_c = hostapd_cli.c
+OBJS_c += src/common/wpa_ctrl.c
+OBJS_c += src/utils/os_$(CONFIG_OS).c
+OBJS_c += src/common/cli.c
+OBJS_c += src/utils/eloop.c
+OBJS_c += src/utils/common.c
+ifdef CONFIG_WPA_TRACE
+OBJS_c += src/utils/trace.c
+endif
+OBJS_c += src/utils/wpa_debug.c
+ifdef CONFIG_WPA_CLI_EDIT
+OBJS_c += src/utils/edit.c
+else
+OBJS_c += src/utils/edit_simple.c
+endif
+
+########################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := hostapd_cli
+LOCAL_MODULE_TAGS := debug
+LOCAL_SHARED_LIBRARIES := libc libcutils liblog
+LOCAL_CFLAGS := $(L_CFLAGS)
+LOCAL_SRC_FILES := $(OBJS_c)
+LOCAL_C_INCLUDES := $(INCLUDES)
+include $(BUILD_EXECUTABLE)
+
+########################
+include $(CLEAR_VARS)
+LOCAL_MODULE := hostapd
+LOCAL_MODULE_TAGS := optional
+ifdef CONFIG_DRIVER_CUSTOM
+LOCAL_STATIC_LIBRARIES := libCustomWifi
+endif
+ifneq ($(BOARD_HOSTAPD_PRIVATE_LIB),)
+LOCAL_STATIC_LIBRARIES += $(BOARD_HOSTAPD_PRIVATE_LIB)
+endif
+LOCAL_SHARED_LIBRARIES := libc libcutils liblog libcrypto libssl
+ifdef CONFIG_DRIVER_NL80211
+ifneq ($(wildcard external/libnl),)
+LOCAL_SHARED_LIBRARIES += libnl
+else
+LOCAL_STATIC_LIBRARIES += libnl_2
+endif
+endif
+LOCAL_CFLAGS := $(L_CFLAGS)
+LOCAL_SRC_FILES := $(OBJS)
+LOCAL_C_INCLUDES := $(INCLUDES)
+LOCAL_INIT_RC := hostapd.android.rc
+include $(BUILD_EXECUTABLE)
+
+endif # ifeq ($(WPA_BUILD_HOSTAPD),true)

+ 1144 - 0
EVSE/GPL/hostapd-2.6/hostapd/ChangeLog

@@ -0,0 +1,1144 @@
+ChangeLog for hostapd
+
+2016-10-02 - v2.6
+	* fixed EAP-pwd last fragment validation
+	  [http://w1.fi/security/2015-7/] (CVE-2015-5314)
+	* fixed WPS configuration update vulnerability with malformed passphrase
+	  [http://w1.fi/security/2016-1/] (CVE-2016-4476)
+	* extended channel switch support for VHT bandwidth changes
+	* added support for configuring new ANQP-elements with
+	  anqp_elem=<InfoID>:<hexdump of payload>
+	* fixed Suite B 192-bit AKM to use proper PMK length
+	  (note: this makes old releases incompatible with the fixed behavior)
+	* added no_probe_resp_if_max_sta=1 parameter to disable Probe Response
+	  frame sending for not-associated STAs if max_num_sta limit has been
+	  reached
+	* added option (-S as command line argument) to request all interfaces
+	  to be started at the same time
+	* modified rts_threshold and fragm_threshold configuration parameters
+	  to allow -1 to be used to disable RTS/fragmentation
+	* EAP-pwd: added support for Brainpool Elliptic Curves
+	  (with OpenSSL 1.0.2 and newer)
+	* fixed EAPOL reauthentication after FT protocol run
+	* fixed FTIE generation for 4-way handshake after FT protocol run
+	* fixed and improved various FST operations
+	* TLS server
+	  - support SHA384 and SHA512 hashes
+	  - support TLS v1.2 signature algorithm with SHA384 and SHA512
+	  - support PKCS #5 v2.0 PBES2
+	  - support PKCS #5 with PKCS #12 style key decryption
+	  - minimal support for PKCS #12
+	  - support OCSP stapling (including ocsp_multi)
+	* added support for OpenSSL 1.1 API changes
+	  - drop support for OpenSSL 0.9.8
+	  - drop support for OpenSSL 1.0.0
+	* EAP-PEAP: support fast-connect crypto binding
+	* RADIUS
+	  - fix Called-Station-Id to not escape SSID
+	  - add Event-Timestamp to all Accounting-Request packets
+	  - add Acct-Session-Id to Accounting-On/Off
+	  - add Acct-Multi-Session-Id  ton Access-Request packets
+	  - add Service-Type (= Frames)
+	  - allow server to provide PSK instead of passphrase for WPA-PSK
+	    Tunnel_password case
+	  - update full message for interim accounting updates
+	  - add Acct-Delay-Time into Accounting messages
+	  - add require_message_authenticator configuration option to require
+	    CoA/Disconnect-Request packets to be authenticated
+	* started to postpone WNM-Notification frame sending by 100 ms so that
+	  the STA has some more time to configure the key before this frame is
+	  received after the 4-way handshake
+	* VHT: added interoperability workaround for 80+80 and 160 MHz channels
+	* extended VLAN support (per-STA vif, etc.)
+	* fixed PMKID derivation with SAE
+	* nl80211
+	  - added support for full station state operations
+	  - fix IEEE 802.1X/WEP EAP reauthentication and rekeying to use
+	    unencrypted EAPOL frames
+	* added initial MBO support; number of extensions to WNM BSS Transition
+	  Management
+	* added initial functionality for location related operations
+	* added assocresp_elements parameter to allow vendor specific elements
+	  to be added into (Re)Association Response frames
+	* improved Public Action frame addressing
+	  - use Address 3 = wildcard BSSID in GAS response if a query from an
+	    unassociated STA used that address
+	  - fix TX status processing for Address 3 = wildcard BSSID
+	  - add gas_address3 configuration parameter to control Address 3
+	    behavior
+	* added command line parameter -i to override interface parameter in
+	  hostapd.conf
+	* added command completion support to hostapd_cli
+	* added passive client taxonomy determination (CONFIG_TAXONOMY=y
+	  compile option and "SIGNATURE <addr>" control interface command)
+	* number of small fixes
+
+2015-09-27 - v2.5
+	* fixed WPS UPnP vulnerability with HTTP chunked transfer encoding
+	  [http://w1.fi/security/2015-2/] (CVE-2015-4141)
+	* fixed WMM Action frame parser
+	  [http://w1.fi/security/2015-3/] (CVE-2015-4142)
+	* fixed EAP-pwd server missing payload length validation
+	  [http://w1.fi/security/2015-4/]
+	  (CVE-2015-4143, CVE-2015-4144, CVE-2015-4145)
+	* fixed validation of WPS and P2P NFC NDEF record payload length
+	  [http://w1.fi/security/2015-5/]
+	* nl80211:
+	  - fixed vendor command handling to check OUI properly
+	* fixed hlr_auc_gw build with OpenSSL
+	* hlr_auc_gw: allow Milenage RES length to be reduced
+	* disable HT for a station that does not support WMM/QoS
+	* added support for hashed password (NtHash) in EAP-pwd server
+	* fixed and extended dynamic VLAN cases
+	* added EAP-EKE server support for deriving Session-Id
+	* set Acct-Session-Id to a random value to make it more likely to be
+	  unique even if the device does not have a proper clock
+	* added more 2.4 GHz channels for 20/40 MHz HT co-ex scan
+	* modified SAE routines to be more robust and PWE generation to be
+	  stronger against timing attacks
+	* added support for Brainpool Elliptic Curves with SAE
+	* increases maximum value accepted for cwmin/cwmax
+	* added support for CCMP-256 and GCMP-256 as group ciphers with FT
+	* added Fast Session Transfer (FST) module
+	* removed optional fields from RSNE when using FT with PMF
+	  (workaround for interoperability issues with iOS 8.4)
+	* added EAP server support for TLS session resumption
+	* fixed key derivation for Suite B 192-bit AKM (this breaks
+	  compatibility with the earlier version)
+	* added mechanism to track unconnected stations and do minimal band
+	  steering
+	* number of small fixes
+
+2015-03-15 - v2.4
+	* allow OpenSSL cipher configuration to be set for internal EAP server
+	  (openssl_ciphers parameter)
+	* fixed number of small issues based on hwsim test case failures and
+	  static analyzer reports
+	* fixed Accounting-Request to not include duplicated Acct-Session-Id
+	* add support for Acct-Multi-Session-Id in RADIUS Accounting messages
+	* add support for PMKSA caching with SAE
+	* add support for generating BSS Load element (bss_load_update_period)
+	* fixed channel switch from VHT to HT
+	* add INTERFACE-ENABLED and INTERFACE-DISABLED ctrl_iface events
+	* add support for learning STA IPv4/IPv6 addresses and configuring
+	  ProxyARP support
+	* dropped support for the madwifi driver interface
+	* add support for Suite B (128-bit and 192-bit level) key management and
+	  cipher suites
+	* fixed a regression with driver=wired
+	* extend EAPOL-Key msg 1/4 retry workaround for changing SNonce
+	* add BSS_TM_REQ ctrl_iface command to send BSS Transition Management
+	  Request frames and BSS-TM-RESP event to indicate response to such
+	  frame
+	* add support for EAP Re-Authentication Protocol (ERP)
+	* fixed AP IE in EAPOL-Key 3/4 when both WPA and FT was enabled
+	* fixed a regression in HT 20/40 coex Action frame parsing
+	* set stdout to be line-buffered
+	* add support for vendor specific VHT extension to enable 256 QAM rates
+	  (VHT-MCS 8 and 9) on 2.4 GHz band
+	* RADIUS DAS:
+	  - extend Disconnect-Request processing to allow matching of multiple
+	    sessions
+	  - support Acct-Multi-Session-Id as an identifier
+	  - allow PMKSA cache entry to be removed without association
+	* expire hostapd STA entry if kernel does not have a matching entry
+	* allow chanlist to be used to specify a subset of channels for ACS
+	* improve ACS behavior on 2.4 GHz band and allow channel bias to be
+	  configured with acs_chan_bias parameter
+	* do not reply to a Probe Request frame that includes DSS Parameter Set
+	  element in which the channel does not match the current operating
+	  channel
+	* add UPDATE_BEACON ctrl_iface command; this can be used to force Beacon
+	  frame contents to be updated and to start beaconing on an interface
+	  that used start_disabled=1
+	* fixed some RADIUS server failover cases
+
+2014-10-09 - v2.3
+	* fixed number of minor issues identified in static analyzer warnings
+	* fixed DFS and channel switch operation for multi-BSS cases
+	* started to use constant time comparison for various password and hash
+	  values to reduce possibility of any externally measurable timing
+	  differences
+	* extended explicit clearing of freed memory and expired keys to avoid
+	  keeping private data in memory longer than necessary
+	* added support for number of new RADIUS attributes from RFC 7268
+	  (Mobility-Domain-Id, WLAN-HESSID, WLAN-Pairwise-Cipher,
+	  WLAN-Group-Cipher, WLAN-AKM-Suite, WLAN-Group-Mgmt-Pairwise-Cipher)
+	* fixed GET_CONFIG wpa_pairwise_cipher value
+	* added code to clear bridge FDB entry on station disconnection
+	* fixed PMKSA cache timeout from Session-Timeout for WPA/WPA2 cases
+	* fixed OKC PMKSA cache entry fetch to avoid a possible infinite loop
+	  in case the first entry does not match
+	* fixed hostapd_cli action script execution to use more robust mechanism
+	  (CVE-2014-3686)
+
+2014-06-04 - v2.2
+	* fixed SAE confirm-before-commit validation to avoid a potential
+	  segmentation fault in an unexpected message sequence that could be
+	  triggered remotely
+	* extended VHT support
+	  - Operating Mode Notification
+	  - Power Constraint element (local_pwr_constraint)
+	  - Spectrum management capability (spectrum_mgmt_required=1)
+	  - fix VHT80 segment picking in ACS
+	  - fix vht_capab 'Maximum A-MPDU Length Exponent' handling
+	  - fix VHT20
+	* fixed HT40 co-ex scan for some pri/sec channel switches
+	* extended HT40 co-ex support to allow dynamic channel width changes
+	  during the lifetime of the BSS
+	* fixed HT40 co-ex support to check for overlapping 20 MHz BSS
+	* fixed MSCHAP UTF-8 to UCS-2 conversion for three-byte encoding;
+	  this fixes password with include UTF-8 characters that use
+	  three-byte encoding EAP methods that use NtPasswordHash
+	* reverted TLS certificate validation step change in v2.1 that rejected
+	  any AAA server certificate with id-kp-clientAuth even if
+	  id-kp-serverAuth EKU was included
+	* fixed STA validation step for WPS ER commands to prevent a potential
+	  crash if an ER sends an unexpected PutWLANResponse to a station that
+	  is disassociated, but not fully removed
+	* enforce full EAP authentication after RADIUS Disconnect-Request by
+	  removing the PMKSA cache entry
+	* added support for NAS-IP-Address, NAS-identifier, and NAS-IPv6-Address
+	  in RADIUS Disconnect-Request
+	* added mechanism for removing addresses for MAC ACLs by prefixing an
+	  entry with "-"
+	* Interworking/Hotspot 2.0 enhancements
+	  - support Hotspot 2.0 Release 2
+	    * OSEN network for online signup connection
+	    * subscription remediation (based on RADIUS server request or
+	      control interface HS20_WNM_NOTIF for testing purposes)
+	    * Hotspot 2.0 release number indication in WFA RADIUS VSA
+	    * deauthentication request (based on RADIUS server request or
+	      control interface WNM_DEAUTH_REQ for testing purposes)
+	    * Session Info URL RADIUS AVP to trigger ESS Disassociation Imminent
+	    * hs20_icon config parameter to configure icon files for OSU
+	    * osu_* config parameters for OSU Providers list
+	  - do not use Interworking filtering rules on Probe Request if
+	    Interworking is disabled to avoid interop issues
+	* added/fixed nl80211 functionality
+	  - AP interface teardown optimization
+	  - support vendor specific driver command
+	    (VENDOR <vendor id> <sub command id> [<hex formatted data>])
+	* fixed PMF protection of Deauthentication frame when this is triggered
+	  by session timeout
+	* internal TLS implementation enhancements/fixes
+	  - add SHA256-based cipher suites
+	  - add DHE-RSA cipher suites
+	  - fix X.509 validation of PKCS#1 signature to check for extra data
+	* RADIUS server functionality
+	  - add minimal RADIUS accounting server support (hostapd-as-server);
+	    this is mainly to enable testing coverage with hwsim scripts
+	  - allow authentication log to be written into SQLite databse
+	  - added option for TLS protocol testing of an EAP peer by simulating
+	    various misbehaviors/known attacks
+	  - MAC ACL support for testing purposes
+	* fixed PTK derivation for CCMP-256 and GCMP-256
+	* extended WPS per-station PSK to support ER case
+	* added option to configure the management group cipher
+	  (group_mgmt_cipher=AES-128-CMAC (default), BIP-GMAC-128, BIP-GMAC-256,
+	  BIP-CMAC-256)
+	* fixed AP mode default TXOP Limit values for AC_VI and AC_VO (these
+	  were rounded incorrectly)
+	* added support for postponing FT response in case PMK-R1 needs to be
+	  pulled from R0KH
+	* added option to advertise 40 MHz intolerant HT capability with
+	  ht_capab=[40-INTOLERANT]
+	* remove WPS 1.0 only support, i.e., WSC 2.0 support is now enabled
+	  whenever CONFIG_WPS=y is set
+	* EAP-pwd fixes
+	  - fix possible segmentation fault on EAP method deinit if an invalid
+	    group is negotiated
+	* fixed RADIUS client retransmit/failover behavior
+	  - there was a potential ctash due to freed memory being accessed
+	  - failover to a backup server mechanism did not work properly
+	* fixed a possible crash on double DISABLE command when multiple BSSes
+	  are enabled
+	* fixed a memory leak in SAE random number generation
+	* fixed GTK rekeying when the station uses FT protocol
+	* fixed off-by-one bounds checking in printf_encode()
+	  - this could result in deinial of service in some EAP server cases
+	* various bug fixes
+
+2014-02-04 - v2.1
+	* added support for simultaneous authentication of equals (SAE) for
+	  stronger password-based authentication with WPA2-Personal
+	* added nl80211 functionality
+	  - VHT configuration for nl80211
+	  - support split wiphy dump
+	  - driver-based MAC ACL
+	  - QoS Mapping configuration
+	* added fully automated regression testing with mac80211_hwsim
+	* allow ctrl_iface group to be specified on command line (-G<group>)
+	* allow single hostapd process to control independent WPS interfaces
+	  (wps_independent=1) instead of synchronized operations through all
+	  configured interfaces within a process
+	* avoid processing received management frames multiple times when using
+	  nl80211 with multiple BSSes
+	* added support for DFS (processing radar detection events, CAC, channel
+	  re-selection)
+	* added EAP-EKE server
+	* added automatic channel selection (ACS)
+	* added option for using per-BSS (vif) configuration files with
+	  -b<phyname>:<config file name>
+	* extended global control interface ADD/REMOVE commands to allow BSSes
+	  of a radio to be removed individually without having to add/remove all
+	  other BSSes of the radio at the same time
+	* added support for sending debug info to Linux tracing (-T on command
+	  line)
+	* replace dump_file functionality with same information being available
+	  through the hostapd control interface
+	* added support for using Protected Dual of Public Action frames for
+	  GAS/ANQP exchanges when PMF is enabled
+	* added support for WPS+NFC updates
+	  - improved protocol
+	  - option to fetch and report alternative carrier records for external
+	    NFC operations
+	* various bug fixes
+
+2013-01-12 - v2.0
+	* added AP-STA-DISCONNECTED ctrl_iface event
+	* improved debug logging (human readable event names, interface name
+	  included in more entries)
+	* added number of small changes to make it easier for static analyzers
+	  to understand the implementation
+	* added a workaround for Windows 7 Michael MIC failure reporting and
+	  use of the Secure bit in EAPOL-Key msg 3/4
+	* fixed number of small bugs (see git logs for more details)
+	* changed OpenSSL to read full certificate chain from server_cert file
+	* nl80211: number of updates to use new cfg80211/nl80211 functionality
+	  - replace monitor interface with nl80211 commands
+	  - additional information for driver-based AP SME
+	* EAP-pwd:
+	  - fix KDF for group 21 and zero-padding
+	  - added support for fragmentation
+	  - increased maximum number of hunting-and-pecking iterations
+	* avoid excessive Probe Response retries for broadcast Probe Request
+	  frames (only with drivers using hostapd SME/MLME)
+	* added preliminary support for using TLS v1.2 (CONFIG_TLSV12=y)
+	* fixed WPS operation stopping on dual concurrent AP
+	* added wps_rf_bands configuration parameter for overriding RF Bands
+	  value for WPS
+	* added support for getting per-device PSK from RADIUS Tunnel-Password
+	* added support for libnl 3.2 and newer
+	* increased initial group key handshake retransmit timeout to 500 ms
+	* added a workaround for 4-way handshake to update SNonce even after
+	  having sent EAPOL-Key 3/4 to avoid issues with some supplicant
+	  implementations that can change SNonce for each EAP-Key 2/4
+	* added a workaround for EAPOL-Key 4/4 using incorrect type value in
+	  WPA2 mode (some deployed stations use WPA type in that message)
+	* added a WPS workaround for mixed mode AP Settings with Windows 7
+	* changed WPS AP PIN disabling mechanism to disable the PIN after 10
+	  consecutive failures in addition to using the exponential lockout
+	  period
+	* added support for WFA Hotspot 2.0
+	  - GAS/ANQP advertisement of network information
+	  - disable_dgaf parameter to disable downstream group-addressed
+	    forwarding
+	* simplified licensing terms by selecting the BSD license as the only
+	  alternative
+	* EAP-SIM: fixed re-authentication not to update pseudonym
+	* EAP-SIM: use Notification round before EAP-Failure
+	* EAP-AKA: added support for AT_COUNTER_TOO_SMALL
+	* EAP-AKA: skip AKA/Identity exchange if EAP identity is recognized
+	* EAP-AKA': fixed identity for MK derivation
+	* EAP-AKA': updated to RFC 5448 (username prefixes changed); note: this
+	  breaks interoperability with older versions
+	* EAP-SIM/AKA: allow pseudonym to be used after unknown reauth id
+	* changed ANonce to be a random number instead of Counter-based
+	* added support for canceling WPS operations with hostapd_cli wps_cancel
+	* fixed EAP/WPS to PSK transition on reassociation in cases where
+	  deauthentication is missed
+	* hlr_auc_gw enhancements:
+	  - a new command line parameter -u can be used to enable updating of
+	    SQN in Milenage file
+	  - use 5 bit IND for SQN updates
+	  - SQLite database can now be used to store Milenage information
+	* EAP-SIM/AKA DB: added optional use of SQLite database for pseudonyms
+	  and reauth data
+	* added support for Chargeable-User-Identity (RFC 4372)
+	* added radius_auth_req_attr and radius_acct_req_attr configuration
+	  parameters to allow adding/overriding of RADIUS attributes in
+	  Access-Request and Accounting-Request packets
+	* added support for RADIUS dynamic authorization server (RFC 5176)
+	* added initial support for WNM operations
+	  - BSS max idle period
+	  - WNM-Sleep Mode
+	* added new WPS NFC ctrl_iface mechanism
+	  - removed obsoleted WPS_OOB command (including support for deprecated
+	    UFD config_method)
+	* added FT support for drivers that implement MLME internally
+	* added SA Query support for drivers that implement MLME internally
+	* removed default ACM=1 from AC_VO and AC_VI
+	* changed VENDOR-TEST EAP method to use proper private enterprise number
+	  (this will not interoperate with older versions)
+	* added hostapd.conf parameter vendor_elements to allow arbitrary vendor
+	  specific elements to be added to the Beacon and Probe Response frames
+	* added support for configuring GCMP cipher for IEEE 802.11ad
+	* added support for 256-bit AES with internal TLS implementation
+	* changed EAPOL transmission to use AC_VO if WMM is active
+	* fixed EAP-TLS/PEAP/TTLS/FAST server to validate TLS Message Length
+	  correctly; invalid messages could have caused the hostapd process to
+	  terminate before this fix [CVE-2012-4445]
+	* limit number of active wildcard PINs for WPS Registrar to one to avoid
+	  confusing behavior with multiple wildcard PINs
+	* added a workaround for WPS PBC session overlap detection to avoid
+	  interop issues with deployed station implementations that do not
+	  remove active PBC indication from Probe Request frames properly
+	* added support for using SQLite for the eap_user database
+	* added Acct-Session-Id attribute into Access-Request messages
+	* fixed EAPOL frame transmission to non-QoS STAs with nl80211
+	  (do not send QoS frames if the STA did not negotiate use of QoS for
+	  this association)
+
+2012-05-10 - v1.0
+	* Add channel selection support in hostapd. See hostapd.conf.
+	* Add support for IEEE 802.11v Time Advertisement mechanism with UTC
+	  TSF offset. See hostapd.conf for config info.
+	* Delay STA entry removal until Deauth/Disassoc TX status in AP mode.
+	  This allows the driver to use PS buffering of Deauthentication and
+	  Disassociation frames when the STA is in power save sleep. Only
+	  available with drivers that provide TX status events for Deauth/
+	  Disassoc frames (nl80211).
+	* Allow PMKSA caching to be disabled on the Authenticator. See
+	  hostap.conf config parameter disable_pmksa_caching.
+	* atheros: Add support for IEEE 802.11w configuration.
+	* bsd: Add support for setting HT values in IFM_MMASK.
+	* Allow client isolation to be configured with ap_isolate. Client
+	  isolation can be used to prevent low-level bridging of frames
+	  between associated stations in the BSS. By default, this bridging
+	  is allowed.
+	* Allow coexistance of HT BSSes with WEP/TKIP BSSes.
+	* Add require_ht config parameter, which can be used to configure
+	  hostapd to reject association with any station that does not support
+	  HT PHY.
+	* Add support for writing debug log to a file using "-f" option. Also
+	  add relog CLI command to re-open the log file.
+	* Add bridge handling for WDS STA interfaces. By default they are
+	  added to the configured bridge of the AP interface (if present),
+	  but the user can also specify a separate bridge using cli command
+	  wds_bridge.
+	* hostapd_cli:
+	  - Add wds_bridge command for specifying bridge for WDS STA
+	    interfaces.
+	  - Add relog command for reopening log file.
+	  - Send AP-STA-DISCONNECTED event when an AP disconnects a station
+	    due to inactivity.
+	  - Add wps_config ctrl_interface command for configuring AP. This
+	    command can be used to configure the AP using the internal WPS
+	    registrar. It works in the same way as new AP settings received
+	    from an ER.
+	  - Many WPS/WPS ER commands - see WPS/WPS ER sections for details.
+	  - Add command get version, that returns hostapd version string.
+	* WNM: Add BSS Transition Management Request for ESS Disassoc Imminent.
+	  Use hostapd_cli ess_disassoc (STA addr) (URL) to send the
+	  notification to the STA.
+	* Allow AP mode to disconnect STAs based on low ACK condition (when
+	  the data connection is not working properly, e.g., due to the STA
+	  going outside the range of the AP). Disabled by default, enable by
+	  config option disassoc_low_ack.
+	* Add WPA_IGNORE_CONFIG_ERRORS build option to continue in case of bad
+	  config file.
+	* WPS:
+	  - Send AP Settings as a wrapped Credential attribute to ctrl_iface
+	    in WPS-NEW-AP-SETTINGS.
+	  - Dispatch more WPS events through hostapd ctrl_iface.
+	  - Add mechanism for indicating non-standard WPS errors.
+	  - Change concurrent radio AP to use only one WPS UPnP instance.
+	  - Add wps_check_pin command for processing PIN from user input.
+	    UIs can use this command to process a PIN entered by a user and to
+	    validate the checksum digit (if present).
+	  - Add hostap_cli get_config command to display current AP config.
+	  - Add new hostapd_cli command, wps_ap_pin, to manage AP PIN at
+	    runtime and support dynamic AP PIN management.
+	  - Disable AP PIN after 10 consecutive failures. Slow down attacks
+	    on failures up to 10.
+	  - Allow AP to start in Enrollee mode without AP PIN for probing,
+	    to be compatible with Windows 7.
+	  - Add Config Error into WPS-FAIL events to provide more info
+	    to the user on how to resolve the issue.
+	  - When controlling multiple interfaces:
+	     - apply WPS commands to all interfaces configured to use WPS
+	     - apply WPS config changes to all interfaces that use WPS
+	     - when an attack is detected on any interface, disable AP PIN on
+	       all interfaces
+	* WPS ER:
+	  - Show SetSelectedRegistrar events as ctrl_iface events.
+	  - Add special AP Setup Locked mode to allow read only ER.
+	    ap_setup_locked=2 can now be used to enable a special mode where
+	    WPS ER can learn the current AP settings, but cannot change them.
+	* WPS 2.0: Add support for WPS 2.0 (CONFIG_WPS2)
+	  - Add build option CONFIG_WPS_EXTENSIBILITY_TESTING to enable tool
+	    for testing protocol extensibility.
+	  - Add build option CONFIG_WPS_STRICT to allow disabling of WPS
+	    workarounds.
+	  - Add support for AuthorizedMACs attribute.
+	* TDLS:
+	  - Allow TDLS use or TDLS channel switching in the BSS to be
+	    prohibited in the BSS, using config params tdls_prohibit and
+	    tdls_prohibit_chan_switch.
+	* EAP server: Add support for configuring fragment size (see
+	  fragment_size in hostapd.conf).
+	* wlantest: Add a tool wlantest for IEEE802.11 protocol testing.
+	  wlantest can be used to capture frames from a monitor interface
+	  for realtime capturing or from pcap files for offline analysis.
+	* Interworking: Support added for 802.11u. Enable in .config with
+	  CONFIG_INTERWORKING. See hostapd.conf for config parameters for
+	  interworking.
+	* Android: Add build and runtime support for Android hostapd.
+	* Add a new debug message level for excessive information. Use
+	  -ddd to enable.
+	* TLS: Add support for tls_disable_time_checks=1 in client mode.
+	* Internal TLS:
+	  - Add support for TLS v1.1 (RFC 4346). Enable with build parameter
+	    CONFIG_TLSV11.
+	  - Add domainComponent parser for X.509 names
+	* Reorder some IEs to get closer to IEEE 802.11 standard. Move
+	  WMM into end of Beacon, Probe Resp and (Re)Assoc Resp frames.
+	  Move HT IEs to be later in (Re)Assoc Resp.
+	* Many bugfixes.
+
+2010-04-18 - v0.7.2
+	* fix WPS internal Registrar use when an external Registrar is also
+	  active
+	* bsd: Cleaned up driver wrapper and added various low-level
+	  configuration options
+	* TNC: fixed issues with fragmentation
+	* EAP-TNC: add Flags field into fragment acknowledgement (needed to
+	  interoperate with other implementations; may potentially breaks
+	  compatibility with older wpa_supplicant/hostapd versions)
+	* cleaned up driver wrapper API for multi-BSS operations
+	* nl80211: fix multi-BSS and VLAN operations
+	* fix number of issues with IEEE 802.11r/FT; this version is not
+	  backwards compatible with old versions
+	* add SA Query Request processing in AP mode (IEEE 802.11w)
+	* fix IGTK PN in group rekeying (IEEE 802.11w)
+	* fix WPS PBC session overlap detection to use correct attribute
+	* hostapd_notif_Assoc() can now be called with all IEs to simplify
+	  driver wrappers
+	* work around interoperability issue with some WPS External Registrar
+	  implementations
+	* nl80211: fix WPS IE update
+	* hostapd_cli: add support for action script operations (run a script
+	  on hostapd events)
+	* fix DH padding with internal crypto code (mainly, for WPS)
+	* fix WPS association with both WPS IE and WPA/RSN IE present with
+	  driver wrappers that use hostapd MLME (e.g., nl80211)
+
+2010-01-16 - v0.7.1
+	* cleaned up driver wrapper API (struct wpa_driver_ops); the new API
+	  is not fully backwards compatible, so out-of-tree driver wrappers
+	  will need modifications
+	* cleaned up various module interfaces
+	* merge hostapd and wpa_supplicant developers' documentation into a
+	  single document
+	* fixed HT Capabilities IE with nl80211 drivers
+	* moved generic AP functionality code into src/ap
+	* WPS: handle Selected Registrar as union of info from all Registrars
+	* remove obsolte Prism54.org driver wrapper
+	* added internal debugging mechanism with backtrace support and memory
+	  allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y)
+	* EAP-FAST server: piggyback Phase 2 start with the end of Phase 1
+	* WPS: add support for dynamically selecting whether to provision the
+	  PSK as an ASCII passphrase or PSK
+	* added support for WDS (4-address frame) mode with per-station virtual
+	  interfaces (wds_sta=1 in config file; only supported with
+	  driver=nl80211 for now)
+	* fixed WPS Probe Request processing to handle missing required
+	  attribute
+	* fixed PKCS#12 use with OpenSSL 1.0.0
+	* detect bridge interface automatically so that bridge parameter in
+	  hostapd.conf becomes optional (though, it may now be used to
+	  automatically add then WLAN interface into a bridge with
+	  driver=nl80211)
+
+2009-11-21 - v0.7.0
+	* increased hostapd_cli ping interval to 5 seconds and made this
+	  configurable with a new command line options (-G<seconds>)
+	* driver_nl80211: use Linux socket filter to improve performance
+	* added support for external Registrars with WPS (UPnP transport)
+	* 802.11n: scan for overlapping BSSes before starting 20/40 MHz channel
+	* driver_nl80211: fixed STA accounting data collection (TX/RX bytes
+	  reported correctly; TX/RX packets not yet available from kernel)
+	* added support for WPS USBA out-of-band mechanism with USB Flash
+	  Drives (UFD) (CONFIG_WPS_UFD=y)
+	* fixed EAPOL/EAP reauthentication when using an external RADIUS
+	  authentication server
+	* fixed TNC with EAP-TTLS
+	* fixed IEEE 802.11r key derivation function to match with the standard
+	  (note: this breaks interoperability with previous version) [Bug 303]
+	* fixed SHA-256 based key derivation function to match with the
+	  standard when using CCMP (for IEEE 802.11r and IEEE 802.11w)
+	  (note: this breaks interoperability with previous version) [Bug 307]
+	* added number of code size optimizations to remove unnecessary
+	  functionality from the program binary based on build configuration
+	  (part of this automatic; part configurable with CONFIG_NO_* build
+	  options)
+	* use shared driver wrapper files with wpa_supplicant
+	* driver_nl80211: multiple updates to provide support for new Linux
+	  nl80211/mac80211 functionality
+	* updated management frame protection to use IEEE Std 802.11w-2009
+	* fixed number of small WPS issues and added workarounds to
+	  interoperate with common deployed broken implementations
+	* added some IEEE 802.11n co-existence rules to disable 40 MHz channels
+	  or modify primary/secondary channels if needed based on neighboring
+	  networks
+	* added support for NFC out-of-band mechanism with WPS
+	* added preliminary support for IEEE 802.11r RIC processing
+
+2009-01-06 - v0.6.7
+	* added support for Wi-Fi Protected Setup (WPS)
+	  (hostapd can now be configured to act as an integrated WPS Registrar
+	  and provision credentials for WPS Enrollees using PIN and PBC
+	  methods; external wireless Registrar can configure the AP, but
+	  external WLAN Manager Registrars are not supported); WPS support can
+	  be enabled by adding CONFIG_WPS=y into .config and setting the
+	  runtime configuration variables in hostapd.conf (see WPS section in
+	  the example configuration file); new hostapd_cli commands wps_pin and
+	  wps_pbc are used to configure WPS negotiation; see README-WPS for
+	  more details
+	* added IEEE 802.11n HT capability configuration (ht_capab)
+	* added support for generating Country IE based on nl80211 regulatory
+	  information (added if ieee80211d=1 in configuration)
+	* fixed WEP authentication (both Open System and Shared Key) with
+	  mac80211
+	* added support for EAP-AKA' (draft-arkko-eap-aka-kdf)
+	* added support for using driver_test over UDP socket
+	* changed EAP-GPSK to use the IANA assigned EAP method type 51
+	* updated management frame protection to use IEEE 802.11w/D7.0
+	* fixed retransmission of EAP requests if no response is received
+
+2008-11-23 - v0.6.6
+	* added a new configuration option, wpa_ptk_rekey, that can be used to
+	  enforce frequent PTK rekeying, e.g., to mitigate some attacks against
+	  TKIP deficiencies
+	* updated OpenSSL code for EAP-FAST to use an updated version of the
+	  session ticket overriding API that was included into the upstream
+	  OpenSSL 0.9.9 tree on 2008-11-15 (no additional OpenSSL patch is
+	  needed with that version anymore)
+	* changed channel flags configuration to read the information from
+	  the driver (e.g., via driver_nl80211 when using mac80211) instead of
+	  using hostapd as the source of the regulatory information (i.e.,
+	  information from CRDA is now used with mac80211); this allows 5 GHz
+	  channels to be used with hostapd (if allowed in the current
+	  regulatory domain)
+	* fixed EAP-TLS message processing for the last TLS message if it is
+	  large enough to require fragmentation (e.g., if a large Session
+	  Ticket data is included)
+	* fixed listen interval configuration for nl80211 drivers
+
+2008-11-01 - v0.6.5
+	* added support for SHA-256 as X.509 certificate digest when using the
+	  internal X.509/TLSv1 implementation
+	* fixed EAP-FAST PAC-Opaque padding (0.6.4 broke this for some peer
+	  identity lengths)
+	* fixed internal TLSv1 implementation for abbreviated handshake (used
+	  by EAP-FAST server)
+	* added support for setting VLAN ID for STAs based on local MAC ACL
+	  (accept_mac_file) as an alternative for RADIUS server-based
+	  configuration
+	* updated management frame protection to use IEEE 802.11w/D6.0
+	  (adds a new association ping to protect against unauthenticated
+	  authenticate or (re)associate request frames dropping association)
+	* added support for using SHA256-based stronger key derivation for WPA2
+	  (IEEE 802.11w)
+	* added new "driver wrapper" for RADIUS-only configuration
+	  (driver=none in hostapd.conf; CONFIG_DRIVER_NONE=y in .config)
+	* fixed WPA/RSN IE validation to verify that the proto (WPA vs. WPA2)
+	  is enabled in configuration
+	* changed EAP-FAST configuration to use separate fields for A-ID and
+	  A-ID-Info (eap_fast_a_id_info) to allow A-ID to be set to a fixed
+	  16-octet len binary value for better interoperability with some peer
+	  implementations; eap_fast_a_id is now configured as a hex string
+	* driver_nl80211: Updated to match the current Linux mac80211 AP mode
+	  configuration (wireless-testing.git and Linux kernel releases
+	  starting from 2.6.29)
+
+2008-08-10 - v0.6.4
+	* added peer identity into EAP-FAST PAC-Opaque and skip Phase 2
+	  Identity Request if identity is already known
+	* added support for EAP Sequences in EAP-FAST Phase 2
+	* added support for EAP-TNC (Trusted Network Connect)
+	  (this version implements the EAP-TNC method and EAP-TTLS/EAP-FAST
+	  changes needed to run two methods in sequence (IF-T) and the IF-IMV
+	  and IF-TNCCS interfaces from TNCS)
+	* added support for optional cryptobinding with PEAPv0
+	* added fragmentation support for EAP-TNC
+	* added support for fragmenting EAP-TTLS/PEAP/FAST Phase 2 (tunneled)
+	  data
+	* added support for opportunistic key caching (OKC)
+
+2008-02-22 - v0.6.3
+	* fixed Reassociation Response callback processing when using internal
+	  MLME (driver_{hostap,nl80211,test}.c)
+	* updated FT support to use the latest draft, IEEE 802.11r/D9.0
+	* copy optional Proxy-State attributes into RADIUS response when acting
+	  as a RADIUS authentication server
+	* fixed EAPOL state machine to handle a case in which no response is
+	  received from the RADIUS authentication server; previous version
+	  could have triggered a crash in some cases after a timeout
+	* fixed EAP-SIM/AKA realm processing to allow decorated usernames to
+	  be used
+	* added a workaround for EAP-SIM/AKA peers that include incorrect null
+	  termination in the username
+	* fixed EAP-SIM/AKA protected result indication to include AT_COUNTER
+	  attribute in notification messages only when using fast
+	  reauthentication
+	* fixed EAP-SIM Start response processing for fast reauthentication
+	  case
+	* added support for pending EAP processing in EAP-{PEAP,TTLS,FAST}
+	  phase 2 to allow EAP-SIM and EAP-AKA to be used as the Phase 2 method
+
+2008-01-01 - v0.6.2
+	* fixed EAP-SIM and EAP-AKA message parser to validate attribute
+	  lengths properly to avoid potential crash caused by invalid messages
+	* added data structure for storing allocated buffers (struct wpabuf);
+	  this does not affect hostapd usage, but many of the APIs changed
+	  and various interfaces (e.g., EAP) is not compatible with old
+	  versions
+	* added support for protecting EAP-AKA/Identity messages with
+	  AT_CHECKCODE (optional feature in RFC 4187)
+	* added support for protected result indication with AT_RESULT_IND for
+	  EAP-SIM and EAP-AKA (eap_sim_aka_result_ind=1)
+	* added support for configuring EAP-TTLS phase 2 non-EAP methods in
+	  EAP server configuration; previously all four were enabled for every
+	  phase 2 user, now all four are disabled by default and need to be
+	  enabled with new method names TTLS-PAP, TTLS-CHAP, TTLS-MSCHAP,
+	  TTLS-MSCHAPV2
+	* removed old debug printing mechanism and the related 'debug'
+	  parameter in the configuration file; debug verbosity is now set with
+	  -d (or -dd) command line arguments
+	* added support for EAP-IKEv2 (draft-tschofenig-eap-ikev2-15.txt);
+	  only shared key/password authentication is supported in this version
+
+2007-11-24 - v0.6.1
+	* added experimental, integrated TLSv1 server implementation with the
+	  needed X.509/ASN.1/RSA/bignum processing (this can be enabled by
+	  setting CONFIG_TLS=internal and CONFIG_INTERNAL_LIBTOMMATH=y in
+	  .config); this can be useful, e.g., if the target system does not
+	  have a suitable TLS library and a minimal code size is required
+	* added support for EAP-FAST server method to the integrated EAP
+	  server
+	* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
+	  draft (draft-ietf-emu-eap-gpsk-07.txt)
+	* added a new configuration parameter, rsn_pairwise, to allow different
+	  pairwise cipher suites to be enabled for WPA and RSN/WPA2
+	  (note: if wpa_pairwise differs from rsn_pairwise, the driver will
+	  either need to support this or will have to use the WPA/RSN IEs from
+	  hostapd; currently, the included madwifi and bsd driver interfaces do
+	  not have support for this)
+	* updated FT support to use the latest draft, IEEE 802.11r/D8.0
+
+2007-05-28 - v0.6.0
+	* added experimental IEEE 802.11r/D6.0 support
+	* updated EAP-SAKE to RFC 4763 and the IANA-allocated EAP type 48
+	* updated EAP-PSK to use the IANA-allocated EAP type 47
+	* fixed EAP-PSK bit ordering of the Flags field
+	* fixed configuration reloading (SIGHUP) to re-initialize WPA PSKs
+	  by reading wpa_psk_file [Bug 181]
+	* fixed EAP-TTLS AVP parser processing for too short AVP lengths
+	* fixed IPv6 connection to RADIUS accounting server
+	* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
+	  draft (draft-ietf-emu-eap-gpsk-04.txt)
+	* hlr_auc_gw: read GSM triplet file into memory and rotate through the
+	  entries instead of only using the same three triplets every time
+	  (this does not work properly with tests using multiple clients, but
+	  provides bit better triplet data for testing a single client; anyway,
+	  if a better quality triplets are needed, GSM-Milenage should be used
+	  instead of hardcoded triplet file)
+	* fixed EAP-MSCHAPv2 server to use a space between S and M parameters
+	  in Success Request [Bug 203]
+	* added support for sending EAP-AKA Notifications in error cases
+	* updated to use IEEE 802.11w/D2.0 for management frame protection
+	  (still experimental)
+	* RADIUS server: added support for processing duplicate messages
+	  (retransmissions from RADIUS client) by replying with the previous
+	  reply
+
+2006-11-24 - v0.5.6
+	* added support for configuring and controlling multiple BSSes per
+	  radio interface (bss=<ifname> in hostapd.conf); this is only
+	  available with Devicescape and test driver interfaces
+	* fixed PMKSA cache update in the end of successful RSN
+	  pre-authentication
+	* added support for dynamic VLAN configuration (i.e., selecting VLAN-ID
+	  for each STA based on RADIUS Access-Accept attributes); this requires
+	  VLAN support from the kernel driver/802.11 stack and this is
+	  currently only available with Devicescape and test driver interfaces
+	* driver_madwifi: fixed configuration of unencrypted modes (plaintext
+	  and IEEE 802.1X without WEP)
+	* removed STAKey handshake since PeerKey handshake has replaced it in
+	  IEEE 802.11ma and there are no known deployments of STAKey
+	* updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest
+	  draft (draft-ietf-emu-eap-gpsk-01.txt)
+	* added preliminary implementation of IEEE 802.11w/D1.0 (management
+	  frame protection)
+	  (Note: this requires driver support to work properly.)
+	  (Note2: IEEE 802.11w is an unapproved draft and subject to change.)
+	* hlr_auc_gw: added support for GSM-Milenage (for EAP-SIM)
+	* hlr_auc_gw: added support for reading per-IMSI Milenage keys and
+	  parameters from a text file to make it possible to implement proper
+	  GSM/UMTS authentication server for multiple SIM/USIM cards using
+	  EAP-SIM/EAP-AKA
+	* fixed session timeout processing with drivers that do not use
+	  ieee802_11.c (e.g., madwifi)
+
+2006-08-27 - v0.5.5
+	* added 'hostapd_cli new_sta <addr>' command for adding a new STA into
+	  hostapd (e.g., to initialize wired network authentication based on an
+	  external signal)
+	* fixed hostapd to add PMKID KDE into 4-Way Handshake Message 1 when
+	  using WPA2 even if PMKSA caching is not used
+	* added -P<pid file> argument for hostapd to write the current process
+	  id into a file
+	* added support for RADIUS Authentication Server MIB (RFC 2619)
+
+2006-06-20 - v0.5.4
+	* fixed nt_password_hash build [Bug 144]
+	* added PeerKey handshake implementation for IEEE 802.11e
+	  direct link setup (DLS) to replace STAKey handshake
+	* added support for EAP Generalized Pre-Shared Key (EAP-GPSK,
+	  draft-clancy-emu-eap-shared-secret-00.txt)
+	* fixed a segmentation fault when RSN pre-authentication was completed
+	  successfully [Bug 152]
+
+2006-04-27 - v0.5.3
+	* do not build nt_password_hash and hlr_auc_gw by default to avoid
+	  requiring a TLS library for a successful build; these programs can be
+	  build with 'make nt_password_hash' and 'make hlr_auc_gw'
+	* added a new configuration option, eapol_version, that can be used to
+	  set EAPOL version to 1 (default is 2) to work around broken client
+	  implementations that drop EAPOL frames which use version number 2
+	  [Bug 89]
+	* added support for EAP-SAKE (no EAP method number allocated yet, so
+	  this is using the same experimental type 255 as EAP-PSK)
+	* fixed EAP-MSCHAPv2 message length validation
+
+2006-03-19 - v0.5.2
+	* fixed stdarg use in hostapd_logger(): if both stdout and syslog
+	  logging was enabled, hostapd could trigger a segmentation fault in
+	  vsyslog on some CPU -- C library combinations
+	* moved HLR/AuC gateway implementation for EAP-SIM/AKA into an external
+	  program to make it easier to use for implementing real SS7 gateway;
+	  eap_sim_db is not anymore used as a file name for GSM authentication
+	  triplets; instead, it is path to UNIX domain socket that will be used
+	  to communicate with the external gateway program (e.g., hlr_auc_gw)
+	* added example HLR/AuC gateway implementation, hlr_auc_gw, that uses
+	  local information (GSM authentication triplets from a text file and
+	  hardcoded AKA authentication data); this can be used to test EAP-SIM
+	  and EAP-AKA
+	* added Milenage algorithm (example 3GPP AKA algorithm) to hlr_auc_gw
+	  to make it possible to test EAP-AKA with real USIM cards (this is
+	  disabled by default; define AKA_USE_MILENAGE when building hlr_auc_gw
+	  to enable this)
+	* driver_madwifi: added support for getting station RSN IE from
+	  madwifi-ng svn r1453 and newer; this fixes RSN that was apparently
+	  broken with earlier change (r1357) in the driver
+	* changed EAP method registration to use a dynamic list of methods
+	  instead of a static list generated at build time
+	* fixed WPA message 3/4 not to encrypt Key Data field (WPA IE)
+	  [Bug 125]
+	* added ap_max_inactivity configuration parameter
+
+2006-01-29 - v0.5.1
+	* driver_test: added better support for multiple APs and STAs by using
+	  a directory with sockets that include MAC address for each device in
+	  the name (test_socket=DIR:/tmp/test)
+	* added support for EAP expanded type (vendor specific EAP methods)
+
+2005-12-18 - v0.5.0 (beginning of 0.5.x development releases)
+	* added experimental STAKey handshake implementation for IEEE 802.11e
+	  direct link setup (DLS); note: this is disabled by default in both
+	  build and runtime configuration (can be enabled with CONFIG_STAKEY=y
+	  and stakey=1)
+	* added support for EAP methods to use callbacks to external programs
+	  by buffering a pending request and processing it after the EAP method
+	  is ready to continue
+	* improved EAP-SIM database interface to allow external request to GSM
+	  HLR/AuC without blocking hostapd process
+	* added support for using EAP-SIM pseudonyms and fast re-authentication
+	* added support for EAP-AKA in the integrated EAP authenticator
+	* added support for matching EAP identity prefixes (e.g., "1"*) in EAP
+	  user database to allow EAP-SIM/AKA selection without extra roundtrip
+	  for EAP-Nak negotiation
+	* added support for storing EAP user password as NtPasswordHash instead
+	  of plaintext password when using MSCHAP or MSCHAPv2 for
+	  authentication (hash:<16-octet hex value>); added nt_password_hash
+	  tool for hashing password to generate NtPasswordHash
+
+2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases)
+	* driver_wired: fixed EAPOL sending to optionally use PAE group address
+	  as the destination instead of supplicant MAC address; this is
+	  disabled by default, but should be enabled with use_pae_group_addr=1
+	  in configuration file if the wired interface is used by only one
+	  device at the time (common switch configuration)
+	* driver_madwifi: configure driver to use TKIP countermeasures in order
+	  to get correct behavior (IEEE 802.11 association failing; previously,
+	  association succeeded, but hostpad forced disassociation immediately)
+	* driver_madwifi: added support for madwifi-ng
+
+2005-10-27 - v0.4.6
+	* added support for replacing user identity from EAP with RADIUS
+	  User-Name attribute from Access-Accept message, if that is included,
+	  for the RADIUS accounting messages (e.g., for EAP-PEAP/TTLS to get
+	  tunneled identity into accounting messages when the RADIUS server
+	  does not support better way of doing this with Class attribute)
+	* driver_madwifi: fixed EAPOL packet receive for configuration where
+	  ath# is part of a bridge interface
+	* added a configuration file and log analyzer script for logwatch
+	* fixed EAPOL state machine step function to process all state
+	  transitions before processing new events; this resolves a race
+	  condition in which EAPOL-Start message could trigger hostapd to send
+	  two EAP-Response/Identity frames to the authentication server
+
+2005-09-25 - v0.4.5
+	* added client CA list to the TLS certificate request in order to make
+	  it easier for the client to select which certificate to use
+	* added experimental support for EAP-PSK
+	* added support for WE-19 (hostap, madwifi)
+
+2005-08-21 - v0.4.4
+	* fixed build without CONFIG_RSN_PREAUTH
+	* fixed FreeBSD build
+
+2005-06-26 - v0.4.3
+	* fixed PMKSA caching to copy User-Name and Class attributes so that
+	  RADIUS accounting gets correct information
+	* start RADIUS accounting only after successful completion of WPA
+	  4-Way Handshake if WPA-PSK is used
+	* fixed PMKSA caching for the case where STA (re)associates without
+	  first disassociating
+
+2005-06-12 - v0.4.2
+	* EAP-PAX is now registered as EAP type 46
+	* fixed EAP-PAX MAC calculation
+	* fixed EAP-PAX CK and ICK key derivation
+	* renamed eap_authenticator configuration variable to eap_server to
+	  better match with RFC 3748 (EAP) terminology
+	* driver_test: added support for testing hostapd with wpa_supplicant
+	  by using test driver interface without any kernel drivers or network
+	  cards
+
+2005-05-22 - v0.4.1
+	* fixed RADIUS server initialization when only auth or acct server
+	  is configured and the other one is left empty
+	* driver_madwifi: added support for RADIUS accounting
+	* driver_madwifi: added preliminary support for compiling against 'BSD'
+	  branch of madwifi CVS tree
+	* driver_madwifi: fixed pairwise key removal to allow WPA reauth
+	  without disassociation
+	* added support for reading additional certificates from PKCS#12 files
+	  and adding them to the certificate chain
+	* fixed RADIUS Class attribute processing to only use Access-Accept
+	  packets to update Class; previously, other RADIUS authentication
+	  packets could have cleared Class attribute
+	* added support for more than one Class attribute in RADIUS packets
+	* added support for verifying certificate revocation list (CRL) when
+	  using integrated EAP authenticator for EAP-TLS; new hostapd.conf
+	  options 'check_crl'; CRL must be included in the ca_cert file for now
+
+2005-04-25 - v0.4.0 (beginning of 0.4.x development releases)
+	* added support for including network information into
+	  EAP-Request/Identity message (ASCII-0 (nul) in eap_message)
+	  (e.g., to implement draft-adrange-eap-network-discovery-07.txt)
+	* fixed a bug which caused some RSN pre-authentication cases to use
+	  freed memory and potentially crash hostapd
+	* fixed private key loading for cases where passphrase is not set
+	* added support for sending TLS alerts and aborting authentication
+	  when receiving a TLS alert
+	* fixed WPA2 to add PMKSA cache entry when using integrated EAP
+	  authenticator
+	* fixed PMKSA caching (EAP authentication was not skipped correctly
+	  with the new state machine changes from IEEE 802.1X draft)
+	* added support for RADIUS over IPv6; own_ip_addr, auth_server_addr,
+	  and acct_server_addr can now be IPv6 addresses (CONFIG_IPV6=y needs
+	  to be added to .config to include IPv6 support); for RADIUS server,
+	  radius_server_ipv6=1 needs to be set in hostapd.conf and addresses
+	  in RADIUS clients file can then use IPv6 format
+	* added experimental support for EAP-PAX
+	* replaced hostapd control interface library (hostapd_ctrl.[ch]) with
+	  the same implementation that wpa_supplicant is using (wpa_ctrl.[ch])
+
+2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases)
+
+2005-01-23 - v0.3.5
+	* added support for configuring a forced PEAP version based on the
+	  Phase 1 identity
+	* fixed PEAPv1 to use tunneled EAP-Success/Failure instead of EAP-TLV
+	  to terminate authentication
+	* fixed EAP identifier duplicate processing with the new IEEE 802.1X
+	  draft
+	* clear accounting data in the driver when starting a new accounting
+	  session
+	* driver_madwifi: filter wireless events based on ifindex to allow more
+	  than one network interface to be used
+	* fixed WPA message 2/4 processing not to cancel timeout for TimeoutEvt
+	  setting if the packet does not pass MIC verification (e.g., due to
+	  incorrect PSK); previously, message 1/4 was not tried again if an
+	  invalid message 2/4 was received
+	* fixed reconfiguration of RADIUS client retransmission timer when
+	  adding a new message to the pending list; previously, timer was not
+	  updated at this point and if there was a pending message with long
+	  time for the next retry, the new message needed to wait that long for
+	  its first retry, too
+
+2005-01-09 - v0.3.4
+	* added support for configuring multiple allowed EAP types for Phase 2
+	  authentication (EAP-PEAP, EAP-TTLS)
+	* fixed EAPOL-Start processing to trigger WPA reauthentication
+	  (previously, only EAPOL authentication was done)
+
+2005-01-02 - v0.3.3
+	* added support for EAP-PEAP in the integrated EAP authenticator
+	* added support for EAP-GTC in the integrated EAP authenticator
+	* added support for configuring list of EAP methods for Phase 1 so that
+	  the integrated EAP authenticator can, e.g., use the wildcard entry
+	  for EAP-TLS and EAP-PEAP
+	* added support for EAP-TTLS in the integrated EAP authenticator
+	* added support for EAP-SIM in the integrated EAP authenticator
+	* added support for using hostapd as a RADIUS authentication server
+	  with the integrated EAP authenticator taking care of EAP
+	  authentication (new hostapd.conf options: radius_server_clients and
+	  radius_server_auth_port); this is not included in default build; use
+	  CONFIG_RADIUS_SERVER=y in .config to include
+
+2004-12-19 - v0.3.2
+	* removed 'daemonize' configuration file option since it has not really
+	  been used at all for more than year
+	* driver_madwifi: fixed group key setup and added get_ssid method
+	* added support for EAP-MSCHAPv2 in the integrated EAP authenticator
+
+2004-12-12 - v0.3.1
+	* added support for integrated EAP-TLS authentication (new hostapd.conf
+	  variables: ca_cert, server_cert, private_key, private_key_passwd);
+	  this enabled dynamic keying (WPA2/WPA/IEEE 802.1X/WEP) without
+	  external RADIUS server
+	* added support for reading PKCS#12 (PFX) files (as a replacement for
+	  PEM/DER) to get certificate and private key (CONFIG_PKCS12)
+
+2004-12-05 - v0.3.0 (beginning of 0.3.x development releases)
+	* added support for Acct-{Input,Output}-Gigawords
+	* added support for Event-Timestamp (in RADIUS Accounting-Requests)
+	* added support for RADIUS Authentication Client MIB (RFC2618)
+	* added support for RADIUS Accounting Client MIB (RFC2620)
+	* made EAP re-authentication period configurable (eap_reauth_period)
+	* fixed EAPOL reauthentication to trigger WPA/WPA2 reauthentication
+	* fixed EAPOL state machine to stop if STA is removed during
+	  eapol_sm_step(); this fixes at least one segfault triggering bug with
+	  IEEE 802.11i pre-authentication
+	* added support for multiple WPA pre-shared keys (e.g., one for each
+	  client MAC address or keys shared by a group of clients);
+	  new hostapd.conf field wpa_psk_file for setting path to a text file
+	  containing PSKs, see hostapd.wpa_psk for an example
+	* added support for multiple driver interfaces to allow hostapd to be
+	  used with other drivers
+	* added wired authenticator driver interface (driver=wired in
+	  hostapd.conf, see wired.conf for example configuration)
+	* added madwifi driver interface (driver=madwifi in hostapd.conf, see
+	  madwifi.conf for example configuration; Note: include files from
+	  madwifi project is needed for building and a configuration file,
+	  .config, needs to be created in hostapd directory with
+	  CONFIG_DRIVER_MADWIFI=y to include this driver interface in hostapd
+	  build)
+	* fixed an alignment issue that could cause SHA-1 to fail on some
+	  platforms (e.g., Intel ixp425 with a compiler that does not 32-bit
+	  align variables)
+	* fixed RADIUS reconnection after an error in sending interim
+	  accounting packets
+	* added hostapd control interface for external programs and an example
+	  CLI, hostapd_cli (like wpa_cli for wpa_supplicant)
+	* started adding dot11, dot1x, radius MIBs ('hostapd_cli mib',
+	  'hostapd_cli sta <addr>')
+	* finished update from IEEE 802.1X-2001 to IEEE 802.1X-REV (now d11)
+	* added support for strict GTK rekeying (wpa_strict_rekey in
+	  hostapd.conf)
+	* updated IAPP to use UDP port 3517 and multicast address 224.0.1.178
+	  (instead of broadcast) for IAPP ADD-notify (moved from draft 3 to
+	  IEEE 802.11F-2003)
+	* added Prism54 driver interface (driver=prism54 in hostapd.conf;
+	  note: .config needs to be created in hostapd directory with
+	  CONFIG_DRIVER_PRISM54=y to include this driver interface in hostapd
+	  build)
+	* dual-licensed hostapd (GPLv2 and BSD licenses)
+	* fixed RADIUS accounting to generate a new session id for cases where
+	  a station reassociates without first being complete deauthenticated
+	* fixed STA disassociation handler to mark next timeout state to
+	  deauthenticate the station, i.e., skip long wait for inactivity poll
+	  and extra disassociation, if the STA disassociates without
+	  deauthenticating
+	* added integrated EAP authenticator that can be used instead of
+	  external RADIUS authentication server; currently, only EAP-MD5 is
+	  supported, so this cannot yet be used for key distribution; the EAP
+	  method interface is generic, though, so adding new EAP methods should
+	  be straightforward; new hostapd.conf variables: 'eap_authenticator'
+	  and 'eap_user_file'; this obsoletes "minimal authentication server"
+	  ('minimal_eap' in hostapd.conf) which is now removed
+	* added support for FreeBSD and driver interface for the BSD net80211
+	  layer (driver=bsd in hostapd.conf and CONFIG_DRIVER_BSD=y in
+	  .config); please note that some of the required kernel mods have not
+	  yet been committed
+
+2004-07-17 - v0.2.4 (beginning of 0.2.x stable releases)
+	* fixed some accounting cases where Accounting-Start was sent when
+	  IEEE 802.1X port was being deauthorized
+
+2004-06-20 - v0.2.3
+	* modified RADIUS client to re-connect the socket in case of certain
+	  error codes that are generated when a network interface state is
+	  changes (e.g., when IP address changes or the interface is set UP)
+	* fixed couple of cases where EAPOL state for a station was freed
+	  twice causing a segfault for hostapd
+	* fixed couple of bugs in processing WPA deauthentication (freed data
+	  was used)
+
+2004-05-31 - v0.2.2
+	* fixed WPA/WPA2 group rekeying to use key index correctly (GN/GM)
+	* fixed group rekeying to send zero TSC in EAPOL-Key messages to fix
+	  cases where STAs dropped multicast frames as replay attacks
+	* added support for copying RADIUS Attribute 'Class' from
+	  authentication messages into accounting messages
+	* send canned EAP failure if RADIUS server sends Access-Reject without
+	  EAP message (previously, Supplicant was not notified in this case)
+	* fixed mixed WPA-PSK and WPA-EAP mode to work with WPA-PSK (i.e., do
+	  not start EAPOL state machines if the STA selected to use WPA-PSK)
+
+2004-05-06 - v0.2.1
+	* added WPA and IEEE 802.11i/RSN (WPA2) Authenticator functionality
+	  - based on IEEE 802.11i/D10.0 but modified to interoperate with WPA
+	    (i.e., IEEE 802.11i/D3.0)
+	  - supports WPA-only, RSN-only, and mixed WPA/RSN mode
+	  - both WPA-PSK and WPA-RADIUS/EAP are supported
+	  - PMKSA caching and pre-authentication
+	  - new hostapd.conf variables: wpa, wpa_psk, wpa_passphrase,
+	    wpa_key_mgmt, wpa_pairwise, wpa_group_rekey, wpa_gmk_rekey,
+	    rsn_preauth, rsn_preauth_interfaces
+	* fixed interim accounting to remove any pending accounting messages
+	  to the STA before sending a new one
+
+2004-02-15 - v0.2.0
+	* added support for Acct-Interim-Interval:
+	  - draft-ietf-radius-acct-interim-01.txt
+	  - use Acct-Interim-Interval attribute from Access-Accept if local
+	    'radius_acct_interim_interval' is not set
+	  - allow different update intervals for each STA
+	* fixed event loop to call signal handlers only after returning from
+	  the real signal handler
+	* reset sta->timeout_next after successful association to make sure
+	  that the previously registered inactivity timer will not remove the
+	  STA immediately (e.g., if STA deauthenticates and re-associates
+	  before the timer is triggered).
+	* added new hostapd.conf variable, nas_identifier, that can be used to
+	  add an optional RADIUS Attribute, NAS-Identifier, into authentication
+	  and accounting messages
+	* added support for Accounting-On and Accounting-Off messages
+	* fixed accounting session handling to send Accounting-Start only once
+	  per session and not to send Accounting-Stop if the session was not
+	  initialized properly
+	* fixed Accounting-Stop statistics in cases where the message was
+	  previously sent after the kernel entry for the STA (and/or IEEE
+	  802.1X data) was removed
+
+
+Note:
+
+Older changes up to and including v0.1.0 are included in the ChangeLog
+of the Host AP driver.

+ 1122 - 0
EVSE/GPL/hostapd-2.6/hostapd/Makefile

@@ -0,0 +1,1122 @@
+ifndef CC
+CC=gcc
+endif
+
+ifndef CFLAGS
+CFLAGS = -MMD -O2 -Wall -g
+endif
+
+ifdef LIBS
+# If LIBS is set with some global build system defaults, clone those for
+# LIBS_c, LIBS_h, and LIBS_n to cover hostapd_cli, hlr_auc_gw, and
+# nt_password_hash as well.
+ifndef LIBS_c
+LIBS_c := $(LIBS)
+endif
+ifndef LIBS_h
+LIBS_h := $(LIBS)
+endif
+ifndef LIBS_n
+LIBS_n := $(LIBS)
+endif
+endif
+
+CFLAGS += $(EXTRA_CFLAGS)
+CFLAGS += -I$(abspath ../src)
+CFLAGS += -I$(abspath ../src/utils)
+
+export BINDIR ?= /usr/local/bin/
+
+-include .config
+
+ifndef CONFIG_NO_GITVER
+# Add VERSION_STR postfix for builds from a git repository
+ifeq ($(wildcard ../.git),../.git)
+GITVER := $(shell git describe --dirty=+)
+ifneq ($(GITVER),)
+CFLAGS += -DGIT_VERSION_STR_POSTFIX=\"-$(GITVER)\"
+endif
+endif
+endif
+
+ifdef CONFIG_TESTING_OPTIONS
+CFLAGS += -DCONFIG_TESTING_OPTIONS
+CONFIG_WPS_TESTING=y
+endif
+
+ifndef CONFIG_OS
+ifdef CONFIG_NATIVE_WINDOWS
+CONFIG_OS=win32
+else
+CONFIG_OS=unix
+endif
+endif
+
+ifeq ($(CONFIG_OS), internal)
+CFLAGS += -DOS_NO_C_LIB_DEFINES
+endif
+
+ifdef CONFIG_NATIVE_WINDOWS
+CFLAGS += -DCONFIG_NATIVE_WINDOWS
+LIBS += -lws2_32
+endif
+
+OBJS += main.o
+OBJS += config_file.o
+
+OBJS += ../src/ap/hostapd.o
+OBJS += ../src/ap/wpa_auth_glue.o
+OBJS += ../src/ap/drv_callbacks.o
+OBJS += ../src/ap/ap_drv_ops.o
+OBJS += ../src/ap/utils.o
+OBJS += ../src/ap/authsrv.o
+OBJS += ../src/ap/ieee802_1x.o
+OBJS += ../src/ap/ap_config.o
+OBJS += ../src/ap/eap_user_db.o
+OBJS += ../src/ap/ieee802_11_auth.o
+OBJS += ../src/ap/sta_info.o
+OBJS += ../src/ap/wpa_auth.o
+OBJS += ../src/ap/tkip_countermeasures.o
+OBJS += ../src/ap/ap_mlme.o
+OBJS += ../src/ap/wpa_auth_ie.o
+OBJS += ../src/ap/preauth_auth.o
+OBJS += ../src/ap/pmksa_cache_auth.o
+OBJS += ../src/ap/ieee802_11_shared.o
+OBJS += ../src/ap/beacon.o
+OBJS += ../src/ap/bss_load.o
+OBJS += ../src/ap/neighbor_db.o
+OBJS += ../src/ap/rrm.o
+
+OBJS_c = hostapd_cli.o
+OBJS_c += ../src/common/wpa_ctrl.o
+OBJS_c += ../src/utils/os_$(CONFIG_OS).o
+OBJS_c += ../src/common/cli.o
+
+NEED_RC4=y
+NEED_AES=y
+NEED_MD5=y
+NEED_SHA1=y
+
+OBJS += ../src/drivers/drivers.o
+CFLAGS += -DHOSTAPD
+
+ifdef CONFIG_TAXONOMY
+CFLAGS += -DCONFIG_TAXONOMY
+OBJS += ../src/ap/taxonomy.o
+endif
+
+ifdef CONFIG_MODULE_TESTS
+CFLAGS += -DCONFIG_MODULE_TESTS
+OBJS += hapd_module_tests.o
+endif
+
+ifdef CONFIG_WPA_TRACE
+CFLAGS += -DWPA_TRACE
+OBJS += ../src/utils/trace.o
+HOBJS += ../src/utils/trace.o
+LDFLAGS += -rdynamic
+CFLAGS += -funwind-tables
+ifdef CONFIG_WPA_TRACE_BFD
+CFLAGS += -DPACKAGE="hostapd" -DWPA_TRACE_BFD
+LIBS += -lbfd -ldl -liberty -lz
+LIBS_c += -lbfd -ldl -liberty -lz
+LIBS_h += -lbfd -ldl -liberty -lz
+endif
+endif
+
+ifndef CONFIG_ELOOP
+CONFIG_ELOOP=eloop
+endif
+OBJS += ../src/utils/$(CONFIG_ELOOP).o
+OBJS_c += ../src/utils/$(CONFIG_ELOOP).o
+
+ifeq ($(CONFIG_ELOOP), eloop)
+# Using glibc < 2.17 requires -lrt for clock_gettime()
+LIBS += -lrt
+LIBS_c += -lrt
+LIBS_h += -lrt
+LIBS_n += -lrt
+endif
+
+ifdef CONFIG_ELOOP_POLL
+CFLAGS += -DCONFIG_ELOOP_POLL
+endif
+
+ifdef CONFIG_ELOOP_EPOLL
+CFLAGS += -DCONFIG_ELOOP_EPOLL
+endif
+
+ifdef CONFIG_ELOOP_KQUEUE
+CFLAGS += -DCONFIG_ELOOP_KQUEUE
+endif
+
+OBJS += ../src/utils/common.o
+OBJS_c += ../src/utils/common.o
+OBJS += ../src/utils/wpa_debug.o
+OBJS_c += ../src/utils/wpa_debug.o
+OBJS += ../src/utils/wpabuf.o
+OBJS += ../src/utils/os_$(CONFIG_OS).o
+OBJS += ../src/utils/ip_addr.o
+
+OBJS += ../src/common/ieee802_11_common.o
+OBJS += ../src/common/wpa_common.o
+OBJS += ../src/common/hw_features_common.o
+
+OBJS += ../src/eapol_auth/eapol_auth_sm.o
+
+
+ifdef CONFIG_CODE_COVERAGE
+CFLAGS += -O0 -fprofile-arcs -ftest-coverage
+LIBS += -lgcov
+LIBS_c += -lgcov
+LIBS_h += -lgcov
+LIBS_n += -lgcov
+endif
+
+ifndef CONFIG_NO_DUMP_STATE
+# define HOSTAPD_DUMP_STATE to include support for dumping internal state
+# through control interface commands (undefine it, if you want to save in
+# binary size)
+CFLAGS += -DHOSTAPD_DUMP_STATE
+OBJS += ../src/eapol_auth/eapol_auth_dump.o
+endif
+
+ifdef CONFIG_NO_RADIUS
+CFLAGS += -DCONFIG_NO_RADIUS
+CONFIG_NO_ACCOUNTING=y
+else
+OBJS += ../src/radius/radius.o
+OBJS += ../src/radius/radius_client.o
+OBJS += ../src/radius/radius_das.o
+endif
+
+ifdef CONFIG_NO_ACCOUNTING
+CFLAGS += -DCONFIG_NO_ACCOUNTING
+else
+OBJS += ../src/ap/accounting.o
+endif
+
+ifdef CONFIG_NO_VLAN
+CFLAGS += -DCONFIG_NO_VLAN
+else
+OBJS += ../src/ap/vlan_init.o
+OBJS += ../src/ap/vlan_ifconfig.o
+OBJS += ../src/ap/vlan.o
+ifdef CONFIG_FULL_DYNAMIC_VLAN
+# Define CONFIG_FULL_DYNAMIC_VLAN to have hostapd manipulate bridges
+# and VLAN interfaces for the VLAN feature.
+CFLAGS += -DCONFIG_FULL_DYNAMIC_VLAN
+OBJS += ../src/ap/vlan_full.o
+ifdef CONFIG_VLAN_NETLINK
+OBJS += ../src/ap/vlan_util.o
+else
+OBJS += ../src/ap/vlan_ioctl.o
+endif
+endif
+endif
+
+ifdef CONFIG_NO_CTRL_IFACE
+CFLAGS += -DCONFIG_NO_CTRL_IFACE
+else
+ifeq ($(CONFIG_CTRL_IFACE), udp)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+else
+ifeq ($(CONFIG_CTRL_IFACE), udp6)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_IPV6
+else
+ifeq ($(CONFIG_CTRL_IFACE), udp-remote)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_REMOTE
+else
+ifeq ($(CONFIG_CTRL_IFACE), udp6-remote)
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_REMOTE
+CFLAGS += -DCONFIG_CTRL_IFACE_UDP_IPV6
+else
+CFLAGS += -DCONFIG_CTRL_IFACE_UNIX
+endif
+endif
+endif
+endif
+OBJS += ../src/common/ctrl_iface_common.o
+OBJS += ctrl_iface.o
+OBJS += ../src/ap/ctrl_iface_ap.o
+endif
+
+ifndef CONFIG_NO_CTRL_IFACE
+CFLAGS += -DCONFIG_CTRL_IFACE
+endif
+
+ifdef CONFIG_IAPP
+CFLAGS += -DCONFIG_IAPP
+OBJS += ../src/ap/iapp.o
+endif
+
+ifdef CONFIG_RSN_PREAUTH
+CFLAGS += -DCONFIG_RSN_PREAUTH
+CONFIG_L2_PACKET=y
+endif
+
+ifdef CONFIG_PEERKEY
+CFLAGS += -DCONFIG_PEERKEY
+OBJS += ../src/ap/peerkey_auth.o
+endif
+
+ifdef CONFIG_HS20
+NEED_AES_OMAC1=y
+CONFIG_PROXYARP=y
+endif
+
+ifdef CONFIG_PROXYARP
+CONFIG_L2_PACKET=y
+endif
+
+ifdef CONFIG_SUITEB
+CFLAGS += -DCONFIG_SUITEB
+NEED_SHA256=y
+NEED_AES_OMAC1=y
+endif
+
+ifdef CONFIG_SUITEB192
+CFLAGS += -DCONFIG_SUITEB192
+NEED_SHA384=y
+endif
+
+ifdef CONFIG_IEEE80211W
+CFLAGS += -DCONFIG_IEEE80211W
+NEED_SHA256=y
+NEED_AES_OMAC1=y
+endif
+
+ifdef CONFIG_IEEE80211R
+CFLAGS += -DCONFIG_IEEE80211R
+OBJS += ../src/ap/wpa_auth_ft.o
+NEED_SHA256=y
+NEED_AES_OMAC1=y
+NEED_AES_UNWRAP=y
+endif
+
+ifdef CONFIG_SAE
+CFLAGS += -DCONFIG_SAE
+OBJS += ../src/common/sae.o
+NEED_ECC=y
+NEED_DH_GROUPS=y
+NEED_AP_MLME=y
+endif
+
+ifdef CONFIG_WNM
+CFLAGS += -DCONFIG_WNM
+OBJS += ../src/ap/wnm_ap.o
+endif
+
+ifdef CONFIG_IEEE80211N
+CFLAGS += -DCONFIG_IEEE80211N
+endif
+
+ifdef CONFIG_IEEE80211AC
+CFLAGS += -DCONFIG_IEEE80211AC
+endif
+
+ifdef CONFIG_MBO
+CFLAGS += -DCONFIG_MBO
+OBJS += ../src/ap/mbo_ap.o
+endif
+
+include ../src/drivers/drivers.mak
+OBJS += $(DRV_AP_OBJS)
+CFLAGS += $(DRV_AP_CFLAGS)
+LDFLAGS += $(DRV_AP_LDFLAGS)
+LIBS += $(DRV_AP_LIBS)
+
+ifdef CONFIG_L2_PACKET
+ifdef CONFIG_DNET_PCAP
+ifdef CONFIG_L2_FREEBSD
+LIBS += -lpcap
+OBJS += ../src/l2_packet/l2_packet_freebsd.o
+else
+LIBS += -ldnet -lpcap
+OBJS += ../src/l2_packet/l2_packet_pcap.o
+endif
+else
+OBJS += ../src/l2_packet/l2_packet_linux.o
+endif
+else
+OBJS += ../src/l2_packet/l2_packet_none.o
+endif
+
+
+ifdef CONFIG_ERP
+CFLAGS += -DCONFIG_ERP
+NEED_SHA256=y
+NEED_HMAC_SHA256_KDF=y
+endif
+
+ifdef CONFIG_EAP_MD5
+CFLAGS += -DEAP_SERVER_MD5
+OBJS += ../src/eap_server/eap_server_md5.o
+CHAP=y
+endif
+
+ifdef CONFIG_EAP_TLS
+CFLAGS += -DEAP_SERVER_TLS
+OBJS += ../src/eap_server/eap_server_tls.o
+TLS_FUNCS=y
+endif
+
+ifdef CONFIG_EAP_UNAUTH_TLS
+CFLAGS += -DEAP_SERVER_UNAUTH_TLS
+ifndef CONFIG_EAP_TLS
+OBJS += ../src/eap_server/eap_server_tls.o
+TLS_FUNCS=y
+endif
+endif
+
+ifdef CONFIG_EAP_PEAP
+CFLAGS += -DEAP_SERVER_PEAP
+OBJS += ../src/eap_server/eap_server_peap.o
+OBJS += ../src/eap_common/eap_peap_common.o
+TLS_FUNCS=y
+CONFIG_EAP_MSCHAPV2=y
+endif
+
+ifdef CONFIG_EAP_TTLS
+CFLAGS += -DEAP_SERVER_TTLS
+OBJS += ../src/eap_server/eap_server_ttls.o
+TLS_FUNCS=y
+CHAP=y
+endif
+
+ifdef CONFIG_EAP_MSCHAPV2
+CFLAGS += -DEAP_SERVER_MSCHAPV2
+OBJS += ../src/eap_server/eap_server_mschapv2.o
+MS_FUNCS=y
+endif
+
+ifdef CONFIG_EAP_GTC
+CFLAGS += -DEAP_SERVER_GTC
+OBJS += ../src/eap_server/eap_server_gtc.o
+endif
+
+ifdef CONFIG_EAP_SIM
+CFLAGS += -DEAP_SERVER_SIM
+OBJS += ../src/eap_server/eap_server_sim.o
+CONFIG_EAP_SIM_COMMON=y
+NEED_AES_CBC=y
+endif
+
+ifdef CONFIG_EAP_AKA
+CFLAGS += -DEAP_SERVER_AKA
+OBJS += ../src/eap_server/eap_server_aka.o
+CONFIG_EAP_SIM_COMMON=y
+NEED_SHA256=y
+NEED_AES_CBC=y
+endif
+
+ifdef CONFIG_EAP_AKA_PRIME
+CFLAGS += -DEAP_SERVER_AKA_PRIME
+endif
+
+ifdef CONFIG_EAP_SIM_COMMON
+OBJS += ../src/eap_common/eap_sim_common.o
+# Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be
+# replaced with another file implementating the interface specified in
+# eap_sim_db.h.
+OBJS += ../src/eap_server/eap_sim_db.o
+NEED_FIPS186_2_PRF=y
+endif
+
+ifdef CONFIG_EAP_PAX
+CFLAGS += -DEAP_SERVER_PAX
+OBJS += ../src/eap_server/eap_server_pax.o ../src/eap_common/eap_pax_common.o
+endif
+
+ifdef CONFIG_EAP_PSK
+CFLAGS += -DEAP_SERVER_PSK
+OBJS += ../src/eap_server/eap_server_psk.o ../src/eap_common/eap_psk_common.o
+NEED_AES_OMAC1=y
+NEED_AES_ENCBLOCK=y
+NEED_AES_EAX=y
+endif
+
+ifdef CONFIG_EAP_SAKE
+CFLAGS += -DEAP_SERVER_SAKE
+OBJS += ../src/eap_server/eap_server_sake.o ../src/eap_common/eap_sake_common.o
+endif
+
+ifdef CONFIG_EAP_GPSK
+CFLAGS += -DEAP_SERVER_GPSK
+OBJS += ../src/eap_server/eap_server_gpsk.o ../src/eap_common/eap_gpsk_common.o
+ifdef CONFIG_EAP_GPSK_SHA256
+CFLAGS += -DEAP_GPSK_SHA256
+endif
+NEED_SHA256=y
+NEED_AES_OMAC1=y
+endif
+
+ifdef CONFIG_EAP_PWD
+CFLAGS += -DEAP_SERVER_PWD
+OBJS += ../src/eap_server/eap_server_pwd.o ../src/eap_common/eap_pwd_common.o
+NEED_SHA256=y
+endif
+
+ifdef CONFIG_EAP_EKE
+CFLAGS += -DEAP_SERVER_EKE
+OBJS += ../src/eap_server/eap_server_eke.o ../src/eap_common/eap_eke_common.o
+NEED_DH_GROUPS=y
+NEED_DH_GROUPS_ALL=y
+endif
+
+ifdef CONFIG_EAP_VENDOR_TEST
+CFLAGS += -DEAP_SERVER_VENDOR_TEST
+OBJS += ../src/eap_server/eap_server_vendor_test.o
+endif
+
+ifdef CONFIG_EAP_FAST
+CFLAGS += -DEAP_SERVER_FAST
+OBJS += ../src/eap_server/eap_server_fast.o
+OBJS += ../src/eap_common/eap_fast_common.o
+TLS_FUNCS=y
+NEED_T_PRF=y
+NEED_AES_UNWRAP=y
+endif
+
+ifdef CONFIG_WPS
+CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC
+OBJS += ../src/utils/uuid.o
+OBJS += ../src/ap/wps_hostapd.o
+OBJS += ../src/eap_server/eap_server_wsc.o ../src/eap_common/eap_wsc_common.o
+OBJS += ../src/wps/wps.o
+OBJS += ../src/wps/wps_common.o
+OBJS += ../src/wps/wps_attr_parse.o
+OBJS += ../src/wps/wps_attr_build.o
+OBJS += ../src/wps/wps_attr_process.o
+OBJS += ../src/wps/wps_dev_attr.o
+OBJS += ../src/wps/wps_enrollee.o
+OBJS += ../src/wps/wps_registrar.o
+NEED_DH_GROUPS=y
+NEED_SHA256=y
+NEED_BASE64=y
+NEED_AES_CBC=y
+NEED_MODEXP=y
+CONFIG_EAP=y
+
+ifdef CONFIG_WPS_NFC
+CFLAGS += -DCONFIG_WPS_NFC
+OBJS += ../src/wps/ndef.o
+NEED_WPS_OOB=y
+endif
+
+ifdef NEED_WPS_OOB
+CFLAGS += -DCONFIG_WPS_OOB
+endif
+
+ifdef CONFIG_WPS_UPNP
+CFLAGS += -DCONFIG_WPS_UPNP
+OBJS += ../src/wps/wps_upnp.o
+OBJS += ../src/wps/wps_upnp_ssdp.o
+OBJS += ../src/wps/wps_upnp_web.o
+OBJS += ../src/wps/wps_upnp_event.o
+OBJS += ../src/wps/wps_upnp_ap.o
+OBJS += ../src/wps/upnp_xml.o
+OBJS += ../src/wps/httpread.o
+OBJS += ../src/wps/http_client.o
+OBJS += ../src/wps/http_server.o
+endif
+
+ifdef CONFIG_WPS_STRICT
+CFLAGS += -DCONFIG_WPS_STRICT
+OBJS += ../src/wps/wps_validate.o
+endif
+
+ifdef CONFIG_WPS_TESTING
+CFLAGS += -DCONFIG_WPS_TESTING
+endif
+
+endif
+
+ifdef CONFIG_EAP_IKEV2
+CFLAGS += -DEAP_SERVER_IKEV2
+OBJS += ../src/eap_server/eap_server_ikev2.o ../src/eap_server/ikev2.o
+OBJS += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o
+NEED_DH_GROUPS=y
+NEED_DH_GROUPS_ALL=y
+NEED_MODEXP=y
+NEED_CIPHER=y
+endif
+
+ifdef CONFIG_EAP_TNC
+CFLAGS += -DEAP_SERVER_TNC
+OBJS += ../src/eap_server/eap_server_tnc.o
+OBJS += ../src/eap_server/tncs.o
+NEED_BASE64=y
+ifndef CONFIG_DRIVER_BSD
+LIBS += -ldl
+endif
+endif
+
+# Basic EAP functionality is needed for EAPOL
+OBJS += eap_register.o
+OBJS += ../src/eap_server/eap_server.o
+OBJS += ../src/eap_common/eap_common.o
+OBJS += ../src/eap_server/eap_server_methods.o
+OBJS += ../src/eap_server/eap_server_identity.o
+CFLAGS += -DEAP_SERVER_IDENTITY
+
+ifdef CONFIG_EAP
+CFLAGS += -DEAP_SERVER
+endif
+
+ifdef CONFIG_PKCS12
+CFLAGS += -DPKCS12_FUNCS
+endif
+
+ifdef MS_FUNCS
+OBJS += ../src/crypto/ms_funcs.o
+NEED_DES=y
+NEED_MD4=y
+endif
+
+ifdef CHAP
+OBJS += ../src/eap_common/chap.o
+endif
+
+ifdef TLS_FUNCS
+NEED_DES=y
+# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS)
+CFLAGS += -DEAP_TLS_FUNCS
+OBJS += ../src/eap_server/eap_server_tls_common.o
+NEED_TLS_PRF=y
+endif
+
+ifndef CONFIG_TLS
+CONFIG_TLS=openssl
+endif
+
+ifdef CONFIG_TLSV11
+CFLAGS += -DCONFIG_TLSV11
+endif
+
+ifdef CONFIG_TLSV12
+CFLAGS += -DCONFIG_TLSV12
+NEED_SHA256=y
+endif
+
+ifeq ($(CONFIG_TLS), openssl)
+ifdef TLS_FUNCS
+OBJS += ../src/crypto/tls_openssl.o
+OBJS += ../src/crypto/tls_openssl_ocsp.o
+LIBS += -lssl
+endif
+OBJS += ../src/crypto/crypto_openssl.o
+HOBJS += ../src/crypto/crypto_openssl.o
+ifdef NEED_FIPS186_2_PRF
+OBJS += ../src/crypto/fips_prf_openssl.o
+endif
+NEED_SHA256=y
+NEED_TLS_PRF_SHA256=y
+LIBS += -lcrypto
+LIBS_h += -lcrypto
+ifdef CONFIG_TLS_ADD_DL
+LIBS += -ldl
+LIBS_h += -ldl
+endif
+endif
+
+ifeq ($(CONFIG_TLS), gnutls)
+ifdef TLS_FUNCS
+OBJS += ../src/crypto/tls_gnutls.o
+LIBS += -lgnutls -lgpg-error
+endif
+OBJS += ../src/crypto/crypto_gnutls.o
+HOBJS += ../src/crypto/crypto_gnutls.o
+ifdef NEED_FIPS186_2_PRF
+OBJS += ../src/crypto/fips_prf_internal.o
+SHA1OBJS += ../src/crypto/sha1-internal.o
+endif
+LIBS += -lgcrypt
+LIBS_h += -lgcrypt
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+
+ifeq ($(CONFIG_TLS), internal)
+ifndef CONFIG_CRYPTO
+CONFIG_CRYPTO=internal
+endif
+ifdef TLS_FUNCS
+OBJS += ../src/crypto/crypto_internal-rsa.o
+OBJS += ../src/crypto/tls_internal.o
+OBJS += ../src/tls/tlsv1_common.o
+OBJS += ../src/tls/tlsv1_record.o
+OBJS += ../src/tls/tlsv1_cred.o
+OBJS += ../src/tls/tlsv1_server.o
+OBJS += ../src/tls/tlsv1_server_write.o
+OBJS += ../src/tls/tlsv1_server_read.o
+OBJS += ../src/tls/asn1.o
+OBJS += ../src/tls/rsa.o
+OBJS += ../src/tls/x509v3.o
+OBJS += ../src/tls/pkcs1.o
+OBJS += ../src/tls/pkcs5.o
+OBJS += ../src/tls/pkcs8.o
+NEED_SHA256=y
+NEED_BASE64=y
+NEED_TLS_PRF=y
+ifdef CONFIG_TLSV12
+NEED_TLS_PRF_SHA256=y
+endif
+NEED_MODEXP=y
+NEED_CIPHER=y
+CFLAGS += -DCONFIG_TLS_INTERNAL
+CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
+endif
+ifdef NEED_CIPHER
+NEED_DES=y
+OBJS += ../src/crypto/crypto_internal-cipher.o
+endif
+ifdef NEED_MODEXP
+OBJS += ../src/crypto/crypto_internal-modexp.o
+OBJS += ../src/tls/bignum.o
+endif
+ifeq ($(CONFIG_CRYPTO), libtomcrypt)
+OBJS += ../src/crypto/crypto_libtomcrypt.o
+LIBS += -ltomcrypt -ltfm
+LIBS_h += -ltomcrypt -ltfm
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+ifeq ($(CONFIG_CRYPTO), internal)
+OBJS += ../src/crypto/crypto_internal.o
+NEED_AES_DEC=y
+CFLAGS += -DCONFIG_CRYPTO_INTERNAL
+ifdef CONFIG_INTERNAL_LIBTOMMATH
+CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
+ifdef CONFIG_INTERNAL_LIBTOMMATH_FAST
+CFLAGS += -DLTM_FAST
+endif
+else
+LIBS += -ltommath
+LIBS_h += -ltommath
+endif
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_DES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD4=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_SHA384=y
+CONFIG_INTERNAL_SHA512=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+ifeq ($(CONFIG_CRYPTO), cryptoapi)
+OBJS += ../src/crypto/crypto_cryptoapi.o
+OBJS_p += ../src/crypto/crypto_cryptoapi.o
+CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_RC4=y
+endif
+endif
+
+ifeq ($(CONFIG_TLS), none)
+ifdef TLS_FUNCS
+OBJS += ../src/crypto/tls_none.o
+CFLAGS += -DEAP_TLS_NONE
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD5=y
+endif
+OBJS += ../src/crypto/crypto_none.o
+OBJS_p += ../src/crypto/crypto_none.o
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_RC4=y
+endif
+
+ifndef TLS_FUNCS
+OBJS += ../src/crypto/tls_none.o
+ifeq ($(CONFIG_TLS), internal)
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_RC4=y
+endif
+endif
+
+AESOBJS = # none so far
+ifdef CONFIG_INTERNAL_AES
+AESOBJS += ../src/crypto/aes-internal.o ../src/crypto/aes-internal-enc.o
+endif
+
+ifneq ($(CONFIG_TLS), openssl)
+AESOBJS += ../src/crypto/aes-wrap.o
+endif
+ifdef NEED_AES_EAX
+AESOBJS += ../src/crypto/aes-eax.o
+NEED_AES_CTR=y
+endif
+ifdef NEED_AES_CTR
+AESOBJS += ../src/crypto/aes-ctr.o
+endif
+ifdef NEED_AES_ENCBLOCK
+AESOBJS += ../src/crypto/aes-encblock.o
+endif
+ifdef NEED_AES_OMAC1
+AESOBJS += ../src/crypto/aes-omac1.o
+endif
+ifdef NEED_AES_UNWRAP
+ifneq ($(CONFIG_TLS), openssl)
+NEED_AES_DEC=y
+AESOBJS += ../src/crypto/aes-unwrap.o
+endif
+endif
+ifdef NEED_AES_CBC
+NEED_AES_DEC=y
+ifneq ($(CONFIG_TLS), openssl)
+AESOBJS += ../src/crypto/aes-cbc.o
+endif
+endif
+ifdef NEED_AES_DEC
+ifdef CONFIG_INTERNAL_AES
+AESOBJS += ../src/crypto/aes-internal-dec.o
+endif
+endif
+ifdef NEED_AES
+OBJS += $(AESOBJS)
+endif
+
+ifdef NEED_SHA1
+ifneq ($(CONFIG_TLS), openssl)
+SHA1OBJS += ../src/crypto/sha1.o
+endif
+SHA1OBJS += ../src/crypto/sha1-prf.o
+ifdef CONFIG_INTERNAL_SHA1
+SHA1OBJS += ../src/crypto/sha1-internal.o
+ifdef NEED_FIPS186_2_PRF
+SHA1OBJS += ../src/crypto/fips_prf_internal.o
+endif
+endif
+ifneq ($(CONFIG_TLS), openssl)
+SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
+endif
+ifdef NEED_T_PRF
+SHA1OBJS += ../src/crypto/sha1-tprf.o
+endif
+ifdef NEED_TLS_PRF
+SHA1OBJS += ../src/crypto/sha1-tlsprf.o
+endif
+endif
+
+ifdef NEED_SHA1
+OBJS += $(SHA1OBJS)
+endif
+
+ifneq ($(CONFIG_TLS), openssl)
+OBJS += ../src/crypto/md5.o
+endif
+
+ifdef NEED_MD5
+ifdef CONFIG_INTERNAL_MD5
+OBJS += ../src/crypto/md5-internal.o
+HOBJS += ../src/crypto/md5-internal.o
+endif
+endif
+
+ifdef NEED_MD4
+ifdef CONFIG_INTERNAL_MD4
+OBJS += ../src/crypto/md4-internal.o
+endif
+endif
+
+ifdef NEED_DES
+ifdef CONFIG_INTERNAL_DES
+OBJS += ../src/crypto/des-internal.o
+endif
+endif
+
+ifdef CONFIG_NO_RC4
+CFLAGS += -DCONFIG_NO_RC4
+endif
+
+ifdef NEED_RC4
+ifdef CONFIG_INTERNAL_RC4
+ifndef CONFIG_NO_RC4
+OBJS += ../src/crypto/rc4.o
+endif
+endif
+endif
+
+ifdef NEED_SHA256
+CFLAGS += -DCONFIG_SHA256
+ifneq ($(CONFIG_TLS), openssl)
+OBJS += ../src/crypto/sha256.o
+endif
+OBJS += ../src/crypto/sha256-prf.o
+ifdef CONFIG_INTERNAL_SHA256
+OBJS += ../src/crypto/sha256-internal.o
+endif
+ifdef NEED_TLS_PRF_SHA256
+OBJS += ../src/crypto/sha256-tlsprf.o
+endif
+ifdef NEED_HMAC_SHA256_KDF
+OBJS += ../src/crypto/sha256-kdf.o
+endif
+endif
+ifdef NEED_SHA384
+CFLAGS += -DCONFIG_SHA384
+OBJS += ../src/crypto/sha384-prf.o
+endif
+
+ifdef CONFIG_INTERNAL_SHA384
+CFLAGS += -DCONFIG_INTERNAL_SHA384
+OBJS += ../src/crypto/sha384-internal.o
+endif
+
+ifdef CONFIG_INTERNAL_SHA512
+CFLAGS += -DCONFIG_INTERNAL_SHA512
+OBJS += ../src/crypto/sha512-internal.o
+endif
+
+ifdef NEED_DH_GROUPS
+OBJS += ../src/crypto/dh_groups.o
+endif
+ifdef NEED_DH_GROUPS_ALL
+CFLAGS += -DALL_DH_GROUPS
+endif
+ifdef CONFIG_INTERNAL_DH_GROUP5
+ifdef NEED_DH_GROUPS
+OBJS += ../src/crypto/dh_group5.o
+endif
+endif
+
+ifdef NEED_ECC
+CFLAGS += -DCONFIG_ECC
+endif
+
+ifdef CONFIG_NO_RANDOM_POOL
+CFLAGS += -DCONFIG_NO_RANDOM_POOL
+else
+OBJS += ../src/crypto/random.o
+HOBJS += ../src/crypto/random.o
+HOBJS += ../src/utils/eloop.o
+HOBJS += $(SHA1OBJS)
+ifneq ($(CONFIG_TLS), openssl)
+HOBJS += ../src/crypto/md5.o
+endif
+endif
+
+ifdef CONFIG_RADIUS_SERVER
+CFLAGS += -DRADIUS_SERVER
+OBJS += ../src/radius/radius_server.o
+endif
+
+ifdef CONFIG_IPV6
+CFLAGS += -DCONFIG_IPV6
+endif
+
+ifdef CONFIG_DRIVER_RADIUS_ACL
+CFLAGS += -DCONFIG_DRIVER_RADIUS_ACL
+endif
+
+ifdef NEED_BASE64
+OBJS += ../src/utils/base64.o
+endif
+
+ifdef NEED_AP_MLME
+OBJS += ../src/ap/wmm.o
+OBJS += ../src/ap/ap_list.o
+OBJS += ../src/ap/ieee802_11.o
+OBJS += ../src/ap/hw_features.o
+OBJS += ../src/ap/dfs.o
+CFLAGS += -DNEED_AP_MLME
+endif
+ifdef CONFIG_IEEE80211N
+OBJS += ../src/ap/ieee802_11_ht.o
+endif
+
+ifdef CONFIG_IEEE80211AC
+OBJS += ../src/ap/ieee802_11_vht.o
+endif
+
+ifdef CONFIG_P2P_MANAGER
+CFLAGS += -DCONFIG_P2P_MANAGER
+OBJS += ../src/ap/p2p_hostapd.o
+endif
+
+ifdef CONFIG_HS20
+CFLAGS += -DCONFIG_HS20
+OBJS += ../src/ap/hs20.o
+CONFIG_INTERWORKING=y
+endif
+
+ifdef CONFIG_INTERWORKING
+CFLAGS += -DCONFIG_INTERWORKING
+OBJS += ../src/common/gas.o
+OBJS += ../src/ap/gas_serv.o
+endif
+
+ifdef CONFIG_PROXYARP
+CFLAGS += -DCONFIG_PROXYARP
+OBJS += ../src/ap/x_snoop.o
+OBJS += ../src/ap/dhcp_snoop.o
+ifdef CONFIG_IPV6
+OBJS += ../src/ap/ndisc_snoop.o
+endif
+endif
+
+OBJS += ../src/drivers/driver_common.o
+
+ifdef CONFIG_WPA_CLI_EDIT
+OBJS_c += ../src/utils/edit.o
+else
+OBJS_c += ../src/utils/edit_simple.o
+endif
+
+ifdef CONFIG_ACS
+CFLAGS += -DCONFIG_ACS
+OBJS += ../src/ap/acs.o
+LIBS += -lm
+endif
+
+ifdef CONFIG_NO_STDOUT_DEBUG
+CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
+endif
+
+ifdef CONFIG_DEBUG_LINUX_TRACING
+CFLAGS += -DCONFIG_DEBUG_LINUX_TRACING
+endif
+
+ifdef CONFIG_DEBUG_FILE
+CFLAGS += -DCONFIG_DEBUG_FILE
+endif
+
+ifdef CONFIG_SQLITE
+CFLAGS += -DCONFIG_SQLITE
+LIBS += -lsqlite3
+LIBS_h += -lsqlite3
+endif
+
+ifdef CONFIG_FST
+CFLAGS += -DCONFIG_FST
+OBJS += ../src/fst/fst.o
+OBJS += ../src/fst/fst_group.o
+OBJS += ../src/fst/fst_iface.o
+OBJS += ../src/fst/fst_session.o
+OBJS += ../src/fst/fst_ctrl_aux.o
+ifdef CONFIG_FST_TEST
+CFLAGS += -DCONFIG_FST_TEST
+endif
+ifndef CONFIG_NO_CTRL_IFACE
+OBJS += ../src/fst/fst_ctrl_iface.o
+endif
+endif
+
+ALL=hostapd hostapd_cli
+
+all: verify_config $(ALL)
+
+Q=@
+E=echo
+ifeq ($(V), 1)
+Q=
+E=true
+endif
+ifeq ($(QUIET), 1)
+Q=@
+E=true
+endif
+
+ifdef CONFIG_CODE_COVERAGE
+%.o: %.c
+	@$(E) "  CC " $<
+	$(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<)
+else
+%.o: %.c
+	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
+	@$(E) "  CC " $<
+endif
+
+verify_config:
+	@if [ ! -r .config ]; then \
+		echo 'Building hostapd requires a configuration file'; \
+		echo '(.config). See README for more instructions. You can'; \
+		echo 'run "cp defconfig .config" to create an example'; \
+		echo 'configuration.'; \
+		exit 1; \
+	fi
+
+$(DESTDIR)$(BINDIR)/%: %
+	install -D $(<) $(@)
+
+install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL))
+
+../src/drivers/build.hostapd:
+	@if [ -f ../src/drivers/build.wpa_supplicant ]; then \
+		$(MAKE) -C ../src/drivers clean; \
+	fi
+	@touch ../src/drivers/build.hostapd
+
+BCHECK=../src/drivers/build.hostapd
+
+hostapd: $(BCHECK) $(OBJS)
+	$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
+	@$(E) "  LD " $@
+
+ifdef CONFIG_WPA_TRACE
+OBJS_c += ../src/utils/trace.o
+endif
+hostapd_cli: $(OBJS_c)
+	$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
+	@$(E) "  LD " $@
+
+NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS)
+NOBJS += ../src/utils/common.o
+ifdef NEED_RC4
+ifdef CONFIG_INTERNAL_RC4
+ifndef CONFIG_NO_RC4
+NOBJS += ../src/crypto/rc4.o
+endif
+endif
+endif
+ifdef CONFIG_INTERNAL_MD5
+NOBJS += ../src/crypto/md5-internal.o
+endif
+NOBJS += ../src/crypto/crypto_openssl.o ../src/utils/os_$(CONFIG_OS).o
+NOBJS += ../src/utils/wpa_debug.o
+NOBJS += ../src/utils/wpabuf.o
+ifdef CONFIG_WPA_TRACE
+NOBJS += ../src/utils/trace.o
+LIBS_n += -lbfd
+endif
+ifdef TLS_FUNCS
+LIBS_n += -lcrypto
+endif
+
+HOBJS += hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/utils/wpabuf.o ../src/crypto/milenage.o
+HOBJS += ../src/crypto/aes-encblock.o
+ifdef CONFIG_INTERNAL_AES
+HOBJS += ../src/crypto/aes-internal.o
+HOBJS += ../src/crypto/aes-internal-enc.o
+endif
+
+nt_password_hash: $(NOBJS)
+	$(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
+	@$(E) "  LD " $@
+
+hlr_auc_gw: $(HOBJS)
+	$(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
+	@$(E) "  LD " $@
+
+lcov-html:
+	lcov -c -d .. > lcov.info
+	genhtml lcov.info --output-directory lcov-html
+
+clean:
+	$(MAKE) -C ../src clean
+	rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw
+	rm -f *.d *.gcno *.gcda *.gcov
+	rm -f lcov.info
+	rm -rf lcov-html
+
+-include $(OBJS:%.o=%.d)

+ 366 - 0
EVSE/GPL/hostapd-2.6/hostapd/README

@@ -0,0 +1,366 @@
+hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
+	  Authenticator and RADIUS authentication server
+================================================================
+
+Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+This program is licensed under the BSD license (the one with
+advertisement clause removed).
+
+If you are submitting changes to the project, please see CONTRIBUTIONS
+file for more instructions.
+
+
+
+License
+-------
+
+This software may be distributed, used, and modified under the terms of
+BSD license:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. Neither the name(s) of the above-listed copyright holder(s) nor the
+   names of its contributors may be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+Introduction
+============
+
+Originally, hostapd was an optional user space component for Host AP
+driver. It adds more features to the basic IEEE 802.11 management
+included in the kernel driver: using external RADIUS authentication
+server for MAC address based access control, IEEE 802.1X Authenticator
+and dynamic WEP keying, RADIUS accounting, WPA/WPA2 (IEEE 802.11i/RSN)
+Authenticator and dynamic TKIP/CCMP keying.
+
+The current version includes support for other drivers, an integrated
+EAP server (i.e., allow full authentication without requiring
+an external RADIUS authentication server), and RADIUS authentication
+server for EAP authentication.
+
+
+Requirements
+------------
+
+Current hardware/software requirements:
+- drivers:
+	Host AP driver for Prism2/2.5/3.
+	(http://hostap.epitest.fi/)
+	Please note that station firmware version needs to be 1.7.0 or newer
+	to work in WPA mode.
+
+	mac80211-based drivers that support AP mode (with driver=nl80211).
+	This includes drivers for Atheros (ath9k) and Broadcom (b43)
+	chipsets.
+
+	Any wired Ethernet driver for wired IEEE 802.1X authentication
+	(experimental code)
+
+	FreeBSD -current (with some kernel mods that have not yet been
+	committed when hostapd v0.3.0 was released)
+	BSD net80211 layer (e.g., Atheros driver)
+
+
+Build configuration
+-------------------
+
+In order to be able to build hostapd, you will need to create a build
+time configuration file, .config that selects which optional
+components are included. See defconfig file for example configuration
+and list of available options.
+
+
+
+IEEE 802.1X
+===========
+
+IEEE Std 802.1X-2001 is a standard for port-based network access
+control. In case of IEEE 802.11 networks, a "virtual port" is used
+between each associated station and the AP. IEEE 802.11 specifies
+minimal authentication mechanism for stations, whereas IEEE 802.1X
+introduces a extensible mechanism for authenticating and authorizing
+users.
+
+IEEE 802.1X uses elements called Supplicant, Authenticator, Port
+Access Entity, and Authentication Server. Supplicant is a component in
+a station and it performs the authentication with the Authentication
+Server. An access point includes an Authenticator that relays the packets
+between a Supplicant and an Authentication Server. In addition, it has a
+Port Access Entity (PAE) with Authenticator functionality for
+controlling the virtual port authorization, i.e., whether to accept
+packets from or to the station.
+
+IEEE 802.1X uses Extensible Authentication Protocol (EAP). The frames
+between a Supplicant and an Authenticator are sent using EAP over LAN
+(EAPOL) and the Authenticator relays these frames to the Authentication
+Server (and similarly, relays the messages from the Authentication
+Server to the Supplicant). The Authentication Server can be colocated with the
+Authenticator, in which case there is no need for additional protocol
+for EAP frame transmission. However, a more common configuration is to
+use an external Authentication Server and encapsulate EAP frame in the
+frames used by that server. RADIUS is suitable for this, but IEEE
+802.1X would also allow other mechanisms.
+
+Host AP driver includes PAE functionality in the kernel driver. It
+is a relatively simple mechanism for denying normal frames going to
+or coming from an unauthorized port. PAE allows IEEE 802.1X related
+frames to be passed between the Supplicant and the Authenticator even
+on an unauthorized port.
+
+User space daemon, hostapd, includes Authenticator functionality. It
+receives 802.1X (EAPOL) frames from the Supplicant using the wlan#ap
+device that is also used with IEEE 802.11 management frames. The
+frames to the Supplicant are sent using the same device.
+
+The normal configuration of the Authenticator would use an external
+Authentication Server. hostapd supports RADIUS encapsulation of EAP
+packets, so the Authentication Server should be a RADIUS server, like
+FreeRADIUS (http://www.freeradius.org/). The Authenticator in hostapd
+relays the frames between the Supplicant and the Authentication
+Server. It also controls the PAE functionality in the kernel driver by
+controlling virtual port authorization, i.e., station-AP
+connection, based on the IEEE 802.1X state.
+
+When a station would like to use the services of an access point, it
+will first perform IEEE 802.11 authentication. This is normally done
+with open systems authentication, so there is no security. After
+this, IEEE 802.11 association is performed. If IEEE 802.1X is
+configured to be used, the virtual port for the station is set in
+Unauthorized state and only IEEE 802.1X frames are accepted at this
+point. The Authenticator will then ask the Supplicant to authenticate
+with the Authentication Server. After this is completed successfully,
+the virtual port is set to Authorized state and frames from and to the
+station are accepted.
+
+Host AP configuration for IEEE 802.1X
+-------------------------------------
+
+The user space daemon has its own configuration file that can be used to
+define AP options. Distribution package contains an example
+configuration file (hostapd/hostapd.conf) that can be used as a basis
+for configuration. It includes examples of all supported configuration
+options and short description of each option. hostapd should be started
+with full path to the configuration file as the command line argument,
+e.g., './hostapd /etc/hostapd.conf'. If you have more that one wireless
+LAN card, you can use one hostapd process for multiple interfaces by
+giving a list of configuration files (one per interface) in the command
+line.
+
+hostapd includes a minimal co-located IEEE 802.1X server which can be
+used to test IEEE 802.1X authentication. However, it should not be
+used in normal use since it does not provide any security. This can be
+configured by setting ieee8021x and minimal_eap options in the
+configuration file.
+
+An external Authentication Server (RADIUS) is configured with
+auth_server_{addr,port,shared_secret} options. In addition,
+ieee8021x and own_ip_addr must be set for this mode. With such
+configuration, the co-located Authentication Server is not used and EAP
+frames will be relayed using EAPOL between the Supplicant and the
+Authenticator and RADIUS encapsulation between the Authenticator and
+the Authentication Server. Other than this, the functionality is similar
+to the case with the co-located Authentication Server.
+
+Authentication Server and Supplicant
+------------------------------------
+
+Any RADIUS server supporting EAP should be usable as an IEEE 802.1X
+Authentication Server with hostapd Authenticator. FreeRADIUS
+(http://www.freeradius.org/) has been successfully tested with hostapd
+Authenticator and both Xsupplicant (http://www.open1x.org) and Windows
+XP Supplicants. EAP/TLS was used with Xsupplicant and
+EAP/MD5-Challenge with Windows XP.
+
+http://www.missl.cs.umd.edu/wireless/eaptls/ has useful information
+about using EAP/TLS with FreeRADIUS and Xsupplicant (just replace
+Cisco access point with Host AP driver, hostapd daemon, and a Prism2
+card ;-). http://www.freeradius.org/doc/EAP-MD5.html has information
+about using EAP/MD5 with FreeRADIUS, including instructions for WinXP
+configuration. http://www.denobula.com/EAPTLS.pdf has a HOWTO on
+EAP/TLS use with WinXP Supplicant.
+
+Automatic WEP key configuration
+-------------------------------
+
+EAP/TLS generates a session key that can be used to send WEP keys from
+an AP to authenticated stations. The Authenticator in hostapd can be
+configured to automatically select a random default/broadcast key
+(shared by all authenticated stations) with wep_key_len_broadcast
+option (5 for 40-bit WEP or 13 for 104-bit WEP). In addition,
+wep_key_len_unicast option can be used to configure individual unicast
+keys for stations. This requires support for individual keys in the
+station driver.
+
+WEP keys can be automatically updated by configuring rekeying. This
+will improve security of the network since same WEP key will only be
+used for a limited period of time. wep_rekey_period option sets the
+interval for rekeying in seconds.
+
+
+WPA/WPA2
+========
+
+Features
+--------
+
+Supported WPA/IEEE 802.11i features:
+- WPA-PSK ("WPA-Personal")
+- WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise")
+- key management for CCMP, TKIP, WEP104, WEP40
+- RSN/WPA2 (IEEE 802.11i), including PMKSA caching and pre-authentication
+
+WPA
+---
+
+The original security mechanism of IEEE 802.11 standard was not
+designed to be strong and has proved to be insufficient for most
+networks that require some kind of security. Task group I (Security)
+of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked
+to address the flaws of the base standard and has in practice
+completed its work in May 2004. The IEEE 802.11i amendment to the IEEE
+802.11 standard was approved in June 2004 and this amendment is likely
+to be published in July 2004.
+
+Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the
+IEEE 802.11i work (draft 3.0) to define a subset of the security
+enhancements that can be implemented with existing wlan hardware. This
+is called Wi-Fi Protected Access<TM> (WPA). This has now become a
+mandatory component of interoperability testing and certification done
+by Wi-Fi Alliance. Wi-Fi provides information about WPA at its web
+site (http://www.wi-fi.org/OpenSection/protected_access.asp).
+
+IEEE 802.11 standard defined wired equivalent privacy (WEP) algorithm
+for protecting wireless networks. WEP uses RC4 with 40-bit keys,
+24-bit initialization vector (IV), and CRC32 to protect against packet
+forgery. All these choices have proven to be insufficient: key space is
+too small against current attacks, RC4 key scheduling is insufficient
+(beginning of the pseudorandom stream should be skipped), IV space is
+too small and IV reuse makes attacks easier, there is no replay
+protection, and non-keyed authentication does not protect against bit
+flipping packet data.
+
+WPA is an intermediate solution for the security issues. It uses
+Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP is a
+compromise on strong security and possibility to use existing
+hardware. It still uses RC4 for the encryption like WEP, but with
+per-packet RC4 keys. In addition, it implements replay protection,
+keyed packet authentication mechanism (Michael MIC).
+
+Keys can be managed using two different mechanisms. WPA can either use
+an external authentication server (e.g., RADIUS) and EAP just like
+IEEE 802.1X is using or pre-shared keys without need for additional
+servers. Wi-Fi calls these "WPA-Enterprise" and "WPA-Personal",
+respectively. Both mechanisms will generate a master session key for
+the Authenticator (AP) and Supplicant (client station).
+
+WPA implements a new key handshake (4-Way Handshake and Group Key
+Handshake) for generating and exchanging data encryption keys between
+the Authenticator and Supplicant. This handshake is also used to
+verify that both Authenticator and Supplicant know the master session
+key. These handshakes are identical regardless of the selected key
+management mechanism (only the method for generating master session
+key changes).
+
+
+IEEE 802.11i / WPA2
+-------------------
+
+The design for parts of IEEE 802.11i that were not included in WPA has
+finished (May 2004) and this amendment to IEEE 802.11 was approved in
+June 2004. Wi-Fi Alliance is using the final IEEE 802.11i as a new
+version of WPA called WPA2. This includes, e.g., support for more
+robust encryption algorithm (CCMP: AES in Counter mode with CBC-MAC)
+to replace TKIP and optimizations for handoff (reduced number of
+messages in initial key handshake, pre-authentication, and PMKSA caching).
+
+Some wireless LAN vendors are already providing support for CCMP in
+their WPA products. There is no "official" interoperability
+certification for CCMP and/or mixed modes using both TKIP and CCMP, so
+some interoperability issues can be expected even though many
+combinations seem to be working with equipment from different vendors.
+Testing for WPA2 is likely to start during the second half of 2004.
+
+hostapd configuration for WPA/WPA2
+----------------------------------
+
+TODO
+
+# Enable WPA. Setting this variable configures the AP to require WPA (either
+# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either
+# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.
+# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),
+# RADIUS authentication server must be configured, and WPA-EAP must be included
+# in wpa_key_mgmt.
+# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0)
+# and/or WPA2 (full IEEE 802.11i/RSN):
+# bit0 = WPA
+# bit1 = IEEE 802.11i/RSN (WPA2)
+#wpa=1
+
+# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
+# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
+# (8..63 characters) that will be converted to PSK. This conversion uses SSID
+# so the PSK changes when ASCII passphrase is used and the SSID is changed.
+#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
+#wpa_passphrase=secret passphrase
+
+# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
+# entries are separated with a space.
+#wpa_key_mgmt=WPA-PSK WPA-EAP
+
+# Set of accepted cipher suites (encryption algorithms) for pairwise keys
+# (unicast packets). This is a space separated list of algorithms:
+# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i]
+# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i]
+# Group cipher suite (encryption algorithm for broadcast and multicast frames)
+# is automatically selected based on this configuration. If only CCMP is
+# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise,
+# TKIP will be used as the group cipher.
+#wpa_pairwise=TKIP CCMP
+
+# Time interval for rekeying GTK (broadcast/multicast encryption keys) in
+# seconds.
+#wpa_group_rekey=600
+
+# Time interval for rekeying GMK (master key used internally to generate GTKs
+# (in seconds).
+#wpa_gmk_rekey=86400
+
+# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up
+# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN
+# authentication and key handshake before actually associating with a new AP.
+#rsn_preauth=1
+#
+# Space separated list of interfaces from which pre-authentication frames are
+# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all
+# interface that are used for connections to other APs. This could include
+# wired interfaces and WDS links. The normal wireless data interface towards
+# associated stations (e.g., wlan0) should not be added, since
+# pre-authentication is only used with APs other than the currently associated
+# one.
+#rsn_preauth_interfaces=eth0

+ 352 - 0
EVSE/GPL/hostapd-2.6/hostapd/README-WPS

@@ -0,0 +1,352 @@
+hostapd and Wi-Fi Protected Setup (WPS)
+=======================================
+
+This document describes how the WPS implementation in hostapd can be
+configured and how an external component on an AP (e.g., web UI) is
+used to enable enrollment of client devices.
+
+
+Introduction to WPS
+-------------------
+
+Wi-Fi Protected Setup (WPS) is a mechanism for easy configuration of a
+wireless network. It allows automated generation of random keys (WPA
+passphrase/PSK) and configuration of an access point and client
+devices. WPS includes number of methods for setting up connections
+with PIN method and push-button configuration (PBC) being the most
+commonly deployed options.
+
+While WPS can enable more home networks to use encryption in the
+wireless network, it should be noted that the use of the PIN and
+especially PBC mechanisms for authenticating the initial key setup is
+not very secure. As such, use of WPS may not be suitable for
+environments that require secure network access without chance for
+allowing outsiders to gain access during the setup phase.
+
+WPS uses following terms to describe the entities participating in the
+network setup:
+- access point: the WLAN access point
+- Registrar: a device that control a network and can authorize
+  addition of new devices); this may be either in the AP ("internal
+  Registrar") or in an external device, e.g., a laptop, ("external
+  Registrar")
+- Enrollee: a device that is being authorized to use the network
+
+It should also be noted that the AP and a client device may change
+roles (i.e., AP acts as an Enrollee and client device as a Registrar)
+when WPS is used to configure the access point.
+
+
+More information about WPS is available from Wi-Fi Alliance:
+http://www.wi-fi.org/wifi-protected-setup
+
+
+hostapd implementation
+----------------------
+
+hostapd includes an optional WPS component that can be used as an
+internal WPS Registrar to manage addition of new WPS enabled clients
+to the network. In addition, WPS Enrollee functionality in hostapd can
+be used to allow external WPS Registrars to configure the access
+point, e.g., for initial network setup. In addition, hostapd can proxy a
+WPS registration between a wireless Enrollee and an external Registrar
+(e.g., Microsoft Vista or Atheros JumpStart) with UPnP.
+
+
+hostapd configuration
+---------------------
+
+WPS is an optional component that needs to be enabled in hostapd build
+configuration (.config). Here is an example configuration that
+includes WPS support and uses nl80211 driver interface:
+
+CONFIG_DRIVER_NL80211=y
+CONFIG_WPS=y
+CONFIG_WPS_UPNP=y
+
+Following parameter can be used to enable support for NFC config method:
+
+CONFIG_WPS_NFC=y
+
+
+Following section shows an example runtime configuration
+(hostapd.conf) that enables WPS:
+
+# Configure the driver and network interface
+driver=nl80211
+interface=wlan0
+
+# WPA2-Personal configuration for the AP
+ssid=wps-test
+wpa=2
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+# Default WPA passphrase for legacy (non-WPS) clients
+wpa_passphrase=12345678
+# Enable random per-device PSK generation for WPS clients
+# Please note that the file has to exists for hostapd to start (i.e., create an
+# empty file as a starting point).
+wpa_psk_file=/etc/hostapd.psk
+
+# Enable control interface for PBC/PIN entry
+ctrl_interface=/var/run/hostapd
+
+# Enable internal EAP server for EAP-WSC (part of Wi-Fi Protected Setup)
+eap_server=1
+
+# WPS configuration (AP configured, do not allow external WPS Registrars)
+wps_state=2
+ap_setup_locked=1
+# If UUID is not configured, it will be generated based on local MAC address.
+uuid=87654321-9abc-def0-1234-56789abc0000
+wps_pin_requests=/var/run/hostapd.pin-req
+device_name=Wireless AP
+manufacturer=Company
+model_name=WAP
+model_number=123
+serial_number=12345
+device_type=6-0050F204-1
+os_version=01020300
+config_methods=label display push_button keypad
+
+# if external Registrars are allowed, UPnP support could be added:
+#upnp_iface=br0
+#friendly_name=WPS Access Point
+
+
+External operations
+-------------------
+
+WPS requires either a device PIN code (usually, 8-digit number) or a
+pushbutton event (for PBC) to allow a new WPS Enrollee to join the
+network. hostapd uses the control interface as an input channel for
+these events.
+
+The PIN value used in the commands must be processed by an UI to
+remove non-digit characters and potentially, to verify the checksum
+digit. "hostapd_cli wps_check_pin <PIN>" can be used to do such
+processing. It returns FAIL if the PIN is invalid, or FAIL-CHECKSUM if
+the checksum digit is incorrect, or the processed PIN (non-digit
+characters removed) if the PIN is valid.
+
+When a client device (WPS Enrollee) connects to hostapd (WPS
+Registrar) in order to start PIN mode negotiation for WPS, an
+identifier (Enrollee UUID) is sent. hostapd will need to be configured
+with a device password (PIN) for this Enrollee. This is an operation
+that requires user interaction (assuming there are no pre-configured
+PINs on the AP for a set of Enrollee).
+
+The PIN request with information about the device is appended to the
+wps_pin_requests file (/var/run/hostapd.pin-req in this example). In
+addition, hostapd control interface event is sent as a notification of
+a new device. The AP could use, e.g., a web UI for showing active
+Enrollees to the user and request a PIN for an Enrollee.
+
+The PIN request file has one line for every Enrollee that connected to
+the AP, but for which there was no PIN. Following information is
+provided for each Enrollee (separated with tabulators):
+- timestamp (seconds from 1970-01-01)
+- Enrollee UUID
+- MAC address
+- Device name
+- Manufacturer
+- Model Name
+- Model Number
+- Serial Number
+- Device category
+
+Example line in the /var/run/hostapd.pin-req file:
+1200188391	53b63a98-d29e-4457-a2ed-094d7e6a669c	Intel(R) Centrino(R)	Intel Corporation	Intel(R) Centrino(R)	-	-	1-0050F204-1
+
+Control interface data:
+WPS-PIN-NEEDED [UUID-E|MAC Address|Device Name|Manufacturer|Model Name|Model Number|Serial Number|Device Category]
+For example:
+<2>WPS-PIN-NEEDED [53b63a98-d29e-4457-a2ed-094d7e6a669c|02:12:34:56:78:9a|Device|Manuf|Model|Model Number|Serial Number|1-0050F204-1]
+
+When the user enters a PIN for a pending Enrollee, e.g., on the web
+UI), hostapd needs to be notified of the new PIN over the control
+interface. This can be done either by using the UNIX domain socket
+-based control interface directly (src/common/wpa_ctrl.c provides
+helper functions for using the interface) or by calling hostapd_cli.
+
+Example command to add a PIN (12345670) for an Enrollee:
+
+hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c 12345670
+
+If the UUID-E is not available (e.g., Enrollee waits for the Registrar
+to be selected before connecting), wildcard UUID may be used to allow
+the PIN to be used once with any UUID:
+
+hostapd_cli wps_pin any 12345670
+
+To reduce likelihood of PIN being used with other devices or of
+forgetting an active PIN available for potential attackers, expiration
+time in seconds can be set for the new PIN (value 0 indicates no
+expiration):
+
+hostapd_cli wps_pin any 12345670 300
+
+If the MAC address of the enrollee is known, it should be configured
+to allow the AP to advertise list of authorized enrollees:
+
+hostapd_cli wps_pin 53b63a98-d29e-4457-a2ed-094d7e6a669c \
+	12345670 300 00:11:22:33:44:55
+
+
+After this, the Enrollee can connect to the AP again and complete WPS
+negotiation. At that point, a new, random WPA PSK is generated for the
+client device and the client can then use that key to connect to the
+AP to access the network.
+
+
+If the AP includes a pushbutton, WPS PBC mode can be used. It is
+enabled by pushing a button on both the AP and the client at about the
+same time (2 minute window). hostapd needs to be notified about the AP
+button pushed event over the control interface, e.g., by calling
+hostapd_cli:
+
+hostapd_cli wps_pbc
+
+At this point, the client has two minutes to complete WPS negotiation
+which will generate a new WPA PSK in the same way as the PIN method
+described above.
+
+
+When an external Registrar is used, the AP can act as an Enrollee and
+use its AP PIN. A static AP PIN (e.g., one one a label in the AP
+device) can be configured in hostapd.conf (ap_pin parameter). A more
+secure option is to use hostapd_cli wps_ap_pin command to enable the
+AP PIN only based on user action (and even better security by using a
+random AP PIN for each session, i.e., by using "wps_ap_pin random"
+command with a timeout value). Following commands are available for
+managing the dynamic AP PIN operations:
+
+hostapd_cli wps_ap_pin disable
+- disable AP PIN (i.e., do not allow external Registrars to use it to
+  learn the current AP settings or to reconfigure the AP)
+
+hostapd_cli wps_ap_pin random [timeout]
+- generate a random AP PIN and enable it
+- if the optional timeout parameter is given, the AP PIN will be enabled
+  for the specified number of seconds
+
+hostapd_cli wps_ap_pin get
+- fetch the current AP PIN
+
+hostapd_cli wps_ap_pin set <PIN> [timeout]
+- set the AP PIN and enable it
+- if the optional timeout parameter is given, the AP PIN will be enabled
+  for the specified number of seconds
+
+hostapd_cli get_config
+- display the current configuration
+
+hostapd_cli wps_config <new SSID> <auth> <encr> <new key>
+examples:
+  hostapd_cli wps_config testing WPA2PSK CCMP 12345678
+  hostapd_cli wps_config "no security" OPEN NONE ""
+
+<auth> must be one of the following: OPEN WPAPSK WPA2PSK
+<encr> must be one of the following: NONE WEP TKIP CCMP
+
+
+Credential generation and configuration changes
+-----------------------------------------------
+
+By default, hostapd generates credentials for Enrollees and processing
+AP configuration updates internally. However, it is possible to
+control these operations from external programs, if desired.
+
+The internal credential generation can be disabled with
+skip_cred_build=1 option in the configuration. extra_cred option will
+then need to be used to provide pre-configured Credential attribute(s)
+for hostapd to use. The exact data from this binary file will be sent,
+i.e., it will have to include valid WPS attributes. extra_cred can
+also be used to add additional networks if the Registrar is used to
+configure credentials for multiple networks.
+
+Processing of received configuration updates can be disabled with
+wps_cred_processing=1 option. When this is used, an external program
+is responsible for creating hostapd configuration files and processing
+configuration updates based on messages received from hostapd over
+control interface. This will also include the initial configuration on
+first successful registration if the AP is initially set in
+unconfigured state.
+
+Following control interface messages are sent out for external programs:
+
+WPS-REG-SUCCESS <Enrollee MAC address <UUID-E>
+For example:
+<2>WPS-REG-SUCCESS 02:66:a0:ee:17:27 2b7093f1-d6fb-5108-adbb-bea66bb87333
+
+This can be used to trigger change from unconfigured to configured
+state (random configuration based on the first successful WPS
+registration). In addition, this can be used to update AP UI about the
+status of WPS registration progress.
+
+
+WPS-NEW-AP-SETTINGS <hexdump of AP Setup attributes>
+For example:
+<2>WPS-NEW-AP-SETTINGS 10260001011045000c6a6b6d2d7770732d74657374100300020020100f00020008102700403065346230343536633236366665306433396164313535346131663462663731323433376163666462376633393965353466316631623032306164343438623510200006024231cede15101e000844
+
+This can be used to update the externally stored AP configuration and
+then update hostapd configuration (followed by restarting of hostapd).
+
+
+WPS with NFC
+------------
+
+WPS can be used with NFC-based configuration method. An NFC tag
+containing a password token from the Enrollee can be used to
+authenticate the connection instead of the PIN. In addition, an NFC tag
+with a configuration token can be used to transfer AP settings without
+going through the WPS protocol.
+
+When the AP acts as an Enrollee, a local NFC tag with a password token
+can be used by touching the NFC interface of an external Registrar. The
+wps_nfc_token command is used to manage use of the NFC password token
+from the AP. "wps_nfc_token enable" enables the use of the AP's NFC
+password token (in place of AP PIN) and "wps_nfc_token disable" disables
+the NFC password token.
+
+The NFC password token that is either pre-configured in the
+configuration file (wps_nfc_dev_pw_id, wps_nfc_dh_pubkey,
+wps_nfc_dh_privkey, wps_nfc_dev_pw) or generated dynamically with
+"wps_nfc_token <WPS|NDEF>" command. The nfc_pw_token tool from
+wpa_supplicant can be used to generate NFC password tokens during
+manufacturing (each AP needs to have its own random keys).
+
+The "wps_nfc_config_token <WPS/NDEF>" command can be used to build an
+NFC configuration token. The output value from this command is a hexdump
+of the current AP configuration (WPS parameter requests this to include
+only the WPS attributes; NDEF parameter requests additional NDEF
+encapsulation to be included). This data needs to be written to an NFC
+tag with an external program. Once written, the NFC configuration token
+can be used to touch an NFC interface on a station to provision the
+credentials needed to access the network.
+
+When the NFC device on the AP reads an NFC tag with a MIME media type
+"application/vnd.wfa.wsc", the NDEF message payload (with or without
+NDEF encapsulation) can be delivered to hostapd using the
+following hostapd_cli command:
+
+wps_nfc_tag_read <hexdump of payload>
+
+If the NFC tag contains a password token, the token is added to the
+internal Registrar. This allows station Enrollee from which the password
+token was received to run through WPS protocol to provision the
+credential.
+
+"nfc_get_handover_sel <NDEF> <WPS>" command can be used to build the
+contents of a Handover Select Message for connection handover when this
+does not depend on the contents of the Handover Request Message. The
+first argument selects the format of the output data and the second
+argument selects which type of connection handover is requested (WPS =
+Wi-Fi handover as specified in WSC 2.0).
+
+"nfc_report_handover <INIT/RESP> WPS <carrier from handover request>
+<carrier from handover select>" is used to report completed NFC
+connection handover. The first parameter indicates whether the local
+device initiated or responded to the connection handover and the carrier
+records are the selected carrier from the handover request and select
+messages as a hexdump.

+ 201 - 0
EVSE/GPL/hostapd-2.6/hostapd/android.config

@@ -0,0 +1,201 @@
+# Example hostapd build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cass, these lines should use += in order not
+# to override previous values of the variables.
+
+# Driver interface for Host AP driver
+#CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for wired authenticator
+#CONFIG_DRIVER_WIRED=y
+
+# Driver interface for drivers using the nl80211 kernel interface
+#CONFIG_DRIVER_NL80211=y
+# driver_nl80211.c requires a rather new libnl (version 1.1) which may not be
+# shipped with your distribution yet. If that is the case, you need to build
+# newer libnl version and point the hostapd build to use it.
+#LIBNL=/usr/src/libnl
+#CFLAGS += -I$(LIBNL)/include
+#LIBS += -L$(LIBNL)/lib
+CONFIG_LIBNL20=y
+
+# QCA vendor extensions to nl80211
+CONFIG_DRIVER_NL80211_QCA=y
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+#LIBS_p += -L/usr/local/lib
+#LIBS_c += -L/usr/local/lib
+
+# Driver interface for no driver (e.g., RADIUS server only)
+#CONFIG_DRIVER_NONE=y
+
+# IEEE 802.11F/IAPP
+#CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+#CONFIG_RSN_PREAUTH=y
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+#CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+# This version is an experimental implementation based on IEEE 802.11w/D1.0
+# draft and is subject to change since the standard has not yet been finalized.
+# Driver support is also needed for IEEE 802.11w.
+CONFIG_IEEE80211W=y
+
+# Integrated EAP server
+#CONFIG_EAP=y
+
+# EAP-MD5 for the integrated EAP server
+#CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP server
+#CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP server
+#CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP server
+#CONFIG_EAP_PEAP=y
+
+# EAP-GTC for the integrated EAP server
+#CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP server
+#CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP server
+#CONFIG_EAP_SIM=y
+
+# EAP-AKA for the integrated EAP server
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' for the integrated EAP server
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# EAP-PAX for the integrated EAP server
+#CONFIG_EAP_PAX=y
+
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-SAKE for the integrated EAP server
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK for the integrated EAP server
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-FAST for the integrated EAP server
+# Note: Default OpenSSL package does not include support for all the
+# functionality needed for EAP-FAST. If EAP-FAST is enabled with OpenSSL,
+# the OpenSSL library must be patched (openssl-0.9.9-session-ticket.patch)
+# to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# Wi-Fi Protected Setup (WPS)
+CONFIG_WPS=y
+# Enable UPnP support for external WPS Registrars
+#CONFIG_WPS_UPNP=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# Trusted Network Connect (EAP-TNC)
+#CONFIG_EAP_TNC=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# RADIUS authentication server. This provides access to the integrated EAP
+# server from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
+
+# Build IPv6 support for RADIUS operations
+CONFIG_IPV6=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
+# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
+#CONFIG_DRIVER_RADIUS_ACL=y
+
+# IEEE 802.11n (High Throughput) support
+CONFIG_IEEE80211N=y
+
+# Remove debugging code that is printing out debug messages to stdout.
+# This can be used to reduce the size of the hostapd considerably if debugging
+# code is not needed.
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Add support for writing debug log to Android logcat instead of standard output
+CONFIG_ANDROID_LOG=y
+
+# Remove support for RADIUS accounting
+#CONFIG_NO_ACCOUNTING=y
+
+# Remove support for RADIUS
+CONFIG_NO_RADIUS=y
+
+# Remove support for VLANs
+#CONFIG_NO_VLAN=y
+
+# Remove support for dumping internal state through control interface commands
+# This can be used to reduce binary size at the cost of disabling a debugging
+# option.
+#CONFIG_NO_DUMP_STATE=y
+
+# Select wrapper for operatins system and C library specific functions
+# unix = UNIX/POSIX like systems (default)
+# win32 = Windows systems
+# none = Empty template
+CONFIG_OS=unix
+
+# Enable tracing code for developer debugging
+# This tracks use of memory allocations and other registrations and reports
+# incorrect use with a backtrace of call (or allocation) location.
+#CONFIG_WPA_TRACE=y
+# For BSD, comment out these.
+#LIBS += -lexecinfo
+#LIBS_p += -lexecinfo
+#LIBS_c += -lexecinfo
+
+# Use libbfd to get more details for developer debugging
+# This enables use of libbfd to get more detailed symbols for the backtraces
+# generated by CONFIG_WPA_TRACE=y.
+#CONFIG_WPA_TRACE_BFD=y
+# For BSD, comment out these.
+#LIBS += -lbfd -liberty -lz
+#LIBS_p += -lbfd -liberty -lz
+#LIBS_c += -lbfd -liberty -lz
+
+# Should we use poll instead of select? Select is used by default.
+#CONFIG_ELOOP_POLL=y
+
+# Should we use epoll instead of select? Select is used by default.
+#CONFIG_ELOOP_EPOLL=y
+
+# Enable AP
+CONFIG_AP=y
+
+# Enable Fast Session Transfer (FST)
+#CONFIG_FST=y
+
+# Multiband Operation support
+# These extentions facilitate efficient use of multiple frequency bands
+# available to the AP and the devices that may associate with it.
+#CONFIG_MBO=y

+ 3618 - 0
EVSE/GPL/hostapd-2.6/hostapd/config_file.c

@@ -0,0 +1,3618 @@
+/*
+ * hostapd / Configuration file parser
+ * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#ifndef CONFIG_NATIVE_WINDOWS
+#include <grp.h>
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+#include "utils/common.h"
+#include "utils/uuid.h"
+#include "common/ieee802_11_defs.h"
+#include "drivers/driver.h"
+#include "eap_server/eap.h"
+#include "radius/radius_client.h"
+#include "ap/wpa_auth.h"
+#include "ap/ap_config.h"
+#include "config_file.h"
+
+
+#ifndef CONFIG_NO_RADIUS
+#ifdef EAP_SERVER
+static struct hostapd_radius_attr *
+hostapd_parse_radius_attr(const char *value);
+#endif /* EAP_SERVER */
+#endif /* CONFIG_NO_RADIUS */
+
+
+#ifndef CONFIG_NO_VLAN
+static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
+					 const char *fname)
+{
+	FILE *f;
+	char buf[128], *pos, *pos2;
+	int line = 0, vlan_id;
+	struct hostapd_vlan *vlan;
+
+	f = fopen(fname, "r");
+	if (!f) {
+		wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", fname);
+		return -1;
+	}
+
+	while (fgets(buf, sizeof(buf), f)) {
+		line++;
+
+		if (buf[0] == '#')
+			continue;
+		pos = buf;
+		while (*pos != '\0') {
+			if (*pos == '\n') {
+				*pos = '\0';
+				break;
+			}
+			pos++;
+		}
+		if (buf[0] == '\0')
+			continue;
+
+		if (buf[0] == '*') {
+			vlan_id = VLAN_ID_WILDCARD;
+			pos = buf + 1;
+		} else {
+			vlan_id = strtol(buf, &pos, 10);
+			if (buf == pos || vlan_id < 1 ||
+			    vlan_id > MAX_VLAN_ID) {
+				wpa_printf(MSG_ERROR, "Invalid VLAN ID at "
+					   "line %d in '%s'", line, fname);
+				fclose(f);
+				return -1;
+			}
+		}
+
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+		pos2 = pos;
+		while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0')
+			pos2++;
+		*pos2 = '\0';
+		if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) {
+			wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d "
+				   "in '%s'", line, fname);
+			fclose(f);
+			return -1;
+		}
+
+		vlan = os_zalloc(sizeof(*vlan));
+		if (vlan == NULL) {
+			wpa_printf(MSG_ERROR, "Out of memory while reading "
+				   "VLAN interfaces from '%s'", fname);
+			fclose(f);
+			return -1;
+		}
+
+		vlan->vlan_id = vlan_id;
+		vlan->vlan_desc.untagged = vlan_id;
+		vlan->vlan_desc.notempty = !!vlan_id;
+		os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
+		vlan->next = bss->vlan;
+		bss->vlan = vlan;
+	}
+
+	fclose(f);
+
+	return 0;
+}
+#endif /* CONFIG_NO_VLAN */
+
+
+static int hostapd_acl_comp(const void *a, const void *b)
+{
+	const struct mac_acl_entry *aa = a;
+	const struct mac_acl_entry *bb = b;
+	return os_memcmp(aa->addr, bb->addr, sizeof(macaddr));
+}
+
+
+static int hostapd_config_read_maclist(const char *fname,
+				       struct mac_acl_entry **acl, int *num)
+{
+	FILE *f;
+	char buf[128], *pos;
+	int line = 0;
+	u8 addr[ETH_ALEN];
+	struct mac_acl_entry *newacl;
+	int vlan_id;
+
+	if (!fname)
+		return 0;
+
+	f = fopen(fname, "r");
+	if (!f) {
+		wpa_printf(MSG_ERROR, "MAC list file '%s' not found.", fname);
+		return -1;
+	}
+
+	while (fgets(buf, sizeof(buf), f)) {
+		int i, rem = 0;
+
+		line++;
+
+		if (buf[0] == '#')
+			continue;
+		pos = buf;
+		while (*pos != '\0') {
+			if (*pos == '\n') {
+				*pos = '\0';
+				break;
+			}
+			pos++;
+		}
+		if (buf[0] == '\0')
+			continue;
+		pos = buf;
+		if (buf[0] == '-') {
+			rem = 1;
+			pos++;
+		}
+
+		if (hwaddr_aton(pos, addr)) {
+			wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at "
+				   "line %d in '%s'", pos, line, fname);
+			fclose(f);
+			return -1;
+		}
+
+		if (rem) {
+			i = 0;
+			while (i < *num) {
+				if (os_memcmp((*acl)[i].addr, addr, ETH_ALEN) ==
+				    0) {
+					os_remove_in_array(*acl, *num,
+							   sizeof(**acl), i);
+					(*num)--;
+				} else
+					i++;
+			}
+			continue;
+		}
+		vlan_id = 0;
+		pos = buf;
+		while (*pos != '\0' && *pos != ' ' && *pos != '\t')
+			pos++;
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+		if (*pos != '\0')
+			vlan_id = atoi(pos);
+
+		newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl));
+		if (newacl == NULL) {
+			wpa_printf(MSG_ERROR, "MAC list reallocation failed");
+			fclose(f);
+			return -1;
+		}
+
+		*acl = newacl;
+		os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
+		os_memset(&(*acl)[*num].vlan_id, 0,
+			  sizeof((*acl)[*num].vlan_id));
+		(*acl)[*num].vlan_id.untagged = vlan_id;
+		(*acl)[*num].vlan_id.notempty = !!vlan_id;
+		(*num)++;
+	}
+
+	fclose(f);
+
+	qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
+
+	return 0;
+}
+
+
+#ifdef EAP_SERVER
+static int hostapd_config_read_eap_user(const char *fname,
+					struct hostapd_bss_config *conf)
+{
+	FILE *f;
+	char buf[512], *pos, *start, *pos2;
+	int line = 0, ret = 0, num_methods;
+	struct hostapd_eap_user *user = NULL, *tail = NULL, *new_user = NULL;
+
+	if (!fname)
+		return 0;
+
+	if (os_strncmp(fname, "sqlite:", 7) == 0) {
+#ifdef CONFIG_SQLITE
+		os_free(conf->eap_user_sqlite);
+		conf->eap_user_sqlite = os_strdup(fname + 7);
+		return 0;
+#else /* CONFIG_SQLITE */
+		wpa_printf(MSG_ERROR,
+			   "EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build.");
+		return -1;
+#endif /* CONFIG_SQLITE */
+	}
+
+	f = fopen(fname, "r");
+	if (!f) {
+		wpa_printf(MSG_ERROR, "EAP user file '%s' not found.", fname);
+		return -1;
+	}
+
+	/* Lines: "user" METHOD,METHOD2 "password" (password optional) */
+	while (fgets(buf, sizeof(buf), f)) {
+		line++;
+
+		if (buf[0] == '#')
+			continue;
+		pos = buf;
+		while (*pos != '\0') {
+			if (*pos == '\n') {
+				*pos = '\0';
+				break;
+			}
+			pos++;
+		}
+		if (buf[0] == '\0')
+			continue;
+
+#ifndef CONFIG_NO_RADIUS
+		if (user && os_strncmp(buf, "radius_accept_attr=", 19) == 0) {
+			struct hostapd_radius_attr *attr, *a;
+			attr = hostapd_parse_radius_attr(buf + 19);
+			if (attr == NULL) {
+				wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s",
+					   buf + 19);
+				user = NULL; /* already in the BSS list */
+				goto failed;
+			}
+			if (user->accept_attr == NULL) {
+				user->accept_attr = attr;
+			} else {
+				a = user->accept_attr;
+				while (a->next)
+					a = a->next;
+				a->next = attr;
+			}
+			continue;
+		}
+#endif /* CONFIG_NO_RADIUS */
+
+		user = NULL;
+
+		if (buf[0] != '"' && buf[0] != '*') {
+			wpa_printf(MSG_ERROR, "Invalid EAP identity (no \" in "
+				   "start) on line %d in '%s'", line, fname);
+			goto failed;
+		}
+
+		user = os_zalloc(sizeof(*user));
+		if (user == NULL) {
+			wpa_printf(MSG_ERROR, "EAP user allocation failed");
+			goto failed;
+		}
+		user->force_version = -1;
+
+		if (buf[0] == '*') {
+			pos = buf;
+		} else {
+			pos = buf + 1;
+			start = pos;
+			while (*pos != '"' && *pos != '\0')
+				pos++;
+			if (*pos == '\0') {
+				wpa_printf(MSG_ERROR, "Invalid EAP identity "
+					   "(no \" in end) on line %d in '%s'",
+					   line, fname);
+				goto failed;
+			}
+
+			user->identity = os_malloc(pos - start);
+			if (user->identity == NULL) {
+				wpa_printf(MSG_ERROR, "Failed to allocate "
+					   "memory for EAP identity");
+				goto failed;
+			}
+			os_memcpy(user->identity, start, pos - start);
+			user->identity_len = pos - start;
+
+			if (pos[0] == '"' && pos[1] == '*') {
+				user->wildcard_prefix = 1;
+				pos++;
+			}
+		}
+		pos++;
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+
+		if (*pos == '\0') {
+			wpa_printf(MSG_ERROR, "No EAP method on line %d in "
+				   "'%s'", line, fname);
+			goto failed;
+		}
+
+		start = pos;
+		while (*pos != ' ' && *pos != '\t' && *pos != '\0')
+			pos++;
+		if (*pos == '\0') {
+			pos = NULL;
+		} else {
+			*pos = '\0';
+			pos++;
+		}
+		num_methods = 0;
+		while (*start) {
+			char *pos3 = os_strchr(start, ',');
+			if (pos3) {
+				*pos3++ = '\0';
+			}
+			user->methods[num_methods].method =
+				eap_server_get_type(
+					start,
+					&user->methods[num_methods].vendor);
+			if (user->methods[num_methods].vendor ==
+			    EAP_VENDOR_IETF &&
+			    user->methods[num_methods].method == EAP_TYPE_NONE)
+			{
+				if (os_strcmp(start, "TTLS-PAP") == 0) {
+					user->ttls_auth |= EAP_TTLS_AUTH_PAP;
+					goto skip_eap;
+				}
+				if (os_strcmp(start, "TTLS-CHAP") == 0) {
+					user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
+					goto skip_eap;
+				}
+				if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
+					user->ttls_auth |=
+						EAP_TTLS_AUTH_MSCHAP;
+					goto skip_eap;
+				}
+				if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
+					user->ttls_auth |=
+						EAP_TTLS_AUTH_MSCHAPV2;
+					goto skip_eap;
+				}
+				if (os_strcmp(start, "MACACL") == 0) {
+					user->macacl = 1;
+					goto skip_eap;
+				}
+				wpa_printf(MSG_ERROR, "Unsupported EAP type "
+					   "'%s' on line %d in '%s'",
+					   start, line, fname);
+				goto failed;
+			}
+
+			num_methods++;
+			if (num_methods >= EAP_MAX_METHODS)
+				break;
+		skip_eap:
+			if (pos3 == NULL)
+				break;
+			start = pos3;
+		}
+		if (num_methods == 0 && user->ttls_auth == 0 && !user->macacl) {
+			wpa_printf(MSG_ERROR, "No EAP types configured on "
+				   "line %d in '%s'", line, fname);
+			goto failed;
+		}
+
+		if (pos == NULL)
+			goto done;
+
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+		if (*pos == '\0')
+			goto done;
+
+		if (os_strncmp(pos, "[ver=0]", 7) == 0) {
+			user->force_version = 0;
+			goto done;
+		}
+
+		if (os_strncmp(pos, "[ver=1]", 7) == 0) {
+			user->force_version = 1;
+			goto done;
+		}
+
+		if (os_strncmp(pos, "[2]", 3) == 0) {
+			user->phase2 = 1;
+			goto done;
+		}
+
+		if (*pos == '"') {
+			pos++;
+			start = pos;
+			while (*pos != '"' && *pos != '\0')
+				pos++;
+			if (*pos == '\0') {
+				wpa_printf(MSG_ERROR, "Invalid EAP password "
+					   "(no \" in end) on line %d in '%s'",
+					   line, fname);
+				goto failed;
+			}
+
+			user->password = os_malloc(pos - start);
+			if (user->password == NULL) {
+				wpa_printf(MSG_ERROR, "Failed to allocate "
+					   "memory for EAP password");
+				goto failed;
+			}
+			os_memcpy(user->password, start, pos - start);
+			user->password_len = pos - start;
+
+			pos++;
+		} else if (os_strncmp(pos, "hash:", 5) == 0) {
+			pos += 5;
+			pos2 = pos;
+			while (*pos2 != '\0' && *pos2 != ' ' &&
+			       *pos2 != '\t' && *pos2 != '#')
+				pos2++;
+			if (pos2 - pos != 32) {
+				wpa_printf(MSG_ERROR, "Invalid password hash "
+					   "on line %d in '%s'", line, fname);
+				goto failed;
+			}
+			user->password = os_malloc(16);
+			if (user->password == NULL) {
+				wpa_printf(MSG_ERROR, "Failed to allocate "
+					   "memory for EAP password hash");
+				goto failed;
+			}
+			if (hexstr2bin(pos, user->password, 16) < 0) {
+				wpa_printf(MSG_ERROR, "Invalid hash password "
+					   "on line %d in '%s'", line, fname);
+				goto failed;
+			}
+			user->password_len = 16;
+			user->password_hash = 1;
+			pos = pos2;
+		} else {
+			pos2 = pos;
+			while (*pos2 != '\0' && *pos2 != ' ' &&
+			       *pos2 != '\t' && *pos2 != '#')
+				pos2++;
+			if ((pos2 - pos) & 1) {
+				wpa_printf(MSG_ERROR, "Invalid hex password "
+					   "on line %d in '%s'", line, fname);
+				goto failed;
+			}
+			user->password = os_malloc((pos2 - pos) / 2);
+			if (user->password == NULL) {
+				wpa_printf(MSG_ERROR, "Failed to allocate "
+					   "memory for EAP password");
+				goto failed;
+			}
+			if (hexstr2bin(pos, user->password,
+				       (pos2 - pos) / 2) < 0) {
+				wpa_printf(MSG_ERROR, "Invalid hex password "
+					   "on line %d in '%s'", line, fname);
+				goto failed;
+			}
+			user->password_len = (pos2 - pos) / 2;
+			pos = pos2;
+		}
+
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+		if (os_strncmp(pos, "[2]", 3) == 0) {
+			user->phase2 = 1;
+		}
+
+	done:
+		if (tail == NULL) {
+			tail = new_user = user;
+		} else {
+			tail->next = user;
+			tail = user;
+		}
+		continue;
+
+	failed:
+		if (user)
+			hostapd_config_free_eap_user(user);
+		ret = -1;
+		break;
+	}
+
+	fclose(f);
+
+	if (ret == 0) {
+		user = conf->eap_user;
+		while (user) {
+			struct hostapd_eap_user *prev;
+
+			prev = user;
+			user = user->next;
+			hostapd_config_free_eap_user(prev);
+		}
+		conf->eap_user = new_user;
+	}
+
+	return ret;
+}
+#endif /* EAP_SERVER */
+
+
+#ifndef CONFIG_NO_RADIUS
+static int
+hostapd_config_read_radius_addr(struct hostapd_radius_server **server,
+				int *num_server, const char *val, int def_port,
+				struct hostapd_radius_server **curr_serv)
+{
+	struct hostapd_radius_server *nserv;
+	int ret;
+	static int server_index = 1;
+
+	nserv = os_realloc_array(*server, *num_server + 1, sizeof(*nserv));
+	if (nserv == NULL)
+		return -1;
+
+	*server = nserv;
+	nserv = &nserv[*num_server];
+	(*num_server)++;
+	(*curr_serv) = nserv;
+
+	os_memset(nserv, 0, sizeof(*nserv));
+	nserv->port = def_port;
+	ret = hostapd_parse_ip_addr(val, &nserv->addr);
+	nserv->index = server_index++;
+
+	return ret;
+}
+
+
+static struct hostapd_radius_attr *
+hostapd_parse_radius_attr(const char *value)
+{
+	const char *pos;
+	char syntax;
+	struct hostapd_radius_attr *attr;
+	size_t len;
+
+	attr = os_zalloc(sizeof(*attr));
+	if (attr == NULL)
+		return NULL;
+
+	attr->type = atoi(value);
+
+	pos = os_strchr(value, ':');
+	if (pos == NULL) {
+		attr->val = wpabuf_alloc(1);
+		if (attr->val == NULL) {
+			os_free(attr);
+			return NULL;
+		}
+		wpabuf_put_u8(attr->val, 0);
+		return attr;
+	}
+
+	pos++;
+	if (pos[0] == '\0' || pos[1] != ':') {
+		os_free(attr);
+		return NULL;
+	}
+	syntax = *pos++;
+	pos++;
+
+	switch (syntax) {
+	case 's':
+		attr->val = wpabuf_alloc_copy(pos, os_strlen(pos));
+		break;
+	case 'x':
+		len = os_strlen(pos);
+		if (len & 1)
+			break;
+		len /= 2;
+		attr->val = wpabuf_alloc(len);
+		if (attr->val == NULL)
+			break;
+		if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) {
+			wpabuf_free(attr->val);
+			os_free(attr);
+			return NULL;
+		}
+		break;
+	case 'd':
+		attr->val = wpabuf_alloc(4);
+		if (attr->val)
+			wpabuf_put_be32(attr->val, atoi(pos));
+		break;
+	default:
+		os_free(attr);
+		return NULL;
+	}
+
+	if (attr->val == NULL) {
+		os_free(attr);
+		return NULL;
+	}
+
+	return attr;
+}
+
+
+static int hostapd_parse_das_client(struct hostapd_bss_config *bss, char *val)
+{
+	char *secret;
+
+	secret = os_strchr(val, ' ');
+	if (secret == NULL)
+		return -1;
+
+	*secret++ = '\0';
+
+	if (hostapd_parse_ip_addr(val, &bss->radius_das_client_addr))
+		return -1;
+
+	os_free(bss->radius_das_shared_secret);
+	bss->radius_das_shared_secret = (u8 *) os_strdup(secret);
+	if (bss->radius_das_shared_secret == NULL)
+		return -1;
+	bss->radius_das_shared_secret_len = os_strlen(secret);
+
+	return 0;
+}
+#endif /* CONFIG_NO_RADIUS */
+
+
+static int hostapd_config_parse_key_mgmt(int line, const char *value)
+{
+	int val = 0, last;
+	char *start, *end, *buf;
+
+	buf = os_strdup(value);
+	if (buf == NULL)
+		return -1;
+	start = buf;
+
+	while (*start != '\0') {
+		while (*start == ' ' || *start == '\t')
+			start++;
+		if (*start == '\0')
+			break;
+		end = start;
+		while (*end != ' ' && *end != '\t' && *end != '\0')
+			end++;
+		last = *end == '\0';
+		*end = '\0';
+		if (os_strcmp(start, "WPA-PSK") == 0)
+			val |= WPA_KEY_MGMT_PSK;
+		else if (os_strcmp(start, "WPA-EAP") == 0)
+			val |= WPA_KEY_MGMT_IEEE8021X;
+#ifdef CONFIG_IEEE80211R
+		else if (os_strcmp(start, "FT-PSK") == 0)
+			val |= WPA_KEY_MGMT_FT_PSK;
+		else if (os_strcmp(start, "FT-EAP") == 0)
+			val |= WPA_KEY_MGMT_FT_IEEE8021X;
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211W
+		else if (os_strcmp(start, "WPA-PSK-SHA256") == 0)
+			val |= WPA_KEY_MGMT_PSK_SHA256;
+		else if (os_strcmp(start, "WPA-EAP-SHA256") == 0)
+			val |= WPA_KEY_MGMT_IEEE8021X_SHA256;
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_SAE
+		else if (os_strcmp(start, "SAE") == 0)
+			val |= WPA_KEY_MGMT_SAE;
+		else if (os_strcmp(start, "FT-SAE") == 0)
+			val |= WPA_KEY_MGMT_FT_SAE;
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_SUITEB
+		else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0)
+			val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B;
+#endif /* CONFIG_SUITEB */
+#ifdef CONFIG_SUITEB192
+		else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
+			val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
+#endif /* CONFIG_SUITEB192 */
+		else {
+			wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
+				   line, start);
+			os_free(buf);
+			return -1;
+		}
+
+		if (last)
+			break;
+		start = end + 1;
+	}
+
+	os_free(buf);
+	if (val == 0) {
+		wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values "
+			   "configured.", line);
+		return -1;
+	}
+
+	return val;
+}
+
+
+static int hostapd_config_parse_cipher(int line, const char *value)
+{
+	int val = wpa_parse_cipher(value);
+	if (val < 0) {
+		wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.",
+			   line, value);
+		return -1;
+	}
+	if (val == 0) {
+		wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.",
+			   line);
+		return -1;
+	}
+	return val;
+}
+
+
+static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
+				   char *val)
+{
+	size_t len = os_strlen(val);
+
+	if (keyidx < 0 || keyidx > 3 || wep->key[keyidx] != NULL)
+		return -1;
+
+	if (val[0] == '"') {
+		if (len < 2 || val[len - 1] != '"')
+			return -1;
+		len -= 2;
+		wep->key[keyidx] = os_malloc(len);
+		if (wep->key[keyidx] == NULL)
+			return -1;
+		os_memcpy(wep->key[keyidx], val + 1, len);
+		wep->len[keyidx] = len;
+	} else {
+		if (len & 1)
+			return -1;
+		len /= 2;
+		wep->key[keyidx] = os_malloc(len);
+		if (wep->key[keyidx] == NULL)
+			return -1;
+		wep->len[keyidx] = len;
+		if (hexstr2bin(val, wep->key[keyidx], len) < 0)
+			return -1;
+	}
+
+	wep->keys_set++;
+
+	return 0;
+}
+
+
+static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
+{
+	char *pos;
+
+	/* for backwards compatibility, translate ' ' in conf str to ',' */
+	pos = val;
+	while (pos) {
+		pos = os_strchr(pos, ' ');
+		if (pos)
+			*pos++ = ',';
+	}
+	if (freq_range_list_parse(&conf->acs_ch_list, val))
+		return -1;
+
+	return 0;
+}
+
+
+static int hostapd_parse_intlist(int **int_list, char *val)
+{
+	int *list;
+	int count;
+	char *pos, *end;
+
+	os_free(*int_list);
+	*int_list = NULL;
+
+	pos = val;
+	count = 0;
+	while (*pos != '\0') {
+		if (*pos == ' ')
+			count++;
+		pos++;
+	}
+
+	list = os_malloc(sizeof(int) * (count + 2));
+	if (list == NULL)
+		return -1;
+	pos = val;
+	count = 0;
+	while (*pos != '\0') {
+		end = os_strchr(pos, ' ');
+		if (end)
+			*end = '\0';
+
+		list[count++] = atoi(pos);
+		if (!end)
+			break;
+		pos = end + 1;
+	}
+	list[count] = -1;
+
+	*int_list = list;
+	return 0;
+}
+
+
+static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
+{
+	struct hostapd_bss_config **all, *bss;
+
+	if (*ifname == '\0')
+		return -1;
+
+	all = os_realloc_array(conf->bss, conf->num_bss + 1,
+			       sizeof(struct hostapd_bss_config *));
+	if (all == NULL) {
+		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
+			   "multi-BSS entry");
+		return -1;
+	}
+	conf->bss = all;
+
+	bss = os_zalloc(sizeof(*bss));
+	if (bss == NULL)
+		return -1;
+	bss->radius = os_zalloc(sizeof(*bss->radius));
+	if (bss->radius == NULL) {
+		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
+			   "multi-BSS RADIUS data");
+		os_free(bss);
+		return -1;
+	}
+
+	conf->bss[conf->num_bss++] = bss;
+	conf->last_bss = bss;
+
+	hostapd_config_defaults_bss(bss);
+	os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
+	os_memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1);
+
+	return 0;
+}
+
+
+/* convert floats with one decimal place to value*10 int, i.e.,
+ * "1.5" will return 15 */
+static int hostapd_config_read_int10(const char *value)
+{
+	int i, d;
+	char *pos;
+
+	i = atoi(value);
+	pos = os_strchr(value, '.');
+	d = 0;
+	if (pos) {
+		pos++;
+		if (*pos >= '0' && *pos <= '9')
+			d = *pos - '0';
+	}
+
+	return i * 10 + d;
+}
+
+
+static int valid_cw(int cw)
+{
+	return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
+		cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 ||
+		cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 ||
+		cw == 32767);
+}
+
+
+enum {
+	IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */
+	IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */
+	IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */
+	IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */
+};
+
+static int hostapd_config_tx_queue(struct hostapd_config *conf,
+				   const char *name, const char *val)
+{
+	int num;
+	const char *pos;
+	struct hostapd_tx_queue_params *queue;
+
+	/* skip 'tx_queue_' prefix */
+	pos = name + 9;
+	if (os_strncmp(pos, "data", 4) == 0 &&
+	    pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') {
+		num = pos[4] - '0';
+		pos += 6;
+	} else if (os_strncmp(pos, "after_beacon_", 13) == 0 ||
+		   os_strncmp(pos, "beacon_", 7) == 0) {
+		wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
+		return 0;
+	} else {
+		wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos);
+		return -1;
+	}
+
+	if (num >= NUM_TX_QUEUES) {
+		/* for backwards compatibility, do not trigger failure */
+		wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name);
+		return 0;
+	}
+
+	queue = &conf->tx_queue[num];
+
+	if (os_strcmp(pos, "aifs") == 0) {
+		queue->aifs = atoi(val);
+		if (queue->aifs < 0 || queue->aifs > 255) {
+			wpa_printf(MSG_ERROR, "Invalid AIFS value %d",
+				   queue->aifs);
+			return -1;
+		}
+	} else if (os_strcmp(pos, "cwmin") == 0) {
+		queue->cwmin = atoi(val);
+		if (!valid_cw(queue->cwmin)) {
+			wpa_printf(MSG_ERROR, "Invalid cwMin value %d",
+				   queue->cwmin);
+			return -1;
+		}
+	} else if (os_strcmp(pos, "cwmax") == 0) {
+		queue->cwmax = atoi(val);
+		if (!valid_cw(queue->cwmax)) {
+			wpa_printf(MSG_ERROR, "Invalid cwMax value %d",
+				   queue->cwmax);
+			return -1;
+		}
+	} else if (os_strcmp(pos, "burst") == 0) {
+		queue->burst = hostapd_config_read_int10(val);
+	} else {
+		wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+#ifdef CONFIG_IEEE80211R
+static int add_r0kh(struct hostapd_bss_config *bss, char *value)
+{
+	struct ft_remote_r0kh *r0kh;
+	char *pos, *next;
+
+	r0kh = os_zalloc(sizeof(*r0kh));
+	if (r0kh == NULL)
+		return -1;
+
+	/* 02:01:02:03:04:05 a.example.com 000102030405060708090a0b0c0d0e0f */
+	pos = value;
+	next = os_strchr(pos, ' ');
+	if (next)
+		*next++ = '\0';
+	if (next == NULL || hwaddr_aton(pos, r0kh->addr)) {
+		wpa_printf(MSG_ERROR, "Invalid R0KH MAC address: '%s'", pos);
+		os_free(r0kh);
+		return -1;
+	}
+
+	pos = next;
+	next = os_strchr(pos, ' ');
+	if (next)
+		*next++ = '\0';
+	if (next == NULL || next - pos > FT_R0KH_ID_MAX_LEN) {
+		wpa_printf(MSG_ERROR, "Invalid R0KH-ID: '%s'", pos);
+		os_free(r0kh);
+		return -1;
+	}
+	r0kh->id_len = next - pos - 1;
+	os_memcpy(r0kh->id, pos, r0kh->id_len);
+
+	pos = next;
+	if (hexstr2bin(pos, r0kh->key, sizeof(r0kh->key))) {
+		wpa_printf(MSG_ERROR, "Invalid R0KH key: '%s'", pos);
+		os_free(r0kh);
+		return -1;
+	}
+
+	r0kh->next = bss->r0kh_list;
+	bss->r0kh_list = r0kh;
+
+	return 0;
+}
+
+
+static int add_r1kh(struct hostapd_bss_config *bss, char *value)
+{
+	struct ft_remote_r1kh *r1kh;
+	char *pos, *next;
+
+	r1kh = os_zalloc(sizeof(*r1kh));
+	if (r1kh == NULL)
+		return -1;
+
+	/* 02:01:02:03:04:05 02:01:02:03:04:05
+	 * 000102030405060708090a0b0c0d0e0f */
+	pos = value;
+	next = os_strchr(pos, ' ');
+	if (next)
+		*next++ = '\0';
+	if (next == NULL || hwaddr_aton(pos, r1kh->addr)) {
+		wpa_printf(MSG_ERROR, "Invalid R1KH MAC address: '%s'", pos);
+		os_free(r1kh);
+		return -1;
+	}
+
+	pos = next;
+	next = os_strchr(pos, ' ');
+	if (next)
+		*next++ = '\0';
+	if (next == NULL || hwaddr_aton(pos, r1kh->id)) {
+		wpa_printf(MSG_ERROR, "Invalid R1KH-ID: '%s'", pos);
+		os_free(r1kh);
+		return -1;
+	}
+
+	pos = next;
+	if (hexstr2bin(pos, r1kh->key, sizeof(r1kh->key))) {
+		wpa_printf(MSG_ERROR, "Invalid R1KH key: '%s'", pos);
+		os_free(r1kh);
+		return -1;
+	}
+
+	r1kh->next = bss->r1kh_list;
+	bss->r1kh_list = r1kh;
+
+	return 0;
+}
+#endif /* CONFIG_IEEE80211R */
+
+
+#ifdef CONFIG_IEEE80211N
+static int hostapd_config_ht_capab(struct hostapd_config *conf,
+				   const char *capab)
+{
+	if (os_strstr(capab, "[LDPC]"))
+		conf->ht_capab |= HT_CAP_INFO_LDPC_CODING_CAP;
+	if (os_strstr(capab, "[HT40-]")) {
+		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+		conf->secondary_channel = -1;
+	}
+	if (os_strstr(capab, "[HT40+]")) {
+		conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
+		conf->secondary_channel = 1;
+	}
+	if (os_strstr(capab, "[SMPS-STATIC]")) {
+		conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
+		conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC;
+	}
+	if (os_strstr(capab, "[SMPS-DYNAMIC]")) {
+		conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK;
+		conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC;
+	}
+	if (os_strstr(capab, "[GF]"))
+		conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD;
+	if (os_strstr(capab, "[SHORT-GI-20]"))
+		conf->ht_capab |= HT_CAP_INFO_SHORT_GI20MHZ;
+	if (os_strstr(capab, "[SHORT-GI-40]"))
+		conf->ht_capab |= HT_CAP_INFO_SHORT_GI40MHZ;
+	if (os_strstr(capab, "[TX-STBC]"))
+		conf->ht_capab |= HT_CAP_INFO_TX_STBC;
+	if (os_strstr(capab, "[RX-STBC1]")) {
+		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
+		conf->ht_capab |= HT_CAP_INFO_RX_STBC_1;
+	}
+	if (os_strstr(capab, "[RX-STBC12]")) {
+		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
+		conf->ht_capab |= HT_CAP_INFO_RX_STBC_12;
+	}
+	if (os_strstr(capab, "[RX-STBC123]")) {
+		conf->ht_capab &= ~HT_CAP_INFO_RX_STBC_MASK;
+		conf->ht_capab |= HT_CAP_INFO_RX_STBC_123;
+	}
+	if (os_strstr(capab, "[DELAYED-BA]"))
+		conf->ht_capab |= HT_CAP_INFO_DELAYED_BA;
+	if (os_strstr(capab, "[MAX-AMSDU-7935]"))
+		conf->ht_capab |= HT_CAP_INFO_MAX_AMSDU_SIZE;
+	if (os_strstr(capab, "[DSSS_CCK-40]"))
+		conf->ht_capab |= HT_CAP_INFO_DSSS_CCK40MHZ;
+	if (os_strstr(capab, "[40-INTOLERANT]"))
+		conf->ht_capab |= HT_CAP_INFO_40MHZ_INTOLERANT;
+	if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
+		conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
+
+	return 0;
+}
+#endif /* CONFIG_IEEE80211N */
+
+
+#ifdef CONFIG_IEEE80211AC
+static int hostapd_config_vht_capab(struct hostapd_config *conf,
+				    const char *capab)
+{
+	if (os_strstr(capab, "[MAX-MPDU-7991]"))
+		conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_7991;
+	if (os_strstr(capab, "[MAX-MPDU-11454]"))
+		conf->vht_capab |= VHT_CAP_MAX_MPDU_LENGTH_11454;
+	if (os_strstr(capab, "[VHT160]"))
+		conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+	if (os_strstr(capab, "[VHT160-80PLUS80]"))
+		conf->vht_capab |= VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+	if (os_strstr(capab, "[RXLDPC]"))
+		conf->vht_capab |= VHT_CAP_RXLDPC;
+	if (os_strstr(capab, "[SHORT-GI-80]"))
+		conf->vht_capab |= VHT_CAP_SHORT_GI_80;
+	if (os_strstr(capab, "[SHORT-GI-160]"))
+		conf->vht_capab |= VHT_CAP_SHORT_GI_160;
+	if (os_strstr(capab, "[TX-STBC-2BY1]"))
+		conf->vht_capab |= VHT_CAP_TXSTBC;
+	if (os_strstr(capab, "[RX-STBC-1]"))
+		conf->vht_capab |= VHT_CAP_RXSTBC_1;
+	if (os_strstr(capab, "[RX-STBC-12]"))
+		conf->vht_capab |= VHT_CAP_RXSTBC_2;
+	if (os_strstr(capab, "[RX-STBC-123]"))
+		conf->vht_capab |= VHT_CAP_RXSTBC_3;
+	if (os_strstr(capab, "[RX-STBC-1234]"))
+		conf->vht_capab |= VHT_CAP_RXSTBC_4;
+	if (os_strstr(capab, "[SU-BEAMFORMER]"))
+		conf->vht_capab |= VHT_CAP_SU_BEAMFORMER_CAPABLE;
+	if (os_strstr(capab, "[SU-BEAMFORMEE]"))
+		conf->vht_capab |= VHT_CAP_SU_BEAMFORMEE_CAPABLE;
+	if (os_strstr(capab, "[BF-ANTENNA-2]") &&
+	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
+		conf->vht_capab |= (1 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
+	if (os_strstr(capab, "[BF-ANTENNA-3]") &&
+	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
+		conf->vht_capab |= (2 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
+	if (os_strstr(capab, "[BF-ANTENNA-4]") &&
+	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
+		conf->vht_capab |= (3 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
+	if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") &&
+	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
+		conf->vht_capab |= (1 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
+	if (os_strstr(capab, "[SOUNDING-DIMENSION-3]") &&
+	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
+		conf->vht_capab |= (2 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
+	if (os_strstr(capab, "[SOUNDING-DIMENSION-4]") &&
+	    (conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
+		conf->vht_capab |= (3 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
+	if (os_strstr(capab, "[MU-BEAMFORMER]"))
+		conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
+	if (os_strstr(capab, "[VHT-TXOP-PS]"))
+		conf->vht_capab |= VHT_CAP_VHT_TXOP_PS;
+	if (os_strstr(capab, "[HTC-VHT]"))
+		conf->vht_capab |= VHT_CAP_HTC_VHT;
+	if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP7]"))
+		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX;
+	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP6]"))
+		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6;
+	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP5]"))
+		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_5;
+	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP4]"))
+		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_4;
+	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP3]"))
+		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_3;
+	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP2]"))
+		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_2;
+	else if (os_strstr(capab, "[MAX-A-MPDU-LEN-EXP1]"))
+		conf->vht_capab |= VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_1;
+	if (os_strstr(capab, "[VHT-LINK-ADAPT2]") &&
+	    (conf->vht_capab & VHT_CAP_HTC_VHT))
+		conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB;
+	if (os_strstr(capab, "[VHT-LINK-ADAPT3]") &&
+	    (conf->vht_capab & VHT_CAP_HTC_VHT))
+		conf->vht_capab |= VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
+	if (os_strstr(capab, "[RX-ANTENNA-PATTERN]"))
+		conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
+	if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
+		conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
+	return 0;
+}
+#endif /* CONFIG_IEEE80211AC */
+
+
+#ifdef CONFIG_INTERWORKING
+static int parse_roaming_consortium(struct hostapd_bss_config *bss, char *pos,
+				    int line)
+{
+	size_t len = os_strlen(pos);
+	u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
+
+	struct hostapd_roaming_consortium *rc;
+
+	if ((len & 1) || len < 2 * 3 || len / 2 > MAX_ROAMING_CONSORTIUM_LEN ||
+	    hexstr2bin(pos, oi, len / 2)) {
+		wpa_printf(MSG_ERROR, "Line %d: invalid roaming_consortium "
+			   "'%s'", line, pos);
+		return -1;
+	}
+	len /= 2;
+
+	rc = os_realloc_array(bss->roaming_consortium,
+			      bss->roaming_consortium_count + 1,
+			      sizeof(struct hostapd_roaming_consortium));
+	if (rc == NULL)
+		return -1;
+
+	os_memcpy(rc[bss->roaming_consortium_count].oi, oi, len);
+	rc[bss->roaming_consortium_count].len = len;
+
+	bss->roaming_consortium = rc;
+	bss->roaming_consortium_count++;
+
+	return 0;
+}
+
+
+static int parse_lang_string(struct hostapd_lang_string **array,
+			     unsigned int *count, char *pos)
+{
+	char *sep, *str = NULL;
+	size_t clen, nlen, slen;
+	struct hostapd_lang_string *ls;
+	int ret = -1;
+
+	if (*pos == '"' || (*pos == 'P' && pos[1] == '"')) {
+		str = wpa_config_parse_string(pos, &slen);
+		if (!str)
+			return -1;
+		pos = str;
+	}
+
+	sep = os_strchr(pos, ':');
+	if (sep == NULL)
+		goto fail;
+	*sep++ = '\0';
+
+	clen = os_strlen(pos);
+	if (clen < 2 || clen > sizeof(ls->lang))
+		goto fail;
+	nlen = os_strlen(sep);
+	if (nlen > 252)
+		goto fail;
+
+	ls = os_realloc_array(*array, *count + 1,
+			      sizeof(struct hostapd_lang_string));
+	if (ls == NULL)
+		goto fail;
+
+	*array = ls;
+	ls = &(*array)[*count];
+	(*count)++;
+
+	os_memset(ls->lang, 0, sizeof(ls->lang));
+	os_memcpy(ls->lang, pos, clen);
+	ls->name_len = nlen;
+	os_memcpy(ls->name, sep, nlen);
+
+	ret = 0;
+fail:
+	os_free(str);
+	return ret;
+}
+
+
+static int parse_venue_name(struct hostapd_bss_config *bss, char *pos,
+			    int line)
+{
+	if (parse_lang_string(&bss->venue_name, &bss->venue_name_count, pos)) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid venue_name '%s'",
+			   line, pos);
+		return -1;
+	}
+	return 0;
+}
+
+
+static int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf,
+			       int line)
+{
+	size_t count;
+	char *pos;
+	u8 *info = NULL, *ipos;
+
+	/* format: <MCC1,MNC1>[;<MCC2,MNC2>][;...] */
+
+	count = 1;
+	for (pos = buf; *pos; pos++) {
+		if ((*pos < '0' || *pos > '9') && *pos != ';' && *pos != ',')
+			goto fail;
+		if (*pos == ';')
+			count++;
+	}
+	if (1 + count * 3 > 0x7f)
+		goto fail;
+
+	info = os_zalloc(2 + 3 + count * 3);
+	if (info == NULL)
+		return -1;
+
+	ipos = info;
+	*ipos++ = 0; /* GUD - Version 1 */
+	*ipos++ = 3 + count * 3; /* User Data Header Length (UDHL) */
+	*ipos++ = 0; /* PLMN List IEI */
+	/* ext(b8) | Length of PLMN List value contents(b7..1) */
+	*ipos++ = 1 + count * 3;
+	*ipos++ = count; /* Number of PLMNs */
+
+	pos = buf;
+	while (pos && *pos) {
+		char *mcc, *mnc;
+		size_t mnc_len;
+
+		mcc = pos;
+		mnc = os_strchr(pos, ',');
+		if (mnc == NULL)
+			goto fail;
+		*mnc++ = '\0';
+		pos = os_strchr(mnc, ';');
+		if (pos)
+			*pos++ = '\0';
+
+		mnc_len = os_strlen(mnc);
+		if (os_strlen(mcc) != 3 || (mnc_len != 2 && mnc_len != 3))
+			goto fail;
+
+		/* BC coded MCC,MNC */
+		/* MCC digit 2 | MCC digit 1 */
+		*ipos++ = ((mcc[1] - '0') << 4) | (mcc[0] - '0');
+		/* MNC digit 3 | MCC digit 3 */
+		*ipos++ = (((mnc_len == 2) ? 0xf0 : ((mnc[2] - '0') << 4))) |
+			(mcc[2] - '0');
+		/* MNC digit 2 | MNC digit 1 */
+		*ipos++ = ((mnc[1] - '0') << 4) | (mnc[0] - '0');
+	}
+
+	os_free(bss->anqp_3gpp_cell_net);
+	bss->anqp_3gpp_cell_net = info;
+	bss->anqp_3gpp_cell_net_len = 2 + 3 + 3 * count;
+	wpa_hexdump(MSG_MSGDUMP, "3GPP Cellular Network information",
+		    bss->anqp_3gpp_cell_net, bss->anqp_3gpp_cell_net_len);
+
+	return 0;
+
+fail:
+	wpa_printf(MSG_ERROR, "Line %d: Invalid anqp_3gpp_cell_net: %s",
+		   line, buf);
+	os_free(info);
+	return -1;
+}
+
+
+static int parse_nai_realm(struct hostapd_bss_config *bss, char *buf, int line)
+{
+	struct hostapd_nai_realm_data *realm;
+	size_t i, j, len;
+	int *offsets;
+	char *pos, *end, *rpos;
+
+	offsets = os_calloc(bss->nai_realm_count * MAX_NAI_REALMS,
+			    sizeof(int));
+	if (offsets == NULL)
+		return -1;
+
+	for (i = 0; i < bss->nai_realm_count; i++) {
+		realm = &bss->nai_realm_data[i];
+		for (j = 0; j < MAX_NAI_REALMS; j++) {
+			offsets[i * MAX_NAI_REALMS + j] =
+				realm->realm[j] ?
+				realm->realm[j] - realm->realm_buf : -1;
+		}
+	}
+
+	realm = os_realloc_array(bss->nai_realm_data, bss->nai_realm_count + 1,
+				 sizeof(struct hostapd_nai_realm_data));
+	if (realm == NULL) {
+		os_free(offsets);
+		return -1;
+	}
+	bss->nai_realm_data = realm;
+
+	/* patch the pointers after realloc */
+	for (i = 0; i < bss->nai_realm_count; i++) {
+		realm = &bss->nai_realm_data[i];
+		for (j = 0; j < MAX_NAI_REALMS; j++) {
+			int offs = offsets[i * MAX_NAI_REALMS + j];
+			if (offs >= 0)
+				realm->realm[j] = realm->realm_buf + offs;
+			else
+				realm->realm[j] = NULL;
+		}
+	}
+	os_free(offsets);
+
+	realm = &bss->nai_realm_data[bss->nai_realm_count];
+	os_memset(realm, 0, sizeof(*realm));
+
+	pos = buf;
+	realm->encoding = atoi(pos);
+	pos = os_strchr(pos, ',');
+	if (pos == NULL)
+		goto fail;
+	pos++;
+
+	end = os_strchr(pos, ',');
+	if (end) {
+		len = end - pos;
+		*end = '\0';
+	} else {
+		len = os_strlen(pos);
+	}
+
+	if (len > MAX_NAI_REALMLEN) {
+		wpa_printf(MSG_ERROR, "Too long a realm string (%d > max %d "
+			   "characters)", (int) len, MAX_NAI_REALMLEN);
+		goto fail;
+	}
+	os_memcpy(realm->realm_buf, pos, len);
+
+	if (end)
+		pos = end + 1;
+	else
+		pos = NULL;
+
+	while (pos && *pos) {
+		struct hostapd_nai_realm_eap *eap;
+
+		if (realm->eap_method_count >= MAX_NAI_EAP_METHODS) {
+			wpa_printf(MSG_ERROR, "Too many EAP methods");
+			goto fail;
+		}
+
+		eap = &realm->eap_method[realm->eap_method_count];
+		realm->eap_method_count++;
+
+		end = os_strchr(pos, ',');
+		if (end == NULL)
+			end = pos + os_strlen(pos);
+
+		eap->eap_method = atoi(pos);
+		for (;;) {
+			pos = os_strchr(pos, '[');
+			if (pos == NULL || pos > end)
+				break;
+			pos++;
+			if (eap->num_auths >= MAX_NAI_AUTH_TYPES) {
+				wpa_printf(MSG_ERROR, "Too many auth params");
+				goto fail;
+			}
+			eap->auth_id[eap->num_auths] = atoi(pos);
+			pos = os_strchr(pos, ':');
+			if (pos == NULL || pos > end)
+				goto fail;
+			pos++;
+			eap->auth_val[eap->num_auths] = atoi(pos);
+			pos = os_strchr(pos, ']');
+			if (pos == NULL || pos > end)
+				goto fail;
+			pos++;
+			eap->num_auths++;
+		}
+
+		if (*end != ',')
+			break;
+
+		pos = end + 1;
+	}
+
+	/* Split realm list into null terminated realms */
+	rpos = realm->realm_buf;
+	i = 0;
+	while (*rpos) {
+		if (i >= MAX_NAI_REALMS) {
+			wpa_printf(MSG_ERROR, "Too many realms");
+			goto fail;
+		}
+		realm->realm[i++] = rpos;
+		rpos = os_strchr(rpos, ';');
+		if (rpos == NULL)
+			break;
+		*rpos++ = '\0';
+	}
+
+	bss->nai_realm_count++;
+
+	return 0;
+
+fail:
+	wpa_printf(MSG_ERROR, "Line %d: invalid nai_realm '%s'", line, buf);
+	return -1;
+}
+
+
+static int parse_anqp_elem(struct hostapd_bss_config *bss, char *buf, int line)
+{
+	char *delim;
+	u16 infoid;
+	size_t len;
+	struct wpabuf *payload;
+	struct anqp_element *elem;
+
+	delim = os_strchr(buf, ':');
+	if (!delim)
+		return -1;
+	delim++;
+	infoid = atoi(buf);
+	len = os_strlen(delim);
+	if (len & 1)
+		return -1;
+	len /= 2;
+	payload = wpabuf_alloc(len);
+	if (!payload)
+		return -1;
+	if (hexstr2bin(delim, wpabuf_put(payload, len), len) < 0) {
+		wpabuf_free(payload);
+		return -1;
+	}
+
+	dl_list_for_each(elem, &bss->anqp_elem, struct anqp_element, list) {
+		if (elem->infoid == infoid) {
+			/* Update existing entry */
+			wpabuf_free(elem->payload);
+			elem->payload = payload;
+			return 0;
+		}
+	}
+
+	/* Add a new entry */
+	elem = os_zalloc(sizeof(*elem));
+	if (!elem) {
+		wpabuf_free(payload);
+		return -1;
+	}
+	elem->infoid = infoid;
+	elem->payload = payload;
+	dl_list_add(&bss->anqp_elem, &elem->list);
+
+	return 0;
+}
+
+
+static int parse_qos_map_set(struct hostapd_bss_config *bss,
+			     char *buf, int line)
+{
+	u8 qos_map_set[16 + 2 * 21], count = 0;
+	char *pos = buf;
+	int val;
+
+	for (;;) {
+		if (count == sizeof(qos_map_set)) {
+			wpa_printf(MSG_ERROR, "Line %d: Too many qos_map_set "
+				   "parameters '%s'", line, buf);
+			return -1;
+		}
+
+		val = atoi(pos);
+		if (val > 255 || val < 0) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set "
+				   "'%s'", line, buf);
+			return -1;
+		}
+
+		qos_map_set[count++] = val;
+		pos = os_strchr(pos, ',');
+		if (!pos)
+			break;
+		pos++;
+	}
+
+	if (count < 16 || count & 1) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid qos_map_set '%s'",
+			   line, buf);
+		return -1;
+	}
+
+	os_memcpy(bss->qos_map_set, qos_map_set, count);
+	bss->qos_map_set_len = count;
+
+	return 0;
+}
+
+#endif /* CONFIG_INTERWORKING */
+
+
+#ifdef CONFIG_HS20
+static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
+				 int line)
+{
+	u8 *conn_cap;
+	char *pos;
+
+	if (bss->hs20_connection_capability_len >= 0xfff0)
+		return -1;
+
+	conn_cap = os_realloc(bss->hs20_connection_capability,
+			      bss->hs20_connection_capability_len + 4);
+	if (conn_cap == NULL)
+		return -1;
+
+	bss->hs20_connection_capability = conn_cap;
+	conn_cap += bss->hs20_connection_capability_len;
+	pos = buf;
+	conn_cap[0] = atoi(pos);
+	pos = os_strchr(pos, ':');
+	if (pos == NULL)
+		return -1;
+	pos++;
+	WPA_PUT_LE16(conn_cap + 1, atoi(pos));
+	pos = os_strchr(pos, ':');
+	if (pos == NULL)
+		return -1;
+	pos++;
+	conn_cap[3] = atoi(pos);
+	bss->hs20_connection_capability_len += 4;
+
+	return 0;
+}
+
+
+static int hs20_parse_wan_metrics(struct hostapd_bss_config *bss, char *buf,
+				  int line)
+{
+	u8 *wan_metrics;
+	char *pos;
+
+	/* <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD> */
+
+	wan_metrics = os_zalloc(13);
+	if (wan_metrics == NULL)
+		return -1;
+
+	pos = buf;
+	/* WAN Info */
+	if (hexstr2bin(pos, wan_metrics, 1) < 0)
+		goto fail;
+	pos += 2;
+	if (*pos != ':')
+		goto fail;
+	pos++;
+
+	/* Downlink Speed */
+	WPA_PUT_LE32(wan_metrics + 1, atoi(pos));
+	pos = os_strchr(pos, ':');
+	if (pos == NULL)
+		goto fail;
+	pos++;
+
+	/* Uplink Speed */
+	WPA_PUT_LE32(wan_metrics + 5, atoi(pos));
+	pos = os_strchr(pos, ':');
+	if (pos == NULL)
+		goto fail;
+	pos++;
+
+	/* Downlink Load */
+	wan_metrics[9] = atoi(pos);
+	pos = os_strchr(pos, ':');
+	if (pos == NULL)
+		goto fail;
+	pos++;
+
+	/* Uplink Load */
+	wan_metrics[10] = atoi(pos);
+	pos = os_strchr(pos, ':');
+	if (pos == NULL)
+		goto fail;
+	pos++;
+
+	/* LMD */
+	WPA_PUT_LE16(wan_metrics + 11, atoi(pos));
+
+	os_free(bss->hs20_wan_metrics);
+	bss->hs20_wan_metrics = wan_metrics;
+
+	return 0;
+
+fail:
+	wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_wan_metrics '%s'",
+		   line, buf);
+	os_free(wan_metrics);
+	return -1;
+}
+
+
+static int hs20_parse_oper_friendly_name(struct hostapd_bss_config *bss,
+					 char *pos, int line)
+{
+	if (parse_lang_string(&bss->hs20_oper_friendly_name,
+			      &bss->hs20_oper_friendly_name_count, pos)) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid "
+			   "hs20_oper_friendly_name '%s'", line, pos);
+		return -1;
+	}
+	return 0;
+}
+
+
+static int hs20_parse_icon(struct hostapd_bss_config *bss, char *pos)
+{
+	struct hs20_icon *icon;
+	char *end;
+
+	icon = os_realloc_array(bss->hs20_icons, bss->hs20_icons_count + 1,
+				sizeof(struct hs20_icon));
+	if (icon == NULL)
+		return -1;
+	bss->hs20_icons = icon;
+	icon = &bss->hs20_icons[bss->hs20_icons_count];
+	os_memset(icon, 0, sizeof(*icon));
+
+	icon->width = atoi(pos);
+	pos = os_strchr(pos, ':');
+	if (pos == NULL)
+		return -1;
+	pos++;
+
+	icon->height = atoi(pos);
+	pos = os_strchr(pos, ':');
+	if (pos == NULL)
+		return -1;
+	pos++;
+
+	end = os_strchr(pos, ':');
+	if (end == NULL || end - pos > 3)
+		return -1;
+	os_memcpy(icon->language, pos, end - pos);
+	pos = end + 1;
+
+	end = os_strchr(pos, ':');
+	if (end == NULL || end - pos > 255)
+		return -1;
+	os_memcpy(icon->type, pos, end - pos);
+	pos = end + 1;
+
+	end = os_strchr(pos, ':');
+	if (end == NULL || end - pos > 255)
+		return -1;
+	os_memcpy(icon->name, pos, end - pos);
+	pos = end + 1;
+
+	if (os_strlen(pos) > 255)
+		return -1;
+	os_memcpy(icon->file, pos, os_strlen(pos));
+
+	bss->hs20_icons_count++;
+
+	return 0;
+}
+
+
+static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss,
+			       char *pos, int line)
+{
+	size_t slen;
+	char *str;
+
+	str = wpa_config_parse_string(pos, &slen);
+	if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos);
+		os_free(str);
+		return -1;
+	}
+
+	os_memcpy(bss->osu_ssid, str, slen);
+	bss->osu_ssid_len = slen;
+	os_free(str);
+
+	return 0;
+}
+
+
+static int hs20_parse_osu_server_uri(struct hostapd_bss_config *bss,
+				     char *pos, int line)
+{
+	struct hs20_osu_provider *p;
+
+	p = os_realloc_array(bss->hs20_osu_providers,
+			     bss->hs20_osu_providers_count + 1, sizeof(*p));
+	if (p == NULL)
+		return -1;
+
+	bss->hs20_osu_providers = p;
+	bss->last_osu = &bss->hs20_osu_providers[bss->hs20_osu_providers_count];
+	bss->hs20_osu_providers_count++;
+	os_memset(bss->last_osu, 0, sizeof(*p));
+	bss->last_osu->server_uri = os_strdup(pos);
+
+	return 0;
+}
+
+
+static int hs20_parse_osu_friendly_name(struct hostapd_bss_config *bss,
+					char *pos, int line)
+{
+	if (bss->last_osu == NULL) {
+		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+		return -1;
+	}
+
+	if (parse_lang_string(&bss->last_osu->friendly_name,
+			      &bss->last_osu->friendly_name_count, pos)) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid osu_friendly_name '%s'",
+			   line, pos);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int hs20_parse_osu_nai(struct hostapd_bss_config *bss,
+			      char *pos, int line)
+{
+	if (bss->last_osu == NULL) {
+		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+		return -1;
+	}
+
+	os_free(bss->last_osu->osu_nai);
+	bss->last_osu->osu_nai = os_strdup(pos);
+	if (bss->last_osu->osu_nai == NULL)
+		return -1;
+
+	return 0;
+}
+
+
+static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos,
+				      int line)
+{
+	if (bss->last_osu == NULL) {
+		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+		return -1;
+	}
+
+	if (hostapd_parse_intlist(&bss->last_osu->method_list, pos)) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid osu_method_list", line);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int hs20_parse_osu_icon(struct hostapd_bss_config *bss, char *pos,
+			       int line)
+{
+	char **n;
+	struct hs20_osu_provider *p = bss->last_osu;
+
+	if (p == NULL) {
+		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+		return -1;
+	}
+
+	n = os_realloc_array(p->icons, p->icons_count + 1, sizeof(char *));
+	if (n == NULL)
+		return -1;
+	p->icons = n;
+	p->icons[p->icons_count] = os_strdup(pos);
+	if (p->icons[p->icons_count] == NULL)
+		return -1;
+	p->icons_count++;
+
+	return 0;
+}
+
+
+static int hs20_parse_osu_service_desc(struct hostapd_bss_config *bss,
+				       char *pos, int line)
+{
+	if (bss->last_osu == NULL) {
+		wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+		return -1;
+	}
+
+	if (parse_lang_string(&bss->last_osu->service_desc,
+			      &bss->last_osu->service_desc_count, pos)) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid osu_service_desc '%s'",
+			   line, pos);
+		return -1;
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_HS20 */
+
+
+#ifdef CONFIG_ACS
+static int hostapd_config_parse_acs_chan_bias(struct hostapd_config *conf,
+					      char *pos)
+{
+	struct acs_bias *bias = NULL, *tmp;
+	unsigned int num = 0;
+	char *end;
+
+	while (*pos) {
+		tmp = os_realloc_array(bias, num + 1, sizeof(*bias));
+		if (!tmp)
+			goto fail;
+		bias = tmp;
+
+		bias[num].channel = atoi(pos);
+		if (bias[num].channel <= 0)
+			goto fail;
+		pos = os_strchr(pos, ':');
+		if (!pos)
+			goto fail;
+		pos++;
+		bias[num].bias = strtod(pos, &end);
+		if (end == pos || bias[num].bias < 0.0)
+			goto fail;
+		pos = end;
+		if (*pos != ' ' && *pos != '\0')
+			goto fail;
+		num++;
+	}
+
+	os_free(conf->acs_chan_bias);
+	conf->acs_chan_bias = bias;
+	conf->num_acs_chan_bias = num;
+
+	return 0;
+fail:
+	os_free(bias);
+	return -1;
+}
+#endif /* CONFIG_ACS */
+
+
+static int parse_wpabuf_hex(int line, const char *name, struct wpabuf **buf,
+			    const char *val)
+{
+	struct wpabuf *elems;
+
+	if (val[0] == '\0') {
+		wpabuf_free(*buf);
+		*buf = NULL;
+		return 0;
+	}
+
+	elems = wpabuf_parse_bin(val);
+	if (!elems) {
+		wpa_printf(MSG_ERROR, "Line %d: Invalid %s '%s'",
+			   line, name, val);
+		return -1;
+	}
+
+	wpabuf_free(*buf);
+	*buf = elems;
+
+	return 0;
+}
+
+
+static int hostapd_config_fill(struct hostapd_config *conf,
+			       struct hostapd_bss_config *bss,
+			       const char *buf, char *pos, int line)
+{
+	if (os_strcmp(buf, "interface") == 0) {
+		os_strlcpy(conf->bss[0]->iface, pos,
+			   sizeof(conf->bss[0]->iface));
+	} else if (os_strcmp(buf, "bridge") == 0) {
+		os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
+	} else if (os_strcmp(buf, "vlan_bridge") == 0) {
+		os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
+	} else if (os_strcmp(buf, "wds_bridge") == 0) {
+		os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
+	} else if (os_strcmp(buf, "driver") == 0) {
+		int j;
+		/* clear to get error below if setting is invalid */
+		conf->driver = NULL;
+		for (j = 0; wpa_drivers[j]; j++) {
+			if (os_strcmp(pos, wpa_drivers[j]->name) == 0) {
+				conf->driver = wpa_drivers[j];
+				break;
+			}
+		}
+		if (conf->driver == NULL) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid/unknown driver '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "driver_params") == 0) {
+		os_free(conf->driver_params);
+		conf->driver_params = os_strdup(pos);
+	} else if (os_strcmp(buf, "debug") == 0) {
+		wpa_printf(MSG_DEBUG, "Line %d: DEPRECATED: 'debug' configuration variable is not used anymore",
+			   line);
+	} else if (os_strcmp(buf, "logger_syslog_level") == 0) {
+		bss->logger_syslog_level = atoi(pos);
+	} else if (os_strcmp(buf, "logger_stdout_level") == 0) {
+		bss->logger_stdout_level = atoi(pos);
+	} else if (os_strcmp(buf, "logger_syslog") == 0) {
+		bss->logger_syslog = atoi(pos);
+	} else if (os_strcmp(buf, "logger_stdout") == 0) {
+		bss->logger_stdout = atoi(pos);
+	} else if (os_strcmp(buf, "dump_file") == 0) {
+		wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
+			   line);
+	} else if (os_strcmp(buf, "ssid") == 0) {
+		bss->ssid.ssid_len = os_strlen(pos);
+		if (bss->ssid.ssid_len > SSID_MAX_LEN ||
+		    bss->ssid.ssid_len < 1) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
+				   line, pos);
+			return 1;
+		}
+		os_memcpy(bss->ssid.ssid, pos, bss->ssid.ssid_len);
+		bss->ssid.ssid_set = 1;
+	} else if (os_strcmp(buf, "ssid2") == 0) {
+		size_t slen;
+		char *str = wpa_config_parse_string(pos, &slen);
+		if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
+				   line, pos);
+			os_free(str);
+			return 1;
+		}
+		os_memcpy(bss->ssid.ssid, str, slen);
+		bss->ssid.ssid_len = slen;
+		bss->ssid.ssid_set = 1;
+		os_free(str);
+	} else if (os_strcmp(buf, "utf8_ssid") == 0) {
+		bss->ssid.utf8_ssid = atoi(pos) > 0;
+	} else if (os_strcmp(buf, "macaddr_acl") == 0) {
+		bss->macaddr_acl = atoi(pos);
+		if (bss->macaddr_acl != ACCEPT_UNLESS_DENIED &&
+		    bss->macaddr_acl != DENY_UNLESS_ACCEPTED &&
+		    bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
+			wpa_printf(MSG_ERROR, "Line %d: unknown macaddr_acl %d",
+				   line, bss->macaddr_acl);
+		}
+	} else if (os_strcmp(buf, "accept_mac_file") == 0) {
+		if (hostapd_config_read_maclist(pos, &bss->accept_mac,
+						&bss->num_accept_mac)) {
+			wpa_printf(MSG_ERROR, "Line %d: Failed to read accept_mac_file '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "deny_mac_file") == 0) {
+		if (hostapd_config_read_maclist(pos, &bss->deny_mac,
+						&bss->num_deny_mac)) {
+			wpa_printf(MSG_ERROR, "Line %d: Failed to read deny_mac_file '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wds_sta") == 0) {
+		bss->wds_sta = atoi(pos);
+	} else if (os_strcmp(buf, "start_disabled") == 0) {
+		bss->start_disabled = atoi(pos);
+	} else if (os_strcmp(buf, "ap_isolate") == 0) {
+		bss->isolate = atoi(pos);
+	} else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
+		bss->ap_max_inactivity = atoi(pos);
+	} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
+		bss->skip_inactivity_poll = atoi(pos);
+	} else if (os_strcmp(buf, "country_code") == 0) {
+		os_memcpy(conf->country, pos, 2);
+		/* FIX: make this configurable */
+		conf->country[2] = ' ';
+	} else if (os_strcmp(buf, "ieee80211d") == 0) {
+		conf->ieee80211d = atoi(pos);
+	} else if (os_strcmp(buf, "ieee80211h") == 0) {
+		conf->ieee80211h = atoi(pos);
+	} else if (os_strcmp(buf, "ieee8021x") == 0) {
+		bss->ieee802_1x = atoi(pos);
+	} else if (os_strcmp(buf, "eapol_version") == 0) {
+		bss->eapol_version = atoi(pos);
+		if (bss->eapol_version < 1 || bss->eapol_version > 2) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid EAPOL version (%d): '%s'.",
+				   line, bss->eapol_version, pos);
+			return 1;
+		}
+		wpa_printf(MSG_DEBUG, "eapol_version=%d", bss->eapol_version);
+#ifdef EAP_SERVER
+	} else if (os_strcmp(buf, "eap_authenticator") == 0) {
+		bss->eap_server = atoi(pos);
+		wpa_printf(MSG_ERROR, "Line %d: obsolete eap_authenticator used; this has been renamed to eap_server", line);
+	} else if (os_strcmp(buf, "eap_server") == 0) {
+		bss->eap_server = atoi(pos);
+	} else if (os_strcmp(buf, "eap_user_file") == 0) {
+		if (hostapd_config_read_eap_user(pos, bss))
+			return 1;
+	} else if (os_strcmp(buf, "ca_cert") == 0) {
+		os_free(bss->ca_cert);
+		bss->ca_cert = os_strdup(pos);
+	} else if (os_strcmp(buf, "server_cert") == 0) {
+		os_free(bss->server_cert);
+		bss->server_cert = os_strdup(pos);
+	} else if (os_strcmp(buf, "private_key") == 0) {
+		os_free(bss->private_key);
+		bss->private_key = os_strdup(pos);
+	} else if (os_strcmp(buf, "private_key_passwd") == 0) {
+		os_free(bss->private_key_passwd);
+		bss->private_key_passwd = os_strdup(pos);
+	} else if (os_strcmp(buf, "check_crl") == 0) {
+		bss->check_crl = atoi(pos);
+	} else if (os_strcmp(buf, "tls_session_lifetime") == 0) {
+		bss->tls_session_lifetime = atoi(pos);
+	} else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
+		os_free(bss->ocsp_stapling_response);
+		bss->ocsp_stapling_response = os_strdup(pos);
+	} else if (os_strcmp(buf, "ocsp_stapling_response_multi") == 0) {
+		os_free(bss->ocsp_stapling_response_multi);
+		bss->ocsp_stapling_response_multi = os_strdup(pos);
+	} else if (os_strcmp(buf, "dh_file") == 0) {
+		os_free(bss->dh_file);
+		bss->dh_file = os_strdup(pos);
+	} else if (os_strcmp(buf, "openssl_ciphers") == 0) {
+		os_free(bss->openssl_ciphers);
+		bss->openssl_ciphers = os_strdup(pos);
+	} else if (os_strcmp(buf, "fragment_size") == 0) {
+		bss->fragment_size = atoi(pos);
+#ifdef EAP_SERVER_FAST
+	} else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) {
+		os_free(bss->pac_opaque_encr_key);
+		bss->pac_opaque_encr_key = os_malloc(16);
+		if (bss->pac_opaque_encr_key == NULL) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: No memory for pac_opaque_encr_key",
+				   line);
+			return 1;
+		} else if (hexstr2bin(pos, bss->pac_opaque_encr_key, 16)) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid pac_opaque_encr_key",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
+		size_t idlen = os_strlen(pos);
+		if (idlen & 1) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid eap_fast_a_id",
+				   line);
+			return 1;
+		}
+		os_free(bss->eap_fast_a_id);
+		bss->eap_fast_a_id = os_malloc(idlen / 2);
+		if (bss->eap_fast_a_id == NULL ||
+		    hexstr2bin(pos, bss->eap_fast_a_id, idlen / 2)) {
+			wpa_printf(MSG_ERROR, "Line %d: Failed to parse eap_fast_a_id",
+				   line);
+			os_free(bss->eap_fast_a_id);
+			bss->eap_fast_a_id = NULL;
+			return 1;
+		} else {
+			bss->eap_fast_a_id_len = idlen / 2;
+		}
+	} else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) {
+		os_free(bss->eap_fast_a_id_info);
+		bss->eap_fast_a_id_info = os_strdup(pos);
+	} else if (os_strcmp(buf, "eap_fast_prov") == 0) {
+		bss->eap_fast_prov = atoi(pos);
+	} else if (os_strcmp(buf, "pac_key_lifetime") == 0) {
+		bss->pac_key_lifetime = atoi(pos);
+	} else if (os_strcmp(buf, "pac_key_refresh_time") == 0) {
+		bss->pac_key_refresh_time = atoi(pos);
+#endif /* EAP_SERVER_FAST */
+#ifdef EAP_SERVER_SIM
+	} else if (os_strcmp(buf, "eap_sim_db") == 0) {
+		os_free(bss->eap_sim_db);
+		bss->eap_sim_db = os_strdup(pos);
+	} else if (os_strcmp(buf, "eap_sim_db_timeout") == 0) {
+		bss->eap_sim_db_timeout = atoi(pos);
+	} else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) {
+		bss->eap_sim_aka_result_ind = atoi(pos);
+#endif /* EAP_SERVER_SIM */
+#ifdef EAP_SERVER_TNC
+	} else if (os_strcmp(buf, "tnc") == 0) {
+		bss->tnc = atoi(pos);
+#endif /* EAP_SERVER_TNC */
+#ifdef EAP_SERVER_PWD
+	} else if (os_strcmp(buf, "pwd_group") == 0) {
+		bss->pwd_group = atoi(pos);
+#endif /* EAP_SERVER_PWD */
+	} else if (os_strcmp(buf, "eap_server_erp") == 0) {
+		bss->eap_server_erp = atoi(pos);
+#endif /* EAP_SERVER */
+	} else if (os_strcmp(buf, "eap_message") == 0) {
+		char *term;
+		os_free(bss->eap_req_id_text);
+		bss->eap_req_id_text = os_strdup(pos);
+		if (bss->eap_req_id_text == NULL) {
+			wpa_printf(MSG_ERROR, "Line %d: Failed to allocate memory for eap_req_id_text",
+				   line);
+			return 1;
+		}
+		bss->eap_req_id_text_len = os_strlen(bss->eap_req_id_text);
+		term = os_strstr(bss->eap_req_id_text, "\\0");
+		if (term) {
+			*term++ = '\0';
+			os_memmove(term, term + 1,
+				   bss->eap_req_id_text_len -
+				   (term - bss->eap_req_id_text) - 1);
+			bss->eap_req_id_text_len--;
+		}
+	} else if (os_strcmp(buf, "erp_send_reauth_start") == 0) {
+		bss->erp_send_reauth_start = atoi(pos);
+	} else if (os_strcmp(buf, "erp_domain") == 0) {
+		os_free(bss->erp_domain);
+		bss->erp_domain = os_strdup(pos);
+	} else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) {
+		bss->default_wep_key_len = atoi(pos);
+		if (bss->default_wep_key_len > 13) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid WEP key len %lu (= %lu bits)",
+				   line,
+				   (unsigned long) bss->default_wep_key_len,
+				   (unsigned long)
+				   bss->default_wep_key_len * 8);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wep_key_len_unicast") == 0) {
+		bss->individual_wep_key_len = atoi(pos);
+		if (bss->individual_wep_key_len < 0 ||
+		    bss->individual_wep_key_len > 13) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid WEP key len %d (= %d bits)",
+				   line, bss->individual_wep_key_len,
+				   bss->individual_wep_key_len * 8);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wep_rekey_period") == 0) {
+		bss->wep_rekeying_period = atoi(pos);
+		if (bss->wep_rekeying_period < 0) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
+				   line, bss->wep_rekeying_period);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "eap_reauth_period") == 0) {
+		bss->eap_reauth_period = atoi(pos);
+		if (bss->eap_reauth_period < 0) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid period %d",
+				   line, bss->eap_reauth_period);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) {
+		bss->eapol_key_index_workaround = atoi(pos);
+#ifdef CONFIG_IAPP
+	} else if (os_strcmp(buf, "iapp_interface") == 0) {
+		bss->ieee802_11f = 1;
+		os_strlcpy(bss->iapp_iface, pos, sizeof(bss->iapp_iface));
+#endif /* CONFIG_IAPP */
+	} else if (os_strcmp(buf, "own_ip_addr") == 0) {
+		if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid IP address '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "nas_identifier") == 0) {
+		os_free(bss->nas_identifier);
+		bss->nas_identifier = os_strdup(pos);
+#ifndef CONFIG_NO_RADIUS
+	} else if (os_strcmp(buf, "radius_client_addr") == 0) {
+		if (hostapd_parse_ip_addr(pos, &bss->radius->client_addr)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid IP address '%s'",
+				   line, pos);
+			return 1;
+		}
+		bss->radius->force_client_addr = 1;
+	} else if (os_strcmp(buf, "auth_server_addr") == 0) {
+		if (hostapd_config_read_radius_addr(
+			    &bss->radius->auth_servers,
+			    &bss->radius->num_auth_servers, pos, 1812,
+			    &bss->radius->auth_server)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid IP address '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (bss->radius->auth_server &&
+		   os_strcmp(buf, "auth_server_addr_replace") == 0) {
+		if (hostapd_parse_ip_addr(pos,
+					  &bss->radius->auth_server->addr)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid IP address '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (bss->radius->auth_server &&
+		   os_strcmp(buf, "auth_server_port") == 0) {
+		bss->radius->auth_server->port = atoi(pos);
+	} else if (bss->radius->auth_server &&
+		   os_strcmp(buf, "auth_server_shared_secret") == 0) {
+		int len = os_strlen(pos);
+		if (len == 0) {
+			/* RFC 2865, Ch. 3 */
+			wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
+				   line);
+			return 1;
+		}
+		os_free(bss->radius->auth_server->shared_secret);
+		bss->radius->auth_server->shared_secret = (u8 *) os_strdup(pos);
+		bss->radius->auth_server->shared_secret_len = len;
+	} else if (os_strcmp(buf, "acct_server_addr") == 0) {
+		if (hostapd_config_read_radius_addr(
+			    &bss->radius->acct_servers,
+			    &bss->radius->num_acct_servers, pos, 1813,
+			    &bss->radius->acct_server)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid IP address '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (bss->radius->acct_server &&
+		   os_strcmp(buf, "acct_server_addr_replace") == 0) {
+		if (hostapd_parse_ip_addr(pos,
+					  &bss->radius->acct_server->addr)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid IP address '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (bss->radius->acct_server &&
+		   os_strcmp(buf, "acct_server_port") == 0) {
+		bss->radius->acct_server->port = atoi(pos);
+	} else if (bss->radius->acct_server &&
+		   os_strcmp(buf, "acct_server_shared_secret") == 0) {
+		int len = os_strlen(pos);
+		if (len == 0) {
+			/* RFC 2865, Ch. 3 */
+			wpa_printf(MSG_ERROR, "Line %d: empty shared secret is not allowed",
+				   line);
+			return 1;
+		}
+		os_free(bss->radius->acct_server->shared_secret);
+		bss->radius->acct_server->shared_secret = (u8 *) os_strdup(pos);
+		bss->radius->acct_server->shared_secret_len = len;
+	} else if (os_strcmp(buf, "radius_retry_primary_interval") == 0) {
+		bss->radius->retry_primary_interval = atoi(pos);
+	} else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) {
+		bss->acct_interim_interval = atoi(pos);
+	} else if (os_strcmp(buf, "radius_request_cui") == 0) {
+		bss->radius_request_cui = atoi(pos);
+	} else if (os_strcmp(buf, "radius_auth_req_attr") == 0) {
+		struct hostapd_radius_attr *attr, *a;
+		attr = hostapd_parse_radius_attr(pos);
+		if (attr == NULL) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid radius_auth_req_attr",
+				   line);
+			return 1;
+		} else if (bss->radius_auth_req_attr == NULL) {
+			bss->radius_auth_req_attr = attr;
+		} else {
+			a = bss->radius_auth_req_attr;
+			while (a->next)
+				a = a->next;
+			a->next = attr;
+		}
+	} else if (os_strcmp(buf, "radius_acct_req_attr") == 0) {
+		struct hostapd_radius_attr *attr, *a;
+		attr = hostapd_parse_radius_attr(pos);
+		if (attr == NULL) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid radius_acct_req_attr",
+				   line);
+			return 1;
+		} else if (bss->radius_acct_req_attr == NULL) {
+			bss->radius_acct_req_attr = attr;
+		} else {
+			a = bss->radius_acct_req_attr;
+			while (a->next)
+				a = a->next;
+			a->next = attr;
+		}
+	} else if (os_strcmp(buf, "radius_das_port") == 0) {
+		bss->radius_das_port = atoi(pos);
+	} else if (os_strcmp(buf, "radius_das_client") == 0) {
+		if (hostapd_parse_das_client(bss, pos) < 0) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid DAS client",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "radius_das_time_window") == 0) {
+		bss->radius_das_time_window = atoi(pos);
+	} else if (os_strcmp(buf, "radius_das_require_event_timestamp") == 0) {
+		bss->radius_das_require_event_timestamp = atoi(pos);
+	} else if (os_strcmp(buf, "radius_das_require_message_authenticator") ==
+		   0) {
+		bss->radius_das_require_message_authenticator = atoi(pos);
+#endif /* CONFIG_NO_RADIUS */
+	} else if (os_strcmp(buf, "auth_algs") == 0) {
+		bss->auth_algs = atoi(pos);
+		if (bss->auth_algs == 0) {
+			wpa_printf(MSG_ERROR, "Line %d: no authentication algorithms allowed",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "max_num_sta") == 0) {
+		bss->max_num_sta = atoi(pos);
+		if (bss->max_num_sta < 0 ||
+		    bss->max_num_sta > MAX_STA_COUNT) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d",
+				   line, bss->max_num_sta, MAX_STA_COUNT);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wpa") == 0) {
+		bss->wpa = atoi(pos);
+	} else if (os_strcmp(buf, "wpa_group_rekey") == 0) {
+		bss->wpa_group_rekey = atoi(pos);
+	} else if (os_strcmp(buf, "wpa_strict_rekey") == 0) {
+		bss->wpa_strict_rekey = atoi(pos);
+	} else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) {
+		bss->wpa_gmk_rekey = atoi(pos);
+	} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
+		bss->wpa_ptk_rekey = atoi(pos);
+	} else if (os_strcmp(buf, "wpa_passphrase") == 0) {
+		int len = os_strlen(pos);
+		if (len < 8 || len > 63) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length %d (expected 8..63)",
+				   line, len);
+			return 1;
+		}
+		os_free(bss->ssid.wpa_passphrase);
+		bss->ssid.wpa_passphrase = os_strdup(pos);
+		if (bss->ssid.wpa_passphrase) {
+			hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
+			bss->ssid.wpa_passphrase_set = 1;
+		}
+	} else if (os_strcmp(buf, "wpa_psk") == 0) {
+		hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
+		bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
+		if (bss->ssid.wpa_psk == NULL)
+			return 1;
+		if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, PMK_LEN) ||
+		    pos[PMK_LEN * 2] != '\0') {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.",
+				   line, pos);
+			hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk);
+			return 1;
+		}
+		bss->ssid.wpa_psk->group = 1;
+		os_free(bss->ssid.wpa_passphrase);
+		bss->ssid.wpa_passphrase = NULL;
+		bss->ssid.wpa_psk_set = 1;
+	} else if (os_strcmp(buf, "wpa_psk_file") == 0) {
+		os_free(bss->ssid.wpa_psk_file);
+		bss->ssid.wpa_psk_file = os_strdup(pos);
+		if (!bss->ssid.wpa_psk_file) {
+			wpa_printf(MSG_ERROR, "Line %d: allocation failed",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wpa_key_mgmt") == 0) {
+		bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos);
+		if (bss->wpa_key_mgmt == -1)
+			return 1;
+	} else if (os_strcmp(buf, "wpa_psk_radius") == 0) {
+		bss->wpa_psk_radius = atoi(pos);
+		if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
+		    bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
+		    bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: unknown wpa_psk_radius %d",
+				   line, bss->wpa_psk_radius);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wpa_pairwise") == 0) {
+		bss->wpa_pairwise = hostapd_config_parse_cipher(line, pos);
+		if (bss->wpa_pairwise == -1 || bss->wpa_pairwise == 0)
+			return 1;
+		if (bss->wpa_pairwise &
+		    (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
+			wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
+				   bss->wpa_pairwise, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "rsn_pairwise") == 0) {
+		bss->rsn_pairwise = hostapd_config_parse_cipher(line, pos);
+		if (bss->rsn_pairwise == -1 || bss->rsn_pairwise == 0)
+			return 1;
+		if (bss->rsn_pairwise &
+		    (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) {
+			wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'",
+				   bss->rsn_pairwise, pos);
+			return 1;
+		}
+#ifdef CONFIG_RSN_PREAUTH
+	} else if (os_strcmp(buf, "rsn_preauth") == 0) {
+		bss->rsn_preauth = atoi(pos);
+	} else if (os_strcmp(buf, "rsn_preauth_interfaces") == 0) {
+		os_free(bss->rsn_preauth_interfaces);
+		bss->rsn_preauth_interfaces = os_strdup(pos);
+#endif /* CONFIG_RSN_PREAUTH */
+#ifdef CONFIG_PEERKEY
+	} else if (os_strcmp(buf, "peerkey") == 0) {
+		bss->peerkey = atoi(pos);
+#endif /* CONFIG_PEERKEY */
+#ifdef CONFIG_IEEE80211R
+	} else if (os_strcmp(buf, "mobility_domain") == 0) {
+		if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
+		    hexstr2bin(pos, bss->mobility_domain,
+			       MOBILITY_DOMAIN_ID_LEN) != 0) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid mobility_domain '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "r1_key_holder") == 0) {
+		if (os_strlen(pos) != 2 * FT_R1KH_ID_LEN ||
+		    hexstr2bin(pos, bss->r1_key_holder, FT_R1KH_ID_LEN) != 0) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid r1_key_holder '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "r0_key_lifetime") == 0) {
+		bss->r0_key_lifetime = atoi(pos);
+	} else if (os_strcmp(buf, "reassociation_deadline") == 0) {
+		bss->reassociation_deadline = atoi(pos);
+	} else if (os_strcmp(buf, "r0kh") == 0) {
+		if (add_r0kh(bss, pos) < 0) {
+			wpa_printf(MSG_DEBUG, "Line %d: Invalid r0kh '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "r1kh") == 0) {
+		if (add_r1kh(bss, pos) < 0) {
+			wpa_printf(MSG_DEBUG, "Line %d: Invalid r1kh '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "pmk_r1_push") == 0) {
+		bss->pmk_r1_push = atoi(pos);
+	} else if (os_strcmp(buf, "ft_over_ds") == 0) {
+		bss->ft_over_ds = atoi(pos);
+#endif /* CONFIG_IEEE80211R */
+#ifndef CONFIG_NO_CTRL_IFACE
+	} else if (os_strcmp(buf, "ctrl_interface") == 0) {
+		os_free(bss->ctrl_interface);
+		bss->ctrl_interface = os_strdup(pos);
+	} else if (os_strcmp(buf, "ctrl_interface_group") == 0) {
+#ifndef CONFIG_NATIVE_WINDOWS
+		struct group *grp;
+		char *endp;
+		const char *group = pos;
+
+		grp = getgrnam(group);
+		if (grp) {
+			bss->ctrl_interface_gid = grp->gr_gid;
+			bss->ctrl_interface_gid_set = 1;
+			wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d (from group name '%s')",
+				   bss->ctrl_interface_gid, group);
+			return 0;
+		}
+
+		/* Group name not found - try to parse this as gid */
+		bss->ctrl_interface_gid = strtol(group, &endp, 10);
+		if (*group == '\0' || *endp != '\0') {
+			wpa_printf(MSG_DEBUG, "Line %d: Invalid group '%s'",
+				   line, group);
+			return 1;
+		}
+		bss->ctrl_interface_gid_set = 1;
+		wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d",
+			   bss->ctrl_interface_gid);
+#endif /* CONFIG_NATIVE_WINDOWS */
+#endif /* CONFIG_NO_CTRL_IFACE */
+#ifdef RADIUS_SERVER
+	} else if (os_strcmp(buf, "radius_server_clients") == 0) {
+		os_free(bss->radius_server_clients);
+		bss->radius_server_clients = os_strdup(pos);
+	} else if (os_strcmp(buf, "radius_server_auth_port") == 0) {
+		bss->radius_server_auth_port = atoi(pos);
+	} else if (os_strcmp(buf, "radius_server_acct_port") == 0) {
+		bss->radius_server_acct_port = atoi(pos);
+	} else if (os_strcmp(buf, "radius_server_ipv6") == 0) {
+		bss->radius_server_ipv6 = atoi(pos);
+#endif /* RADIUS_SERVER */
+	} else if (os_strcmp(buf, "use_pae_group_addr") == 0) {
+		bss->use_pae_group_addr = atoi(pos);
+	} else if (os_strcmp(buf, "hw_mode") == 0) {
+		if (os_strcmp(pos, "a") == 0)
+			conf->hw_mode = HOSTAPD_MODE_IEEE80211A;
+		else if (os_strcmp(pos, "b") == 0)
+			conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
+		else if (os_strcmp(pos, "g") == 0)
+			conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
+		else if (os_strcmp(pos, "ad") == 0)
+			conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
+		else if (os_strcmp(pos, "any") == 0)
+			conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY;
+		else {
+			wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wps_rf_bands") == 0) {
+		if (os_strcmp(pos, "ad") == 0)
+			bss->wps_rf_bands = WPS_RF_60GHZ;
+		else if (os_strcmp(pos, "a") == 0)
+			bss->wps_rf_bands = WPS_RF_50GHZ;
+		else if (os_strcmp(pos, "g") == 0 ||
+			 os_strcmp(pos, "b") == 0)
+			bss->wps_rf_bands = WPS_RF_24GHZ;
+		else if (os_strcmp(pos, "ag") == 0 ||
+			 os_strcmp(pos, "ga") == 0)
+			bss->wps_rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ;
+		else {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: unknown wps_rf_band '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "channel") == 0) {
+		if (os_strcmp(pos, "acs_survey") == 0) {
+#ifndef CONFIG_ACS
+			wpa_printf(MSG_ERROR, "Line %d: tries to enable ACS but CONFIG_ACS disabled",
+				   line);
+			return 1;
+#else /* CONFIG_ACS */
+			conf->acs = 1;
+			conf->channel = 0;
+#endif /* CONFIG_ACS */
+		} else {
+			conf->channel = atoi(pos);
+			conf->acs = conf->channel == 0;
+		}
+	} else if (os_strcmp(buf, "chanlist") == 0) {
+		if (hostapd_parse_chanlist(conf, pos)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "beacon_int") == 0) {
+		int val = atoi(pos);
+		/* MIB defines range as 1..65535, but very small values
+		 * cause problems with the current implementation.
+		 * Since it is unlikely that this small numbers are
+		 * useful in real life scenarios, do not allow beacon
+		 * period to be set below 15 TU. */
+		if (val < 15 || val > 65535) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid beacon_int %d (expected 15..65535)",
+				   line, val);
+			return 1;
+		}
+		conf->beacon_int = val;
+#ifdef CONFIG_ACS
+	} else if (os_strcmp(buf, "acs_num_scans") == 0) {
+		int val = atoi(pos);
+		if (val <= 0 || val > 100) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid acs_num_scans %d (expected 1..100)",
+				   line, val);
+			return 1;
+		}
+		conf->acs_num_scans = val;
+	} else if (os_strcmp(buf, "acs_chan_bias") == 0) {
+		if (hostapd_config_parse_acs_chan_bias(conf, pos)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid acs_chan_bias",
+				   line);
+			return -1;
+		}
+#endif /* CONFIG_ACS */
+	} else if (os_strcmp(buf, "dtim_period") == 0) {
+		bss->dtim_period = atoi(pos);
+		if (bss->dtim_period < 1 || bss->dtim_period > 255) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid dtim_period %d",
+				   line, bss->dtim_period);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "bss_load_update_period") == 0) {
+		bss->bss_load_update_period = atoi(pos);
+		if (bss->bss_load_update_period < 0 ||
+		    bss->bss_load_update_period > 100) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid bss_load_update_period %d",
+				   line, bss->bss_load_update_period);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "rts_threshold") == 0) {
+		conf->rts_threshold = atoi(pos);
+		if (conf->rts_threshold < -1 || conf->rts_threshold > 65535) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid rts_threshold %d",
+				   line, conf->rts_threshold);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "fragm_threshold") == 0) {
+		conf->fragm_threshold = atoi(pos);
+		if (conf->fragm_threshold == -1) {
+			/* allow a value of -1 */
+		} else if (conf->fragm_threshold < 256 ||
+			   conf->fragm_threshold > 2346) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid fragm_threshold %d",
+				   line, conf->fragm_threshold);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "send_probe_response") == 0) {
+		int val = atoi(pos);
+		if (val != 0 && val != 1) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid send_probe_response %d (expected 0 or 1)",
+				   line, val);
+			return 1;
+		}
+		conf->send_probe_response = val;
+	} else if (os_strcmp(buf, "supported_rates") == 0) {
+		if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "basic_rates") == 0) {
+		if (hostapd_parse_intlist(&conf->basic_rates, pos)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid rate list",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "preamble") == 0) {
+		if (atoi(pos))
+			conf->preamble = SHORT_PREAMBLE;
+		else
+			conf->preamble = LONG_PREAMBLE;
+	} else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) {
+		bss->ignore_broadcast_ssid = atoi(pos);
+	} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
+		bss->no_probe_resp_if_max_sta = atoi(pos);
+	} else if (os_strcmp(buf, "wep_default_key") == 0) {
+		bss->ssid.wep.idx = atoi(pos);
+		if (bss->ssid.wep.idx > 3) {
+			wpa_printf(MSG_ERROR,
+				   "Invalid wep_default_key index %d",
+				   bss->ssid.wep.idx);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wep_key0") == 0 ||
+		   os_strcmp(buf, "wep_key1") == 0 ||
+		   os_strcmp(buf, "wep_key2") == 0 ||
+		   os_strcmp(buf, "wep_key3") == 0) {
+		if (hostapd_config_read_wep(&bss->ssid.wep,
+					    buf[7] - '0', pos)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid WEP key '%s'",
+				   line, buf);
+			return 1;
+		}
+#ifndef CONFIG_NO_VLAN
+	} else if (os_strcmp(buf, "dynamic_vlan") == 0) {
+		bss->ssid.dynamic_vlan = atoi(pos);
+	} else if (os_strcmp(buf, "per_sta_vif") == 0) {
+		bss->ssid.per_sta_vif = atoi(pos);
+	} else if (os_strcmp(buf, "vlan_file") == 0) {
+		if (hostapd_config_read_vlan_file(bss, pos)) {
+			wpa_printf(MSG_ERROR, "Line %d: failed to read VLAN file '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "vlan_naming") == 0) {
+		bss->ssid.vlan_naming = atoi(pos);
+		if (bss->ssid.vlan_naming >= DYNAMIC_VLAN_NAMING_END ||
+		    bss->ssid.vlan_naming < 0) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid naming scheme %d",
+				   line, bss->ssid.vlan_naming);
+			return 1;
+		}
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+	} else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
+		os_free(bss->ssid.vlan_tagged_interface);
+		bss->ssid.vlan_tagged_interface = os_strdup(pos);
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+#endif /* CONFIG_NO_VLAN */
+	} else if (os_strcmp(buf, "ap_table_max_size") == 0) {
+		conf->ap_table_max_size = atoi(pos);
+	} else if (os_strcmp(buf, "ap_table_expiration_time") == 0) {
+		conf->ap_table_expiration_time = atoi(pos);
+	} else if (os_strncmp(buf, "tx_queue_", 9) == 0) {
+		if (hostapd_config_tx_queue(conf, buf, pos)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wme_enabled") == 0 ||
+		   os_strcmp(buf, "wmm_enabled") == 0) {
+		bss->wmm_enabled = atoi(pos);
+	} else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) {
+		bss->wmm_uapsd = atoi(pos);
+	} else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
+		   os_strncmp(buf, "wmm_ac_", 7) == 0) {
+		if (hostapd_config_wmm_ac(conf->wmm_ac_params, buf, pos)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid WMM ac item",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "bss") == 0) {
+		if (hostapd_config_bss(conf, pos)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid bss item",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "bssid") == 0) {
+		if (hwaddr_aton(pos, bss->bssid)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid bssid item",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "use_driver_iface_addr") == 0) {
+		conf->use_driver_iface_addr = atoi(pos);
+#ifdef CONFIG_IEEE80211W
+	} else if (os_strcmp(buf, "ieee80211w") == 0) {
+		bss->ieee80211w = atoi(pos);
+	} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
+		if (os_strcmp(pos, "AES-128-CMAC") == 0) {
+			bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
+		} else if (os_strcmp(pos, "BIP-GMAC-128") == 0) {
+			bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_128;
+		} else if (os_strcmp(pos, "BIP-GMAC-256") == 0) {
+			bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_256;
+		} else if (os_strcmp(pos, "BIP-CMAC-256") == 0) {
+			bss->group_mgmt_cipher = WPA_CIPHER_BIP_CMAC_256;
+		} else {
+			wpa_printf(MSG_ERROR, "Line %d: invalid group_mgmt_cipher: %s",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
+		bss->assoc_sa_query_max_timeout = atoi(pos);
+		if (bss->assoc_sa_query_max_timeout == 0) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_max_timeout",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "assoc_sa_query_retry_timeout") == 0) {
+		bss->assoc_sa_query_retry_timeout = atoi(pos);
+		if (bss->assoc_sa_query_retry_timeout == 0) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid assoc_sa_query_retry_timeout",
+				   line);
+			return 1;
+		}
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_IEEE80211N
+	} else if (os_strcmp(buf, "ieee80211n") == 0) {
+		conf->ieee80211n = atoi(pos);
+	} else if (os_strcmp(buf, "ht_capab") == 0) {
+		if (hostapd_config_ht_capab(conf, pos) < 0) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid ht_capab",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "require_ht") == 0) {
+		conf->require_ht = atoi(pos);
+	} else if (os_strcmp(buf, "obss_interval") == 0) {
+		conf->obss_interval = atoi(pos);
+#endif /* CONFIG_IEEE80211N */
+#ifdef CONFIG_IEEE80211AC
+	} else if (os_strcmp(buf, "ieee80211ac") == 0) {
+		conf->ieee80211ac = atoi(pos);
+	} else if (os_strcmp(buf, "vht_capab") == 0) {
+		if (hostapd_config_vht_capab(conf, pos) < 0) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid vht_capab",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "require_vht") == 0) {
+		conf->require_vht = atoi(pos);
+	} else if (os_strcmp(buf, "vht_oper_chwidth") == 0) {
+		conf->vht_oper_chwidth = atoi(pos);
+	} else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) {
+		conf->vht_oper_centr_freq_seg0_idx = atoi(pos);
+	} else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) {
+		conf->vht_oper_centr_freq_seg1_idx = atoi(pos);
+	} else if (os_strcmp(buf, "vendor_vht") == 0) {
+		bss->vendor_vht = atoi(pos);
+	} else if (os_strcmp(buf, "use_sta_nsts") == 0) {
+		bss->use_sta_nsts = atoi(pos);
+#endif /* CONFIG_IEEE80211AC */
+	} else if (os_strcmp(buf, "max_listen_interval") == 0) {
+		bss->max_listen_interval = atoi(pos);
+	} else if (os_strcmp(buf, "disable_pmksa_caching") == 0) {
+		bss->disable_pmksa_caching = atoi(pos);
+	} else if (os_strcmp(buf, "okc") == 0) {
+		bss->okc = atoi(pos);
+#ifdef CONFIG_WPS
+	} else if (os_strcmp(buf, "wps_state") == 0) {
+		bss->wps_state = atoi(pos);
+		if (bss->wps_state < 0 || bss->wps_state > 2) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid wps_state",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wps_independent") == 0) {
+		bss->wps_independent = atoi(pos);
+	} else if (os_strcmp(buf, "ap_setup_locked") == 0) {
+		bss->ap_setup_locked = atoi(pos);
+	} else if (os_strcmp(buf, "uuid") == 0) {
+		if (uuid_str2bin(pos, bss->uuid)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid UUID", line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wps_pin_requests") == 0) {
+		os_free(bss->wps_pin_requests);
+		bss->wps_pin_requests = os_strdup(pos);
+	} else if (os_strcmp(buf, "device_name") == 0) {
+		if (os_strlen(pos) > WPS_DEV_NAME_MAX_LEN) {
+			wpa_printf(MSG_ERROR, "Line %d: Too long "
+				   "device_name", line);
+			return 1;
+		}
+		os_free(bss->device_name);
+		bss->device_name = os_strdup(pos);
+	} else if (os_strcmp(buf, "manufacturer") == 0) {
+		if (os_strlen(pos) > 64) {
+			wpa_printf(MSG_ERROR, "Line %d: Too long manufacturer",
+				   line);
+			return 1;
+		}
+		os_free(bss->manufacturer);
+		bss->manufacturer = os_strdup(pos);
+	} else if (os_strcmp(buf, "model_name") == 0) {
+		if (os_strlen(pos) > 32) {
+			wpa_printf(MSG_ERROR, "Line %d: Too long model_name",
+				   line);
+			return 1;
+		}
+		os_free(bss->model_name);
+		bss->model_name = os_strdup(pos);
+	} else if (os_strcmp(buf, "model_number") == 0) {
+		if (os_strlen(pos) > 32) {
+			wpa_printf(MSG_ERROR, "Line %d: Too long model_number",
+				   line);
+			return 1;
+		}
+		os_free(bss->model_number);
+		bss->model_number = os_strdup(pos);
+	} else if (os_strcmp(buf, "serial_number") == 0) {
+		if (os_strlen(pos) > 32) {
+			wpa_printf(MSG_ERROR, "Line %d: Too long serial_number",
+				   line);
+			return 1;
+		}
+		os_free(bss->serial_number);
+		bss->serial_number = os_strdup(pos);
+	} else if (os_strcmp(buf, "device_type") == 0) {
+		if (wps_dev_type_str2bin(pos, bss->device_type))
+			return 1;
+	} else if (os_strcmp(buf, "config_methods") == 0) {
+		os_free(bss->config_methods);
+		bss->config_methods = os_strdup(pos);
+	} else if (os_strcmp(buf, "os_version") == 0) {
+		if (hexstr2bin(pos, bss->os_version, 4)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid os_version",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "ap_pin") == 0) {
+		os_free(bss->ap_pin);
+		bss->ap_pin = os_strdup(pos);
+	} else if (os_strcmp(buf, "skip_cred_build") == 0) {
+		bss->skip_cred_build = atoi(pos);
+	} else if (os_strcmp(buf, "extra_cred") == 0) {
+		os_free(bss->extra_cred);
+		bss->extra_cred = (u8 *) os_readfile(pos, &bss->extra_cred_len);
+		if (bss->extra_cred == NULL) {
+			wpa_printf(MSG_ERROR, "Line %d: could not read Credentials from '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "wps_cred_processing") == 0) {
+		bss->wps_cred_processing = atoi(pos);
+	} else if (os_strcmp(buf, "ap_settings") == 0) {
+		os_free(bss->ap_settings);
+		bss->ap_settings =
+			(u8 *) os_readfile(pos, &bss->ap_settings_len);
+		if (bss->ap_settings == NULL) {
+			wpa_printf(MSG_ERROR, "Line %d: could not read AP Settings from '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "upnp_iface") == 0) {
+		os_free(bss->upnp_iface);
+		bss->upnp_iface = os_strdup(pos);
+	} else if (os_strcmp(buf, "friendly_name") == 0) {
+		os_free(bss->friendly_name);
+		bss->friendly_name = os_strdup(pos);
+	} else if (os_strcmp(buf, "manufacturer_url") == 0) {
+		os_free(bss->manufacturer_url);
+		bss->manufacturer_url = os_strdup(pos);
+	} else if (os_strcmp(buf, "model_description") == 0) {
+		os_free(bss->model_description);
+		bss->model_description = os_strdup(pos);
+	} else if (os_strcmp(buf, "model_url") == 0) {
+		os_free(bss->model_url);
+		bss->model_url = os_strdup(pos);
+	} else if (os_strcmp(buf, "upc") == 0) {
+		os_free(bss->upc);
+		bss->upc = os_strdup(pos);
+	} else if (os_strcmp(buf, "pbc_in_m1") == 0) {
+		bss->pbc_in_m1 = atoi(pos);
+	} else if (os_strcmp(buf, "server_id") == 0) {
+		os_free(bss->server_id);
+		bss->server_id = os_strdup(pos);
+#ifdef CONFIG_WPS_NFC
+	} else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) {
+		bss->wps_nfc_dev_pw_id = atoi(pos);
+		if (bss->wps_nfc_dev_pw_id < 0x10 ||
+		    bss->wps_nfc_dev_pw_id > 0xffff) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid wps_nfc_dev_pw_id value",
+				   line);
+			return 1;
+		}
+		bss->wps_nfc_pw_from_config = 1;
+	} else if (os_strcmp(buf, "wps_nfc_dh_pubkey") == 0) {
+		wpabuf_free(bss->wps_nfc_dh_pubkey);
+		bss->wps_nfc_dh_pubkey = wpabuf_parse_bin(pos);
+		bss->wps_nfc_pw_from_config = 1;
+	} else if (os_strcmp(buf, "wps_nfc_dh_privkey") == 0) {
+		wpabuf_free(bss->wps_nfc_dh_privkey);
+		bss->wps_nfc_dh_privkey = wpabuf_parse_bin(pos);
+		bss->wps_nfc_pw_from_config = 1;
+	} else if (os_strcmp(buf, "wps_nfc_dev_pw") == 0) {
+		wpabuf_free(bss->wps_nfc_dev_pw);
+		bss->wps_nfc_dev_pw = wpabuf_parse_bin(pos);
+		bss->wps_nfc_pw_from_config = 1;
+#endif /* CONFIG_WPS_NFC */
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P_MANAGER
+	} else if (os_strcmp(buf, "manage_p2p") == 0) {
+		if (atoi(pos))
+			bss->p2p |= P2P_MANAGE;
+		else
+			bss->p2p &= ~P2P_MANAGE;
+	} else if (os_strcmp(buf, "allow_cross_connection") == 0) {
+		if (atoi(pos))
+			bss->p2p |= P2P_ALLOW_CROSS_CONNECTION;
+		else
+			bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
+#endif /* CONFIG_P2P_MANAGER */
+	} else if (os_strcmp(buf, "disassoc_low_ack") == 0) {
+		bss->disassoc_low_ack = atoi(pos);
+	} else if (os_strcmp(buf, "tdls_prohibit") == 0) {
+		if (atoi(pos))
+			bss->tdls |= TDLS_PROHIBIT;
+		else
+			bss->tdls &= ~TDLS_PROHIBIT;
+	} else if (os_strcmp(buf, "tdls_prohibit_chan_switch") == 0) {
+		if (atoi(pos))
+			bss->tdls |= TDLS_PROHIBIT_CHAN_SWITCH;
+		else
+			bss->tdls &= ~TDLS_PROHIBIT_CHAN_SWITCH;
+#ifdef CONFIG_RSN_TESTING
+	} else if (os_strcmp(buf, "rsn_testing") == 0) {
+		extern int rsn_testing;
+		rsn_testing = atoi(pos);
+#endif /* CONFIG_RSN_TESTING */
+	} else if (os_strcmp(buf, "time_advertisement") == 0) {
+		bss->time_advertisement = atoi(pos);
+	} else if (os_strcmp(buf, "time_zone") == 0) {
+		size_t tz_len = os_strlen(pos);
+		if (tz_len < 4 || tz_len > 255) {
+			wpa_printf(MSG_DEBUG, "Line %d: invalid time_zone",
+				   line);
+			return 1;
+		}
+		os_free(bss->time_zone);
+		bss->time_zone = os_strdup(pos);
+		if (bss->time_zone == NULL)
+			return 1;
+#ifdef CONFIG_WNM
+	} else if (os_strcmp(buf, "wnm_sleep_mode") == 0) {
+		bss->wnm_sleep_mode = atoi(pos);
+	} else if (os_strcmp(buf, "bss_transition") == 0) {
+		bss->bss_transition = atoi(pos);
+#endif /* CONFIG_WNM */
+#ifdef CONFIG_INTERWORKING
+	} else if (os_strcmp(buf, "interworking") == 0) {
+		bss->interworking = atoi(pos);
+	} else if (os_strcmp(buf, "access_network_type") == 0) {
+		bss->access_network_type = atoi(pos);
+		if (bss->access_network_type < 0 ||
+		    bss->access_network_type > 15) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid access_network_type",
+				   line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "internet") == 0) {
+		bss->internet = atoi(pos);
+	} else if (os_strcmp(buf, "asra") == 0) {
+		bss->asra = atoi(pos);
+	} else if (os_strcmp(buf, "esr") == 0) {
+		bss->esr = atoi(pos);
+	} else if (os_strcmp(buf, "uesa") == 0) {
+		bss->uesa = atoi(pos);
+	} else if (os_strcmp(buf, "venue_group") == 0) {
+		bss->venue_group = atoi(pos);
+		bss->venue_info_set = 1;
+	} else if (os_strcmp(buf, "venue_type") == 0) {
+		bss->venue_type = atoi(pos);
+		bss->venue_info_set = 1;
+	} else if (os_strcmp(buf, "hessid") == 0) {
+		if (hwaddr_aton(pos, bss->hessid)) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid hessid", line);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "roaming_consortium") == 0) {
+		if (parse_roaming_consortium(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "venue_name") == 0) {
+		if (parse_venue_name(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "network_auth_type") == 0) {
+		u8 auth_type;
+		u16 redirect_url_len;
+		if (hexstr2bin(pos, &auth_type, 1)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid network_auth_type '%s'",
+				   line, pos);
+			return 1;
+		}
+		if (auth_type == 0 || auth_type == 2)
+			redirect_url_len = os_strlen(pos + 2);
+		else
+			redirect_url_len = 0;
+		os_free(bss->network_auth_type);
+		bss->network_auth_type = os_malloc(redirect_url_len + 3 + 1);
+		if (bss->network_auth_type == NULL)
+			return 1;
+		*bss->network_auth_type = auth_type;
+		WPA_PUT_LE16(bss->network_auth_type + 1, redirect_url_len);
+		if (redirect_url_len)
+			os_memcpy(bss->network_auth_type + 3, pos + 2,
+				  redirect_url_len);
+		bss->network_auth_type_len = 3 + redirect_url_len;
+	} else if (os_strcmp(buf, "ipaddr_type_availability") == 0) {
+		if (hexstr2bin(pos, &bss->ipaddr_type_availability, 1)) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid ipaddr_type_availability '%s'",
+				   line, pos);
+			bss->ipaddr_type_configured = 0;
+			return 1;
+		}
+		bss->ipaddr_type_configured = 1;
+	} else if (os_strcmp(buf, "domain_name") == 0) {
+		int j, num_domains, domain_len, domain_list_len = 0;
+		char *tok_start, *tok_prev;
+		u8 *domain_list, *domain_ptr;
+
+		domain_list_len = os_strlen(pos) + 1;
+		domain_list = os_malloc(domain_list_len);
+		if (domain_list == NULL)
+			return 1;
+
+		domain_ptr = domain_list;
+		tok_prev = pos;
+		num_domains = 1;
+		while ((tok_prev = os_strchr(tok_prev, ','))) {
+			num_domains++;
+			tok_prev++;
+		}
+		tok_prev = pos;
+		for (j = 0; j < num_domains; j++) {
+			tok_start = os_strchr(tok_prev, ',');
+			if (tok_start) {
+				domain_len = tok_start - tok_prev;
+				*domain_ptr = domain_len;
+				os_memcpy(domain_ptr + 1, tok_prev, domain_len);
+				domain_ptr += domain_len + 1;
+				tok_prev = ++tok_start;
+			} else {
+				domain_len = os_strlen(tok_prev);
+				*domain_ptr = domain_len;
+				os_memcpy(domain_ptr + 1, tok_prev, domain_len);
+				domain_ptr += domain_len + 1;
+			}
+		}
+
+		os_free(bss->domain_name);
+		bss->domain_name = domain_list;
+		bss->domain_name_len = domain_list_len;
+	} else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) {
+		if (parse_3gpp_cell_net(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "nai_realm") == 0) {
+		if (parse_nai_realm(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "anqp_elem") == 0) {
+		if (parse_anqp_elem(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "gas_frag_limit") == 0) {
+		bss->gas_frag_limit = atoi(pos);
+	} else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
+		bss->gas_comeback_delay = atoi(pos);
+	} else if (os_strcmp(buf, "qos_map_set") == 0) {
+		if (parse_qos_map_set(bss, pos, line) < 0)
+			return 1;
+#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_RADIUS_TEST
+	} else if (os_strcmp(buf, "dump_msk_file") == 0) {
+		os_free(bss->dump_msk_file);
+		bss->dump_msk_file = os_strdup(pos);
+#endif /* CONFIG_RADIUS_TEST */
+#ifdef CONFIG_PROXYARP
+	} else if (os_strcmp(buf, "proxy_arp") == 0) {
+		bss->proxy_arp = atoi(pos);
+#endif /* CONFIG_PROXYARP */
+#ifdef CONFIG_HS20
+	} else if (os_strcmp(buf, "hs20") == 0) {
+		bss->hs20 = atoi(pos);
+	} else if (os_strcmp(buf, "disable_dgaf") == 0) {
+		bss->disable_dgaf = atoi(pos);
+	} else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) {
+		bss->na_mcast_to_ucast = atoi(pos);
+	} else if (os_strcmp(buf, "osen") == 0) {
+		bss->osen = atoi(pos);
+	} else if (os_strcmp(buf, "anqp_domain_id") == 0) {
+		bss->anqp_domain_id = atoi(pos);
+	} else if (os_strcmp(buf, "hs20_deauth_req_timeout") == 0) {
+		bss->hs20_deauth_req_timeout = atoi(pos);
+	} else if (os_strcmp(buf, "hs20_oper_friendly_name") == 0) {
+		if (hs20_parse_oper_friendly_name(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "hs20_wan_metrics") == 0) {
+		if (hs20_parse_wan_metrics(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "hs20_conn_capab") == 0) {
+		if (hs20_parse_conn_capab(bss, pos, line) < 0) {
+			return 1;
+		}
+	} else if (os_strcmp(buf, "hs20_operating_class") == 0) {
+		u8 *oper_class;
+		size_t oper_class_len;
+		oper_class_len = os_strlen(pos);
+		if (oper_class_len < 2 || (oper_class_len & 0x01)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid hs20_operating_class '%s'",
+				   line, pos);
+			return 1;
+		}
+		oper_class_len /= 2;
+		oper_class = os_malloc(oper_class_len);
+		if (oper_class == NULL)
+			return 1;
+		if (hexstr2bin(pos, oper_class, oper_class_len)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid hs20_operating_class '%s'",
+				   line, pos);
+			os_free(oper_class);
+			return 1;
+		}
+		os_free(bss->hs20_operating_class);
+		bss->hs20_operating_class = oper_class;
+		bss->hs20_operating_class_len = oper_class_len;
+	} else if (os_strcmp(buf, "hs20_icon") == 0) {
+		if (hs20_parse_icon(bss, pos) < 0) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_icon '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "osu_ssid") == 0) {
+		if (hs20_parse_osu_ssid(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "osu_server_uri") == 0) {
+		if (hs20_parse_osu_server_uri(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "osu_friendly_name") == 0) {
+		if (hs20_parse_osu_friendly_name(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "osu_nai") == 0) {
+		if (hs20_parse_osu_nai(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "osu_method_list") == 0) {
+		if (hs20_parse_osu_method_list(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "osu_icon") == 0) {
+		if (hs20_parse_osu_icon(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "osu_service_desc") == 0) {
+		if (hs20_parse_osu_service_desc(bss, pos, line) < 0)
+			return 1;
+	} else if (os_strcmp(buf, "subscr_remediation_url") == 0) {
+		os_free(bss->subscr_remediation_url);
+		bss->subscr_remediation_url = os_strdup(pos);
+	} else if (os_strcmp(buf, "subscr_remediation_method") == 0) {
+		bss->subscr_remediation_method = atoi(pos);
+#endif /* CONFIG_HS20 */
+#ifdef CONFIG_MBO
+	} else if (os_strcmp(buf, "mbo") == 0) {
+		bss->mbo_enabled = atoi(pos);
+#endif /* CONFIG_MBO */
+#ifdef CONFIG_TESTING_OPTIONS
+#define PARSE_TEST_PROBABILITY(_val)				\
+	} else if (os_strcmp(buf, #_val) == 0) {		\
+		char *end;					\
+								\
+		conf->_val = strtod(pos, &end);			\
+		if (*end || conf->_val < 0.0 ||			\
+		    conf->_val > 1.0) {				\
+			wpa_printf(MSG_ERROR,			\
+				   "Line %d: Invalid value '%s'", \
+				   line, pos);			\
+			return 1;				\
+		}
+	PARSE_TEST_PROBABILITY(ignore_probe_probability)
+	PARSE_TEST_PROBABILITY(ignore_auth_probability)
+	PARSE_TEST_PROBABILITY(ignore_assoc_probability)
+	PARSE_TEST_PROBABILITY(ignore_reassoc_probability)
+	PARSE_TEST_PROBABILITY(corrupt_gtk_rekey_mic_probability)
+	} else if (os_strcmp(buf, "ecsa_ie_only") == 0) {
+		conf->ecsa_ie_only = atoi(pos);
+	} else if (os_strcmp(buf, "bss_load_test") == 0) {
+		WPA_PUT_LE16(bss->bss_load_test, atoi(pos));
+		pos = os_strchr(pos, ':');
+		if (pos == NULL) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
+				   line);
+			return 1;
+		}
+		pos++;
+		bss->bss_load_test[2] = atoi(pos);
+		pos = os_strchr(pos, ':');
+		if (pos == NULL) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid bss_load_test",
+				   line);
+			return 1;
+		}
+		pos++;
+		WPA_PUT_LE16(&bss->bss_load_test[3], atoi(pos));
+		bss->bss_load_test_set = 1;
+	} else if (os_strcmp(buf, "radio_measurements") == 0) {
+		/*
+		 * DEPRECATED: This parameter will be removed in the future.
+		 * Use rrm_neighbor_report instead.
+		 */
+		int val = atoi(pos);
+
+		if (val & BIT(0))
+			bss->radio_measurements[0] |=
+				WLAN_RRM_CAPS_NEIGHBOR_REPORT;
+	} else if (os_strcmp(buf, "own_ie_override") == 0) {
+		struct wpabuf *tmp;
+		size_t len = os_strlen(pos) / 2;
+
+		tmp = wpabuf_alloc(len);
+		if (!tmp)
+			return 1;
+
+		if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
+			wpabuf_free(tmp);
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid own_ie_override '%s'",
+				   line, pos);
+			return 1;
+		}
+
+		wpabuf_free(bss->own_ie_override);
+		bss->own_ie_override = tmp;
+#endif /* CONFIG_TESTING_OPTIONS */
+	} else if (os_strcmp(buf, "vendor_elements") == 0) {
+		if (parse_wpabuf_hex(line, buf, &bss->vendor_elements, pos))
+			return 1;
+	} else if (os_strcmp(buf, "assocresp_elements") == 0) {
+		if (parse_wpabuf_hex(line, buf, &bss->assocresp_elements, pos))
+			return 1;
+	} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
+		bss->sae_anti_clogging_threshold = atoi(pos);
+	} else if (os_strcmp(buf, "sae_groups") == 0) {
+		if (hostapd_parse_intlist(&bss->sae_groups, pos)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid sae_groups value '%s'",
+				   line, pos);
+			return 1;
+		}
+	} else if (os_strcmp(buf, "local_pwr_constraint") == 0) {
+		int val = atoi(pos);
+		if (val < 0 || val > 255) {
+			wpa_printf(MSG_ERROR, "Line %d: Invalid local_pwr_constraint %d (expected 0..255)",
+				   line, val);
+			return 1;
+		}
+		conf->local_pwr_constraint = val;
+	} else if (os_strcmp(buf, "spectrum_mgmt_required") == 0) {
+		conf->spectrum_mgmt_required = atoi(pos);
+	} else if (os_strcmp(buf, "wowlan_triggers") == 0) {
+		os_free(bss->wowlan_triggers);
+		bss->wowlan_triggers = os_strdup(pos);
+#ifdef CONFIG_FST
+	} else if (os_strcmp(buf, "fst_group_id") == 0) {
+		size_t len = os_strlen(pos);
+
+		if (!len || len >= sizeof(conf->fst_cfg.group_id)) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid fst_group_id value '%s'",
+				   line, pos);
+			return 1;
+		}
+
+		if (conf->fst_cfg.group_id[0]) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Duplicate fst_group value '%s'",
+				   line, pos);
+			return 1;
+		}
+
+		os_strlcpy(conf->fst_cfg.group_id, pos,
+			   sizeof(conf->fst_cfg.group_id));
+	} else if (os_strcmp(buf, "fst_priority") == 0) {
+		char *endp;
+		long int val;
+
+		if (!*pos) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: fst_priority value not supplied (expected 1..%u)",
+				   line, FST_MAX_PRIO_VALUE);
+			return -1;
+		}
+
+		val = strtol(pos, &endp, 0);
+		if (*endp || val < 1 || val > FST_MAX_PRIO_VALUE) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid fst_priority %ld (%s) (expected 1..%u)",
+				   line, val, pos, FST_MAX_PRIO_VALUE);
+			return 1;
+		}
+		conf->fst_cfg.priority = (u8) val;
+	} else if (os_strcmp(buf, "fst_llt") == 0) {
+		char *endp;
+		long int val;
+
+		if (!*pos) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: fst_llt value not supplied (expected 1..%u)",
+				   line, FST_MAX_LLT_MS);
+			return -1;
+		}
+		val = strtol(pos, &endp, 0);
+		if (*endp || val < 1 ||
+		    (unsigned long int) val > FST_MAX_LLT_MS) {
+			wpa_printf(MSG_ERROR,
+				   "Line %d: Invalid fst_llt %ld (%s) (expected 1..%u)",
+				   line, val, pos, FST_MAX_LLT_MS);
+			return 1;
+		}
+		conf->fst_cfg.llt = (u32) val;
+#endif /* CONFIG_FST */
+	} else if (os_strcmp(buf, "track_sta_max_num") == 0) {
+		conf->track_sta_max_num = atoi(pos);
+	} else if (os_strcmp(buf, "track_sta_max_age") == 0) {
+		conf->track_sta_max_age = atoi(pos);
+	} else if (os_strcmp(buf, "no_probe_resp_if_seen_on") == 0) {
+		os_free(bss->no_probe_resp_if_seen_on);
+		bss->no_probe_resp_if_seen_on = os_strdup(pos);
+	} else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) {
+		os_free(bss->no_auth_if_seen_on);
+		bss->no_auth_if_seen_on = os_strdup(pos);
+	} else if (os_strcmp(buf, "lci") == 0) {
+		wpabuf_free(conf->lci);
+		conf->lci = wpabuf_parse_bin(pos);
+	} else if (os_strcmp(buf, "civic") == 0) {
+		wpabuf_free(conf->civic);
+		conf->civic = wpabuf_parse_bin(pos);
+	} else if (os_strcmp(buf, "rrm_neighbor_report") == 0) {
+		if (atoi(pos))
+			bss->radio_measurements[0] |=
+				WLAN_RRM_CAPS_NEIGHBOR_REPORT;
+	} else if (os_strcmp(buf, "gas_address3") == 0) {
+		bss->gas_address3 = atoi(pos);
+	} else if (os_strcmp(buf, "ftm_responder") == 0) {
+		bss->ftm_responder = atoi(pos);
+	} else if (os_strcmp(buf, "ftm_initiator") == 0) {
+		bss->ftm_initiator = atoi(pos);
+	} else {
+		wpa_printf(MSG_ERROR,
+			   "Line %d: unknown configuration item '%s'",
+			   line, buf);
+		return 1;
+	}
+
+	return 0;
+}
+
+
+/**
+ * hostapd_config_read - Read and parse a configuration file
+ * @fname: Configuration file name (including path, if needed)
+ * Returns: Allocated configuration data structure
+ */
+struct hostapd_config * hostapd_config_read(const char *fname)
+{
+	struct hostapd_config *conf;
+	FILE *f;
+	char buf[4096], *pos;
+	int line = 0;
+	int errors = 0;
+	size_t i;
+
+	f = fopen(fname, "r");
+	if (f == NULL) {
+		wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
+			   "for reading.", fname);
+		return NULL;
+	}
+
+	conf = hostapd_config_defaults();
+	if (conf == NULL) {
+		fclose(f);
+		return NULL;
+	}
+
+	/* set default driver based on configuration */
+	conf->driver = wpa_drivers[0];
+	if (conf->driver == NULL) {
+		wpa_printf(MSG_ERROR, "No driver wrappers registered!");
+		hostapd_config_free(conf);
+		fclose(f);
+		return NULL;
+	}
+
+	conf->last_bss = conf->bss[0];
+
+	while (fgets(buf, sizeof(buf), f)) {
+		struct hostapd_bss_config *bss;
+
+		bss = conf->last_bss;
+		line++;
+
+		if (buf[0] == '#')
+			continue;
+		pos = buf;
+		while (*pos != '\0') {
+			if (*pos == '\n') {
+				*pos = '\0';
+				break;
+			}
+			pos++;
+		}
+		if (buf[0] == '\0')
+			continue;
+
+		pos = os_strchr(buf, '=');
+		if (pos == NULL) {
+			wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
+				   line, buf);
+			errors++;
+			continue;
+		}
+		*pos = '\0';
+		pos++;
+		errors += hostapd_config_fill(conf, bss, buf, pos, line);
+	}
+
+	fclose(f);
+
+	for (i = 0; i < conf->num_bss; i++)
+		hostapd_set_security_params(conf->bss[i], 1);
+
+	if (hostapd_config_check(conf, 1))
+		errors++;
+
+#ifndef WPA_IGNORE_CONFIG_ERRORS
+	if (errors) {
+		wpa_printf(MSG_ERROR, "%d errors found in configuration file "
+			   "'%s'", errors, fname);
+		hostapd_config_free(conf);
+		conf = NULL;
+	}
+#endif /* WPA_IGNORE_CONFIG_ERRORS */
+
+	return conf;
+}
+
+
+int hostapd_set_iface(struct hostapd_config *conf,
+		      struct hostapd_bss_config *bss, const char *field,
+		      char *value)
+{
+	int errors;
+	size_t i;
+
+	errors = hostapd_config_fill(conf, bss, field, value, 0);
+	if (errors) {
+		wpa_printf(MSG_INFO, "Failed to set configuration field '%s' "
+			   "to value '%s'", field, value);
+		return -1;
+	}
+
+	for (i = 0; i < conf->num_bss; i++)
+		hostapd_set_security_params(conf->bss[i], 0);
+
+	if (hostapd_config_check(conf, 0)) {
+		wpa_printf(MSG_ERROR, "Configuration check failed");
+		return -1;
+	}
+
+	return 0;
+}

+ 29 - 0
EVSE/GPL/hostapd-2.6/hostapd/config_file.d

@@ -0,0 +1,29 @@
+config_file.o: config_file.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/uuid.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_common/eap_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap_methods.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius_client.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/wpa_auth.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/eapol_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/vlan.h \
+ config_file.h

+ 17 - 0
EVSE/GPL/hostapd-2.6/hostapd/config_file.h

@@ -0,0 +1,17 @@
+/*
+ * hostapd / Configuration file parser
+ * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef CONFIG_FILE_H
+#define CONFIG_FILE_H
+
+struct hostapd_config * hostapd_config_read(const char *fname);
+int hostapd_set_iface(struct hostapd_config *conf,
+		      struct hostapd_bss_config *bss, const char *field,
+		      char *value);
+
+#endif /* CONFIG_FILE_H */

+ 3755 - 0
EVSE/GPL/hostapd-2.6/hostapd/ctrl_iface.c

@@ -0,0 +1,3755 @@
+/*
+ * hostapd / UNIX domain socket -based control interface
+ * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#ifndef CONFIG_NATIVE_WINDOWS
+
+#ifdef CONFIG_TESTING_OPTIONS
+#include <net/ethernet.h>
+#include <netinet/ip.h>
+#endif /* CONFIG_TESTING_OPTIONS */
+
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <stddef.h>
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+#include <netdb.h>
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/module_tests.h"
+#include "common/version.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ctrl_iface_common.h"
+#include "crypto/tls.h"
+#include "drivers/driver.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "radius/radius_client.h"
+#include "radius/radius_server.h"
+#include "l2_packet/l2_packet.h"
+#include "ap/hostapd.h"
+#include "ap/ap_config.h"
+#include "ap/ieee802_1x.h"
+#include "ap/wpa_auth.h"
+#include "ap/ieee802_11.h"
+#include "ap/sta_info.h"
+#include "ap/wps_hostapd.h"
+#include "ap/ctrl_iface_ap.h"
+#include "ap/ap_drv_ops.h"
+#include "ap/hs20.h"
+#include "ap/wnm_ap.h"
+#include "ap/wpa_auth.h"
+#include "ap/beacon.h"
+#include "ap/neighbor_db.h"
+#include "ap/rrm.h"
+#include "wps/wps_defs.h"
+#include "wps/wps.h"
+#include "fst/fst_ctrl_iface.h"
+#include "config_file.h"
+#include "ctrl_iface.h"
+
+
+#define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+#define COOKIE_LEN 8
+static unsigned char cookie[COOKIE_LEN];
+static unsigned char gcookie[COOKIE_LEN];
+#define HOSTAPD_CTRL_IFACE_PORT		8877
+#define HOSTAPD_CTRL_IFACE_PORT_LIMIT	50
+#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT		8878
+#define HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT	50
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+				    enum wpa_msg_type type,
+				    const char *buf, size_t len);
+
+
+static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
+				     struct sockaddr_storage *from,
+				     socklen_t fromlen)
+{
+	return ctrl_iface_attach(&hapd->ctrl_dst, from, fromlen);
+}
+
+
+static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
+				     struct sockaddr_storage *from,
+				     socklen_t fromlen)
+{
+	return ctrl_iface_detach(&hapd->ctrl_dst, from, fromlen);
+}
+
+
+static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
+				    struct sockaddr_storage *from,
+				    socklen_t fromlen,
+				    char *level)
+{
+	return ctrl_iface_level(&hapd->ctrl_dst, from, fromlen, level);
+}
+
+
+static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd,
+				      const char *txtaddr)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+
+	wpa_printf(MSG_DEBUG, "CTRL_IFACE NEW_STA %s", txtaddr);
+
+	if (hwaddr_aton(txtaddr, addr))
+		return -1;
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "Add new STA " MACSTR " based on ctrl_iface "
+		   "notification", MAC2STR(addr));
+	sta = ap_sta_add(hapd, addr);
+	if (sta == NULL)
+		return -1;
+
+	hostapd_new_assoc_sta(hapd, sta, 0);
+	return 0;
+}
+
+
+#ifdef CONFIG_IEEE80211W
+#ifdef NEED_AP_MLME
+static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
+				       const char *txtaddr)
+{
+	u8 addr[ETH_ALEN];
+	u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
+
+	wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr);
+
+	if (hwaddr_aton(txtaddr, addr) ||
+	    os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0)
+		return -1;
+
+	ieee802_11_send_sa_query_req(hapd, addr, trans_id);
+
+	return 0;
+}
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_IEEE80211W */
+
+
+#ifdef CONFIG_WPS
+static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt)
+{
+	char *pin = os_strchr(txt, ' ');
+	char *timeout_txt;
+	int timeout;
+	u8 addr_buf[ETH_ALEN], *addr = NULL;
+	char *pos;
+
+	if (pin == NULL)
+		return -1;
+	*pin++ = '\0';
+
+	timeout_txt = os_strchr(pin, ' ');
+	if (timeout_txt) {
+		*timeout_txt++ = '\0';
+		timeout = atoi(timeout_txt);
+		pos = os_strchr(timeout_txt, ' ');
+		if (pos) {
+			*pos++ = '\0';
+			if (hwaddr_aton(pos, addr_buf) == 0)
+				addr = addr_buf;
+		}
+	} else
+		timeout = 0;
+
+	return hostapd_wps_add_pin(hapd, addr, txt, pin, timeout);
+}
+
+
+static int hostapd_ctrl_iface_wps_check_pin(
+	struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen)
+{
+	char pin[9];
+	size_t len;
+	char *pos;
+	int ret;
+
+	wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN",
+			      (u8 *) cmd, os_strlen(cmd));
+	for (pos = cmd, len = 0; *pos != '\0'; pos++) {
+		if (*pos < '0' || *pos > '9')
+			continue;
+		pin[len++] = *pos;
+		if (len == 9) {
+			wpa_printf(MSG_DEBUG, "WPS: Too long PIN");
+			return -1;
+		}
+	}
+	if (len != 4 && len != 8) {
+		wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len);
+		return -1;
+	}
+	pin[len] = '\0';
+
+	if (len == 8) {
+		unsigned int pin_val;
+		pin_val = atoi(pin);
+		if (!wps_pin_valid(pin_val)) {
+			wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit");
+			ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n");
+			if (os_snprintf_error(buflen, ret))
+				return -1;
+			return ret;
+		}
+	}
+
+	ret = os_snprintf(buf, buflen, "%s", pin);
+	if (os_snprintf_error(buflen, ret))
+		return -1;
+
+	return ret;
+}
+
+
+#ifdef CONFIG_WPS_NFC
+static int hostapd_ctrl_iface_wps_nfc_tag_read(struct hostapd_data *hapd,
+					       char *pos)
+{
+	size_t len;
+	struct wpabuf *buf;
+	int ret;
+
+	len = os_strlen(pos);
+	if (len & 0x01)
+		return -1;
+	len /= 2;
+
+	buf = wpabuf_alloc(len);
+	if (buf == NULL)
+		return -1;
+	if (hexstr2bin(pos, wpabuf_put(buf, len), len) < 0) {
+		wpabuf_free(buf);
+		return -1;
+	}
+
+	ret = hostapd_wps_nfc_tag_read(hapd, buf);
+	wpabuf_free(buf);
+
+	return ret;
+}
+
+
+static int hostapd_ctrl_iface_wps_nfc_config_token(struct hostapd_data *hapd,
+						   char *cmd, char *reply,
+						   size_t max_len)
+{
+	int ndef;
+	struct wpabuf *buf;
+	int res;
+
+	if (os_strcmp(cmd, "WPS") == 0)
+		ndef = 0;
+	else if (os_strcmp(cmd, "NDEF") == 0)
+		ndef = 1;
+	else
+		return -1;
+
+	buf = hostapd_wps_nfc_config_token(hapd, ndef);
+	if (buf == NULL)
+		return -1;
+
+	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
+					 wpabuf_len(buf));
+	reply[res++] = '\n';
+	reply[res] = '\0';
+
+	wpabuf_free(buf);
+
+	return res;
+}
+
+
+static int hostapd_ctrl_iface_wps_nfc_token_gen(struct hostapd_data *hapd,
+						char *reply, size_t max_len,
+						int ndef)
+{
+	struct wpabuf *buf;
+	int res;
+
+	buf = hostapd_wps_nfc_token_gen(hapd, ndef);
+	if (buf == NULL)
+		return -1;
+
+	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
+					 wpabuf_len(buf));
+	reply[res++] = '\n';
+	reply[res] = '\0';
+
+	wpabuf_free(buf);
+
+	return res;
+}
+
+
+static int hostapd_ctrl_iface_wps_nfc_token(struct hostapd_data *hapd,
+					    char *cmd, char *reply,
+					    size_t max_len)
+{
+	if (os_strcmp(cmd, "WPS") == 0)
+		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
+							    max_len, 0);
+
+	if (os_strcmp(cmd, "NDEF") == 0)
+		return hostapd_ctrl_iface_wps_nfc_token_gen(hapd, reply,
+							    max_len, 1);
+
+	if (os_strcmp(cmd, "enable") == 0)
+		return hostapd_wps_nfc_token_enable(hapd);
+
+	if (os_strcmp(cmd, "disable") == 0) {
+		hostapd_wps_nfc_token_disable(hapd);
+		return 0;
+	}
+
+	return -1;
+}
+
+
+static int hostapd_ctrl_iface_nfc_get_handover_sel(struct hostapd_data *hapd,
+						   char *cmd, char *reply,
+						   size_t max_len)
+{
+	struct wpabuf *buf;
+	int res;
+	char *pos;
+	int ndef;
+
+	pos = os_strchr(cmd, ' ');
+	if (pos == NULL)
+		return -1;
+	*pos++ = '\0';
+
+	if (os_strcmp(cmd, "WPS") == 0)
+		ndef = 0;
+	else if (os_strcmp(cmd, "NDEF") == 0)
+		ndef = 1;
+	else
+		return -1;
+
+	if (os_strcmp(pos, "WPS-CR") == 0)
+		buf = hostapd_wps_nfc_hs_cr(hapd, ndef);
+	else
+		buf = NULL;
+	if (buf == NULL)
+		return -1;
+
+	res = wpa_snprintf_hex_uppercase(reply, max_len, wpabuf_head(buf),
+					 wpabuf_len(buf));
+	reply[res++] = '\n';
+	reply[res] = '\0';
+
+	wpabuf_free(buf);
+
+	return res;
+}
+
+
+static int hostapd_ctrl_iface_nfc_report_handover(struct hostapd_data *hapd,
+						  char *cmd)
+{
+	size_t len;
+	struct wpabuf *req, *sel;
+	int ret;
+	char *pos, *role, *type, *pos2;
+
+	role = cmd;
+	pos = os_strchr(role, ' ');
+	if (pos == NULL)
+		return -1;
+	*pos++ = '\0';
+
+	type = pos;
+	pos = os_strchr(type, ' ');
+	if (pos == NULL)
+		return -1;
+	*pos++ = '\0';
+
+	pos2 = os_strchr(pos, ' ');
+	if (pos2 == NULL)
+		return -1;
+	*pos2++ = '\0';
+
+	len = os_strlen(pos);
+	if (len & 0x01)
+		return -1;
+	len /= 2;
+
+	req = wpabuf_alloc(len);
+	if (req == NULL)
+		return -1;
+	if (hexstr2bin(pos, wpabuf_put(req, len), len) < 0) {
+		wpabuf_free(req);
+		return -1;
+	}
+
+	len = os_strlen(pos2);
+	if (len & 0x01) {
+		wpabuf_free(req);
+		return -1;
+	}
+	len /= 2;
+
+	sel = wpabuf_alloc(len);
+	if (sel == NULL) {
+		wpabuf_free(req);
+		return -1;
+	}
+	if (hexstr2bin(pos2, wpabuf_put(sel, len), len) < 0) {
+		wpabuf_free(req);
+		wpabuf_free(sel);
+		return -1;
+	}
+
+	if (os_strcmp(role, "RESP") == 0 && os_strcmp(type, "WPS") == 0) {
+		ret = hostapd_wps_nfc_report_handover(hapd, req, sel);
+	} else {
+		wpa_printf(MSG_DEBUG, "NFC: Unsupported connection handover "
+			   "reported: role=%s type=%s", role, type);
+		ret = -1;
+	}
+	wpabuf_free(req);
+	wpabuf_free(sel);
+
+	return ret;
+}
+
+#endif /* CONFIG_WPS_NFC */
+
+
+static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt,
+					 char *buf, size_t buflen)
+{
+	int timeout = 300;
+	char *pos;
+	const char *pin_txt;
+
+	pos = os_strchr(txt, ' ');
+	if (pos)
+		*pos++ = '\0';
+
+	if (os_strcmp(txt, "disable") == 0) {
+		hostapd_wps_ap_pin_disable(hapd);
+		return os_snprintf(buf, buflen, "OK\n");
+	}
+
+	if (os_strcmp(txt, "random") == 0) {
+		if (pos)
+			timeout = atoi(pos);
+		pin_txt = hostapd_wps_ap_pin_random(hapd, timeout);
+		if (pin_txt == NULL)
+			return -1;
+		return os_snprintf(buf, buflen, "%s", pin_txt);
+	}
+
+	if (os_strcmp(txt, "get") == 0) {
+		pin_txt = hostapd_wps_ap_pin_get(hapd);
+		if (pin_txt == NULL)
+			return -1;
+		return os_snprintf(buf, buflen, "%s", pin_txt);
+	}
+
+	if (os_strcmp(txt, "set") == 0) {
+		char *pin;
+		if (pos == NULL)
+			return -1;
+		pin = pos;
+		pos = os_strchr(pos, ' ');
+		if (pos) {
+			*pos++ = '\0';
+			timeout = atoi(pos);
+		}
+		if (os_strlen(pin) > buflen)
+			return -1;
+		if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0)
+			return -1;
+		return os_snprintf(buf, buflen, "%s", pin);
+	}
+
+	return -1;
+}
+
+
+static int hostapd_ctrl_iface_wps_config(struct hostapd_data *hapd, char *txt)
+{
+	char *pos;
+	char *ssid, *auth, *encr = NULL, *key = NULL;
+
+	ssid = txt;
+	pos = os_strchr(txt, ' ');
+	if (!pos)
+		return -1;
+	*pos++ = '\0';
+
+	auth = pos;
+	pos = os_strchr(pos, ' ');
+	if (pos) {
+		*pos++ = '\0';
+		encr = pos;
+		pos = os_strchr(pos, ' ');
+		if (pos) {
+			*pos++ = '\0';
+			key = pos;
+		}
+	}
+
+	return hostapd_wps_config_ap(hapd, ssid, auth, encr, key);
+}
+
+
+static const char * pbc_status_str(enum pbc_status status)
+{
+	switch (status) {
+	case WPS_PBC_STATUS_DISABLE:
+		return "Disabled";
+	case WPS_PBC_STATUS_ACTIVE:
+		return "Active";
+	case WPS_PBC_STATUS_TIMEOUT:
+		return "Timed-out";
+	case WPS_PBC_STATUS_OVERLAP:
+		return "Overlap";
+	default:
+		return "Unknown";
+	}
+}
+
+
+static int hostapd_ctrl_iface_wps_get_status(struct hostapd_data *hapd,
+					     char *buf, size_t buflen)
+{
+	int ret;
+	char *pos, *end;
+
+	pos = buf;
+	end = buf + buflen;
+
+	ret = os_snprintf(pos, end - pos, "PBC Status: %s\n",
+			  pbc_status_str(hapd->wps_stats.pbc_status));
+
+	if (os_snprintf_error(end - pos, ret))
+		return pos - buf;
+	pos += ret;
+
+	ret = os_snprintf(pos, end - pos, "Last WPS result: %s\n",
+			  (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
+			   "Success":
+			   (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
+			    "Failed" : "None")));
+
+	if (os_snprintf_error(end - pos, ret))
+		return pos - buf;
+	pos += ret;
+
+	/* If status == Failure - Add possible Reasons */
+	if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
+	   hapd->wps_stats.failure_reason > 0) {
+		ret = os_snprintf(pos, end - pos,
+				  "Failure Reason: %s\n",
+				  wps_ei_str(hapd->wps_stats.failure_reason));
+
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+
+	if (hapd->wps_stats.status) {
+		ret = os_snprintf(pos, end - pos, "Peer Address: " MACSTR "\n",
+				  MAC2STR(hapd->wps_stats.peer_addr));
+
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+
+	return pos - buf;
+}
+
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_HS20
+
+static int hostapd_ctrl_iface_hs20_wnm_notif(struct hostapd_data *hapd,
+					     const char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	const char *url;
+
+	if (hwaddr_aton(cmd, addr))
+		return -1;
+	url = cmd + 17;
+	if (*url == '\0') {
+		url = NULL;
+	} else {
+		if (*url != ' ')
+			return -1;
+		url++;
+		if (*url == '\0')
+			url = NULL;
+	}
+
+	return hs20_send_wnm_notification(hapd, addr, 1, url);
+}
+
+
+static int hostapd_ctrl_iface_hs20_deauth_req(struct hostapd_data *hapd,
+					      const char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	int code, reauth_delay, ret;
+	const char *pos;
+	size_t url_len;
+	struct wpabuf *req;
+
+	/* <STA MAC Addr> <Code(0/1)> <Re-auth-Delay(sec)> [URL] */
+	if (hwaddr_aton(cmd, addr))
+		return -1;
+
+	pos = os_strchr(cmd, ' ');
+	if (pos == NULL)
+		return -1;
+	pos++;
+	code = atoi(pos);
+
+	pos = os_strchr(pos, ' ');
+	if (pos == NULL)
+		return -1;
+	pos++;
+	reauth_delay = atoi(pos);
+
+	url_len = 0;
+	pos = os_strchr(pos, ' ');
+	if (pos) {
+		pos++;
+		url_len = os_strlen(pos);
+	}
+
+	req = wpabuf_alloc(4 + url_len);
+	if (req == NULL)
+		return -1;
+	wpabuf_put_u8(req, code);
+	wpabuf_put_le16(req, reauth_delay);
+	wpabuf_put_u8(req, url_len);
+	if (pos)
+		wpabuf_put_data(req, pos, url_len);
+
+	wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to " MACSTR
+		   " to indicate imminent deauthentication (code=%d "
+		   "reauth_delay=%d)", MAC2STR(addr), code, reauth_delay);
+	ret = hs20_send_wnm_notification_deauth_req(hapd, addr, req);
+	wpabuf_free(req);
+	return ret;
+}
+
+#endif /* CONFIG_HS20 */
+
+
+#ifdef CONFIG_INTERWORKING
+
+static int hostapd_ctrl_iface_set_qos_map_set(struct hostapd_data *hapd,
+					      const char *cmd)
+{
+	u8 qos_map_set[16 + 2 * 21], count = 0;
+	const char *pos = cmd;
+	int val, ret;
+
+	for (;;) {
+		if (count == sizeof(qos_map_set)) {
+			wpa_printf(MSG_ERROR, "Too many qos_map_set parameters");
+			return -1;
+		}
+
+		val = atoi(pos);
+		if (val < 0 || val > 255) {
+			wpa_printf(MSG_INFO, "Invalid QoS Map Set");
+			return -1;
+		}
+
+		qos_map_set[count++] = val;
+		pos = os_strchr(pos, ',');
+		if (!pos)
+			break;
+		pos++;
+	}
+
+	if (count < 16 || count & 1) {
+		wpa_printf(MSG_INFO, "Invalid QoS Map Set");
+		return -1;
+	}
+
+	ret = hostapd_drv_set_qos_map(hapd, qos_map_set, count);
+	if (ret) {
+		wpa_printf(MSG_INFO, "Failed to set QoS Map Set");
+		return -1;
+	}
+
+	os_memcpy(hapd->conf->qos_map_set, qos_map_set, count);
+	hapd->conf->qos_map_set_len = count;
+
+	return 0;
+}
+
+
+static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd,
+						const char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+	struct wpabuf *buf;
+	u8 *qos_map_set = hapd->conf->qos_map_set;
+	u8 qos_map_set_len = hapd->conf->qos_map_set_len;
+	int ret;
+
+	if (!qos_map_set_len) {
+		wpa_printf(MSG_INFO, "QoS Map Set is not set");
+		return -1;
+	}
+
+	if (hwaddr_aton(cmd, addr))
+		return -1;
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta == NULL) {
+		wpa_printf(MSG_DEBUG, "Station " MACSTR " not found "
+			   "for QoS Map Configuration message",
+			   MAC2STR(addr));
+		return -1;
+	}
+
+	if (!sta->qos_map_enabled) {
+		wpa_printf(MSG_DEBUG, "Station " MACSTR " did not indicate "
+			   "support for QoS Map", MAC2STR(addr));
+		return -1;
+	}
+
+	buf = wpabuf_alloc(2 + 2 + qos_map_set_len);
+	if (buf == NULL)
+		return -1;
+
+	wpabuf_put_u8(buf, WLAN_ACTION_QOS);
+	wpabuf_put_u8(buf, QOS_QOS_MAP_CONFIG);
+
+	/* QoS Map Set Element */
+	wpabuf_put_u8(buf, WLAN_EID_QOS_MAP_SET);
+	wpabuf_put_u8(buf, qos_map_set_len);
+	wpabuf_put_data(buf, qos_map_set, qos_map_set_len);
+
+	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
+				      wpabuf_head(buf), wpabuf_len(buf));
+	wpabuf_free(buf);
+
+	return ret;
+}
+
+#endif /* CONFIG_INTERWORKING */
+
+
+#ifdef CONFIG_WNM
+
+static int hostapd_ctrl_iface_disassoc_imminent(struct hostapd_data *hapd,
+						const char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	int disassoc_timer;
+	struct sta_info *sta;
+
+	if (hwaddr_aton(cmd, addr))
+		return -1;
+	if (cmd[17] != ' ')
+		return -1;
+	disassoc_timer = atoi(cmd + 17);
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta == NULL) {
+		wpa_printf(MSG_DEBUG, "Station " MACSTR
+			   " not found for disassociation imminent message",
+			   MAC2STR(addr));
+		return -1;
+	}
+
+	return wnm_send_disassoc_imminent(hapd, sta, disassoc_timer);
+}
+
+
+static int hostapd_ctrl_iface_ess_disassoc(struct hostapd_data *hapd,
+					   const char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	const char *url, *timerstr;
+	int disassoc_timer;
+	struct sta_info *sta;
+
+	if (hwaddr_aton(cmd, addr))
+		return -1;
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta == NULL) {
+		wpa_printf(MSG_DEBUG, "Station " MACSTR
+			   " not found for ESS disassociation imminent message",
+			   MAC2STR(addr));
+		return -1;
+	}
+
+	timerstr = cmd + 17;
+	if (*timerstr != ' ')
+		return -1;
+	timerstr++;
+	disassoc_timer = atoi(timerstr);
+	if (disassoc_timer < 0 || disassoc_timer > 65535)
+		return -1;
+
+	url = os_strchr(timerstr, ' ');
+	if (url == NULL)
+		return -1;
+	url++;
+
+	return wnm_send_ess_disassoc_imminent(hapd, sta, url, disassoc_timer);
+}
+
+
+static int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
+					 const char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	const char *pos, *end;
+	int disassoc_timer = 0;
+	struct sta_info *sta;
+	u8 req_mode = 0, valid_int = 0x01;
+	u8 bss_term_dur[12];
+	char *url = NULL;
+	int ret;
+	u8 nei_rep[1000];
+	u8 *nei_pos = nei_rep;
+	u8 mbo[10];
+	size_t mbo_len = 0;
+
+	if (hwaddr_aton(cmd, addr)) {
+		wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
+		return -1;
+	}
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta == NULL) {
+		wpa_printf(MSG_DEBUG, "Station " MACSTR
+			   " not found for BSS TM Request message",
+			   MAC2STR(addr));
+		return -1;
+	}
+
+	pos = os_strstr(cmd, " disassoc_timer=");
+	if (pos) {
+		pos += 16;
+		disassoc_timer = atoi(pos);
+		if (disassoc_timer < 0 || disassoc_timer > 65535) {
+			wpa_printf(MSG_DEBUG, "Invalid disassoc_timer");
+			return -1;
+		}
+	}
+
+	pos = os_strstr(cmd, " valid_int=");
+	if (pos) {
+		pos += 11;
+		valid_int = atoi(pos);
+	}
+
+	pos = os_strstr(cmd, " bss_term=");
+	if (pos) {
+		pos += 10;
+		req_mode |= WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED;
+		/* TODO: TSF configurable/learnable */
+		bss_term_dur[0] = 4; /* Subelement ID */
+		bss_term_dur[1] = 10; /* Length */
+		os_memset(bss_term_dur, 2, 8);
+		end = os_strchr(pos, ',');
+		if (end == NULL) {
+			wpa_printf(MSG_DEBUG, "Invalid bss_term data");
+			return -1;
+		}
+		end++;
+		WPA_PUT_LE16(&bss_term_dur[10], atoi(end));
+	}
+
+
+	/*
+	 * BSS Transition Candidate List Entries - Neighbor Report elements
+	 * neighbor=<BSSID>,<BSSID Information>,<Operating Class>,
+	 * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>]
+	 */
+	pos = cmd;
+	while (pos) {
+		u8 *nei_start;
+		long int val;
+		char *endptr, *tmp;
+
+		pos = os_strstr(pos, " neighbor=");
+		if (!pos)
+			break;
+		if (nei_pos + 15 > nei_rep + sizeof(nei_rep)) {
+			wpa_printf(MSG_DEBUG,
+				   "Not enough room for additional neighbor");
+			return -1;
+		}
+		pos += 10;
+
+		nei_start = nei_pos;
+		*nei_pos++ = WLAN_EID_NEIGHBOR_REPORT;
+		nei_pos++; /* length to be filled in */
+
+		if (hwaddr_aton(pos, nei_pos)) {
+			wpa_printf(MSG_DEBUG, "Invalid BSSID");
+			return -1;
+		}
+		nei_pos += ETH_ALEN;
+		pos += 17;
+		if (*pos != ',') {
+			wpa_printf(MSG_DEBUG, "Missing BSSID Information");
+			return -1;
+		}
+		pos++;
+
+		val = strtol(pos, &endptr, 0);
+		WPA_PUT_LE32(nei_pos, val);
+		nei_pos += 4;
+		if (*endptr != ',') {
+			wpa_printf(MSG_DEBUG, "Missing Operating Class");
+			return -1;
+		}
+		pos = endptr + 1;
+
+		*nei_pos++ = atoi(pos); /* Operating Class */
+		pos = os_strchr(pos, ',');
+		if (pos == NULL) {
+			wpa_printf(MSG_DEBUG, "Missing Channel Number");
+			return -1;
+		}
+		pos++;
+
+		*nei_pos++ = atoi(pos); /* Channel Number */
+		pos = os_strchr(pos, ',');
+		if (pos == NULL) {
+			wpa_printf(MSG_DEBUG, "Missing PHY Type");
+			return -1;
+		}
+		pos++;
+
+		*nei_pos++ = atoi(pos); /* PHY Type */
+		end = os_strchr(pos, ' ');
+		tmp = os_strchr(pos, ',');
+		if (tmp && (!end || tmp < end)) {
+			/* Optional Subelements (hexdump) */
+			size_t len;
+
+			pos = tmp + 1;
+			end = os_strchr(pos, ' ');
+			if (end)
+				len = end - pos;
+			else
+				len = os_strlen(pos);
+			if (nei_pos + len / 2 > nei_rep + sizeof(nei_rep)) {
+				wpa_printf(MSG_DEBUG,
+					   "Not enough room for neighbor subelements");
+				return -1;
+			}
+			if (len & 0x01 ||
+			    hexstr2bin(pos, nei_pos, len / 2) < 0) {
+				wpa_printf(MSG_DEBUG,
+					   "Invalid neighbor subelement info");
+				return -1;
+			}
+			nei_pos += len / 2;
+			pos = end;
+		}
+
+		nei_start[1] = nei_pos - nei_start - 2;
+	}
+
+	pos = os_strstr(cmd, " url=");
+	if (pos) {
+		size_t len;
+		pos += 5;
+		end = os_strchr(pos, ' ');
+		if (end)
+			len = end - pos;
+		else
+			len = os_strlen(pos);
+		url = os_malloc(len + 1);
+		if (url == NULL)
+			return -1;
+		os_memcpy(url, pos, len);
+		url[len] = '\0';
+		req_mode |= WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT;
+	}
+
+	if (os_strstr(cmd, " pref=1"))
+		req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
+	if (os_strstr(cmd, " abridged=1"))
+		req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
+	if (os_strstr(cmd, " disassoc_imminent=1"))
+		req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
+
+#ifdef CONFIG_MBO
+	pos = os_strstr(cmd, "mbo=");
+	if (pos) {
+		unsigned int mbo_reason, cell_pref, reassoc_delay;
+		u8 *mbo_pos = mbo;
+
+		ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
+			     &reassoc_delay, &cell_pref);
+		if (ret != 3) {
+			wpa_printf(MSG_DEBUG,
+				   "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
+			return -1;
+		}
+
+		if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
+			wpa_printf(MSG_DEBUG,
+				   "Invalid MBO transition reason code %u",
+				   mbo_reason);
+			return -1;
+		}
+
+		/* Valid values for Cellular preference are: 0, 1, 255 */
+		if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255) {
+			wpa_printf(MSG_DEBUG,
+				   "Invalid MBO cellular capability %u",
+				   cell_pref);
+			return -1;
+		}
+
+		if (reassoc_delay > 65535 ||
+		    (reassoc_delay &&
+		     !(req_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT))) {
+			wpa_printf(MSG_DEBUG,
+				   "MBO: Assoc retry delay is only valid in disassoc imminent mode");
+			return -1;
+		}
+
+		*mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
+		*mbo_pos++ = 1;
+		*mbo_pos++ = mbo_reason;
+		*mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
+		*mbo_pos++ = 1;
+		*mbo_pos++ = cell_pref;
+
+		if (reassoc_delay) {
+			*mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
+			*mbo_pos++ = 2;
+			WPA_PUT_LE16(mbo_pos, reassoc_delay);
+			mbo_pos += 2;
+		}
+
+		mbo_len = mbo_pos - mbo;
+	}
+#endif /* CONFIG_MBO */
+
+	ret = wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer,
+				  valid_int, bss_term_dur, url,
+				  nei_pos > nei_rep ? nei_rep : NULL,
+				  nei_pos - nei_rep, mbo_len ? mbo : NULL,
+				  mbo_len);
+	os_free(url);
+	return ret;
+}
+
+#endif /* CONFIG_WNM */
+
+
+static int hostapd_ctrl_iface_get_key_mgmt(struct hostapd_data *hapd,
+					   char *buf, size_t buflen)
+{
+	int ret = 0;
+	char *pos, *end;
+
+	pos = buf;
+	end = buf + buflen;
+
+	WPA_ASSERT(hapd->conf->wpa_key_mgmt);
+
+	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
+		ret = os_snprintf(pos, end - pos, "WPA-PSK ");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
+		ret = os_snprintf(pos, end - pos, "WPA-EAP ");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+#ifdef CONFIG_IEEE80211R
+	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
+		ret = os_snprintf(pos, end - pos, "FT-PSK ");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
+		ret = os_snprintf(pos, end - pos, "FT-EAP ");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+#ifdef CONFIG_SAE
+	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
+		ret = os_snprintf(pos, end - pos, "FT-SAE ");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+#endif /* CONFIG_SAE */
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211W
+	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
+		ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 ");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
+		ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 ");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_SAE
+	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
+		ret = os_snprintf(pos, end - pos, "SAE ");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+#endif /* CONFIG_SAE */
+	if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
+		ret = os_snprintf(pos, end - pos, "WPA-EAP-SUITE-B ");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+	if (hapd->conf->wpa_key_mgmt &
+	    WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
+		ret = os_snprintf(pos, end - pos,
+				  "WPA-EAP-SUITE-B-192 ");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+
+	if (pos > buf && *(pos - 1) == ' ') {
+		*(pos - 1) = '\0';
+		pos--;
+	}
+
+	return pos - buf;
+}
+
+
+static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd,
+					 char *buf, size_t buflen)
+{
+	int ret;
+	char *pos, *end;
+
+	pos = buf;
+	end = buf + buflen;
+
+	ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n"
+			  "ssid=%s\n",
+			  MAC2STR(hapd->own_addr),
+			  wpa_ssid_txt(hapd->conf->ssid.ssid,
+				       hapd->conf->ssid.ssid_len));
+	if (os_snprintf_error(end - pos, ret))
+		return pos - buf;
+	pos += ret;
+
+#ifdef CONFIG_WPS
+	ret = os_snprintf(pos, end - pos, "wps_state=%s\n",
+			  hapd->conf->wps_state == 0 ? "disabled" :
+			  (hapd->conf->wps_state == 1 ? "not configured" :
+			   "configured"));
+	if (os_snprintf_error(end - pos, ret))
+		return pos - buf;
+	pos += ret;
+
+	if (hapd->conf->wps_state && hapd->conf->wpa &&
+	    hapd->conf->ssid.wpa_passphrase) {
+		ret = os_snprintf(pos, end - pos, "passphrase=%s\n",
+				  hapd->conf->ssid.wpa_passphrase);
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+
+	if (hapd->conf->wps_state && hapd->conf->wpa &&
+	    hapd->conf->ssid.wpa_psk &&
+	    hapd->conf->ssid.wpa_psk->group) {
+		char hex[PMK_LEN * 2 + 1];
+		wpa_snprintf_hex(hex, sizeof(hex),
+				 hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
+		ret = os_snprintf(pos, end - pos, "psk=%s\n", hex);
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+#endif /* CONFIG_WPS */
+
+	if (hapd->conf->wpa) {
+		ret = os_snprintf(pos, end - pos, "wpa=%d\n", hapd->conf->wpa);
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+
+	if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) {
+		ret = os_snprintf(pos, end - pos, "key_mgmt=");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+
+		pos += hostapd_ctrl_iface_get_key_mgmt(hapd, pos, end - pos);
+
+		ret = os_snprintf(pos, end - pos, "\n");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+
+	if (hapd->conf->wpa) {
+		ret = os_snprintf(pos, end - pos, "group_cipher=%s\n",
+				  wpa_cipher_txt(hapd->conf->wpa_group));
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+
+	if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) {
+		ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher=");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+
+		ret = wpa_write_ciphers(pos, end, hapd->conf->rsn_pairwise,
+					" ");
+		if (ret < 0)
+			return pos - buf;
+		pos += ret;
+
+		ret = os_snprintf(pos, end - pos, "\n");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+
+	if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) {
+		ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher=");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+
+		ret = wpa_write_ciphers(pos, end, hapd->conf->wpa_pairwise,
+					" ");
+		if (ret < 0)
+			return pos - buf;
+		pos += ret;
+
+		ret = os_snprintf(pos, end - pos, "\n");
+		if (os_snprintf_error(end - pos, ret))
+			return pos - buf;
+		pos += ret;
+	}
+
+	return pos - buf;
+}
+
+
+static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
+{
+	char *value;
+	int ret = 0;
+
+	value = os_strchr(cmd, ' ');
+	if (value == NULL)
+		return -1;
+	*value++ = '\0';
+
+	wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
+	if (0) {
+#ifdef CONFIG_WPS_TESTING
+	} else if (os_strcasecmp(cmd, "wps_version_number") == 0) {
+		long int val;
+		val = strtol(value, NULL, 0);
+		if (val < 0 || val > 0xff) {
+			ret = -1;
+			wpa_printf(MSG_DEBUG, "WPS: Invalid "
+				   "wps_version_number %ld", val);
+		} else {
+			wps_version_number = val;
+			wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS "
+				   "version %u.%u",
+				   (wps_version_number & 0xf0) >> 4,
+				   wps_version_number & 0x0f);
+			hostapd_wps_update_ie(hapd);
+		}
+	} else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) {
+		wps_testing_dummy_cred = atoi(value);
+		wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d",
+			   wps_testing_dummy_cred);
+	} else if (os_strcasecmp(cmd, "wps_corrupt_pkhash") == 0) {
+		wps_corrupt_pkhash = atoi(value);
+		wpa_printf(MSG_DEBUG, "WPS: Testing - wps_corrupt_pkhash=%d",
+			   wps_corrupt_pkhash);
+#endif /* CONFIG_WPS_TESTING */
+#ifdef CONFIG_INTERWORKING
+	} else if (os_strcasecmp(cmd, "gas_frag_limit") == 0) {
+		int val = atoi(value);
+		if (val <= 0)
+			ret = -1;
+		else
+			hapd->gas_frag_limit = val;
+#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_TESTING_OPTIONS
+	} else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) {
+		hapd->ext_mgmt_frame_handling = atoi(value);
+	} else if (os_strcasecmp(cmd, "ext_eapol_frame_io") == 0) {
+		hapd->ext_eapol_frame_io = atoi(value);
+#endif /* CONFIG_TESTING_OPTIONS */
+#ifdef CONFIG_MBO
+	} else if (os_strcasecmp(cmd, "mbo_assoc_disallow") == 0) {
+		int val;
+
+		if (!hapd->conf->mbo_enabled)
+			return -1;
+
+		val = atoi(value);
+		if (val < 0 || val > 1)
+			return -1;
+
+		hapd->mbo_assoc_disallow = val;
+		ieee802_11_update_beacons(hapd->iface);
+
+		/*
+		 * TODO: Need to configure drivers that do AP MLME offload with
+		 * disallowing station logic.
+		 */
+#endif /* CONFIG_MBO */
+	} else {
+		struct sta_info *sta;
+		struct vlan_description vlan_id;
+
+		ret = hostapd_set_iface(hapd->iconf, hapd->conf, cmd, value);
+		if (ret)
+			return ret;
+
+		if (os_strcasecmp(cmd, "deny_mac_file") == 0) {
+			for (sta = hapd->sta_list; sta; sta = sta->next) {
+				if (hostapd_maclist_found(
+					    hapd->conf->deny_mac,
+					    hapd->conf->num_deny_mac, sta->addr,
+					    &vlan_id) &&
+				    (!vlan_id.notempty ||
+				     !vlan_compare(&vlan_id, sta->vlan_desc)))
+					ap_sta_disconnect(
+						hapd, sta, sta->addr,
+						WLAN_REASON_UNSPECIFIED);
+			}
+		} else if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED &&
+			   os_strcasecmp(cmd, "accept_mac_file") == 0) {
+			for (sta = hapd->sta_list; sta; sta = sta->next) {
+				if (!hostapd_maclist_found(
+					    hapd->conf->accept_mac,
+					    hapd->conf->num_accept_mac,
+					    sta->addr, &vlan_id) ||
+				    (vlan_id.notempty &&
+				     vlan_compare(&vlan_id, sta->vlan_desc)))
+					ap_sta_disconnect(
+						hapd, sta, sta->addr,
+						WLAN_REASON_UNSPECIFIED);
+			}
+		}
+	}
+
+	return ret;
+}
+
+
+static int hostapd_ctrl_iface_get(struct hostapd_data *hapd, char *cmd,
+				  char *buf, size_t buflen)
+{
+	int res;
+
+	wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
+
+	if (os_strcmp(cmd, "version") == 0) {
+		res = os_snprintf(buf, buflen, "%s", VERSION_STR);
+		if (os_snprintf_error(buflen, res))
+			return -1;
+		return res;
+	} else if (os_strcmp(cmd, "tls_library") == 0) {
+		res = tls_get_library_version(buf, buflen);
+		if (os_snprintf_error(buflen, res))
+			return -1;
+		return res;
+	}
+
+	return -1;
+}
+
+
+static int hostapd_ctrl_iface_enable(struct hostapd_iface *iface)
+{
+	if (hostapd_enable_iface(iface) < 0) {
+		wpa_printf(MSG_ERROR, "Enabling of interface failed");
+		return -1;
+	}
+	return 0;
+}
+
+
+static int hostapd_ctrl_iface_reload(struct hostapd_iface *iface)
+{
+	if (hostapd_reload_iface(iface) < 0) {
+		wpa_printf(MSG_ERROR, "Reloading of interface failed");
+		return -1;
+	}
+	return 0;
+}
+
+
+static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface)
+{
+	if (hostapd_disable_iface(iface) < 0) {
+		wpa_printf(MSG_ERROR, "Disabling of interface failed");
+		return -1;
+	}
+	return 0;
+}
+
+
+#ifdef CONFIG_TESTING_OPTIONS
+
+static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd)
+{
+	union wpa_event_data data;
+	char *pos, *param;
+	enum wpa_event_type event;
+
+	wpa_printf(MSG_DEBUG, "RADAR TEST: %s", cmd);
+
+	os_memset(&data, 0, sizeof(data));
+
+	param = os_strchr(cmd, ' ');
+	if (param == NULL)
+		return -1;
+	*param++ = '\0';
+
+	if (os_strcmp(cmd, "DETECTED") == 0)
+		event = EVENT_DFS_RADAR_DETECTED;
+	else if (os_strcmp(cmd, "CAC-FINISHED") == 0)
+		event = EVENT_DFS_CAC_FINISHED;
+	else if (os_strcmp(cmd, "CAC-ABORTED") == 0)
+		event = EVENT_DFS_CAC_ABORTED;
+	else if (os_strcmp(cmd, "NOP-FINISHED") == 0)
+		event = EVENT_DFS_NOP_FINISHED;
+	else {
+		wpa_printf(MSG_DEBUG, "Unsupported RADAR test command: %s",
+			   cmd);
+		return -1;
+	}
+
+	pos = os_strstr(param, "freq=");
+	if (pos)
+		data.dfs_event.freq = atoi(pos + 5);
+
+	pos = os_strstr(param, "ht_enabled=1");
+	if (pos)
+		data.dfs_event.ht_enabled = 1;
+
+	pos = os_strstr(param, "chan_offset=");
+	if (pos)
+		data.dfs_event.chan_offset = atoi(pos + 12);
+
+	pos = os_strstr(param, "chan_width=");
+	if (pos)
+		data.dfs_event.chan_width = atoi(pos + 11);
+
+	pos = os_strstr(param, "cf1=");
+	if (pos)
+		data.dfs_event.cf1 = atoi(pos + 4);
+
+	pos = os_strstr(param, "cf2=");
+	if (pos)
+		data.dfs_event.cf2 = atoi(pos + 4);
+
+	wpa_supplicant_event(hapd, event, &data);
+
+	return 0;
+}
+
+
+static int hostapd_ctrl_iface_mgmt_tx(struct hostapd_data *hapd, char *cmd)
+{
+	size_t len;
+	u8 *buf;
+	int res;
+
+	wpa_printf(MSG_DEBUG, "External MGMT TX: %s", cmd);
+
+	len = os_strlen(cmd);
+	if (len & 1)
+		return -1;
+	len /= 2;
+
+	buf = os_malloc(len);
+	if (buf == NULL)
+		return -1;
+
+	if (hexstr2bin(cmd, buf, len) < 0) {
+		os_free(buf);
+		return -1;
+	}
+
+	res = hostapd_drv_send_mlme(hapd, buf, len, 0);
+	os_free(buf);
+	return res;
+}
+
+
+static int hostapd_ctrl_iface_eapol_rx(struct hostapd_data *hapd, char *cmd)
+{
+	char *pos;
+	u8 src[ETH_ALEN], *buf;
+	int used;
+	size_t len;
+
+	wpa_printf(MSG_DEBUG, "External EAPOL RX: %s", cmd);
+
+	pos = cmd;
+	used = hwaddr_aton2(pos, src);
+	if (used < 0)
+		return -1;
+	pos += used;
+	while (*pos == ' ')
+		pos++;
+
+	len = os_strlen(pos);
+	if (len & 1)
+		return -1;
+	len /= 2;
+
+	buf = os_malloc(len);
+	if (buf == NULL)
+		return -1;
+
+	if (hexstr2bin(pos, buf, len) < 0) {
+		os_free(buf);
+		return -1;
+	}
+
+	ieee802_1x_receive(hapd, src, buf, len);
+	os_free(buf);
+
+	return 0;
+}
+
+
+static u16 ipv4_hdr_checksum(const void *buf, size_t len)
+{
+	size_t i;
+	u32 sum = 0;
+	const u16 *pos = buf;
+
+	for (i = 0; i < len / 2; i++)
+		sum += *pos++;
+
+	while (sum >> 16)
+		sum = (sum & 0xffff) + (sum >> 16);
+
+	return sum ^ 0xffff;
+}
+
+
+#define HWSIM_PACKETLEN 1500
+#define HWSIM_IP_LEN (HWSIM_PACKETLEN - sizeof(struct ether_header))
+
+static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf,
+				 size_t len)
+{
+	struct hostapd_data *hapd = ctx;
+	const struct ether_header *eth;
+	struct iphdr ip;
+	const u8 *pos;
+	unsigned int i;
+
+	if (len != HWSIM_PACKETLEN)
+		return;
+
+	eth = (const struct ether_header *) buf;
+	os_memcpy(&ip, eth + 1, sizeof(ip));
+	pos = &buf[sizeof(*eth) + sizeof(ip)];
+
+	if (ip.ihl != 5 || ip.version != 4 ||
+	    ntohs(ip.tot_len) != HWSIM_IP_LEN)
+		return;
+
+	for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) {
+		if (*pos != (u8) i)
+			return;
+		pos++;
+	}
+
+	wpa_msg(hapd->msg_ctx, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR,
+		MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost));
+}
+
+
+static int hostapd_ctrl_iface_data_test_config(struct hostapd_data *hapd,
+					       char *cmd)
+{
+	int enabled = atoi(cmd);
+	char *pos;
+	const char *ifname;
+
+	if (!enabled) {
+		if (hapd->l2_test) {
+			l2_packet_deinit(hapd->l2_test);
+			hapd->l2_test = NULL;
+			wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
+				"test data: Disabled");
+		}
+		return 0;
+	}
+
+	if (hapd->l2_test)
+		return 0;
+
+	pos = os_strstr(cmd, " ifname=");
+	if (pos)
+		ifname = pos + 8;
+	else
+		ifname = hapd->conf->iface;
+
+	hapd->l2_test = l2_packet_init(ifname, hapd->own_addr,
+					ETHERTYPE_IP, hostapd_data_test_rx,
+					hapd, 1);
+	if (hapd->l2_test == NULL)
+		return -1;
+
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: Enabled");
+
+	return 0;
+}
+
+
+static int hostapd_ctrl_iface_data_test_tx(struct hostapd_data *hapd, char *cmd)
+{
+	u8 dst[ETH_ALEN], src[ETH_ALEN];
+	char *pos;
+	int used;
+	long int val;
+	u8 tos;
+	u8 buf[2 + HWSIM_PACKETLEN];
+	struct ether_header *eth;
+	struct iphdr *ip;
+	u8 *dpos;
+	unsigned int i;
+
+	if (hapd->l2_test == NULL)
+		return -1;
+
+	/* format: <dst> <src> <tos> */
+
+	pos = cmd;
+	used = hwaddr_aton2(pos, dst);
+	if (used < 0)
+		return -1;
+	pos += used;
+	while (*pos == ' ')
+		pos++;
+	used = hwaddr_aton2(pos, src);
+	if (used < 0)
+		return -1;
+	pos += used;
+
+	val = strtol(pos, NULL, 0);
+	if (val < 0 || val > 0xff)
+		return -1;
+	tos = val;
+
+	eth = (struct ether_header *) &buf[2];
+	os_memcpy(eth->ether_dhost, dst, ETH_ALEN);
+	os_memcpy(eth->ether_shost, src, ETH_ALEN);
+	eth->ether_type = htons(ETHERTYPE_IP);
+	ip = (struct iphdr *) (eth + 1);
+	os_memset(ip, 0, sizeof(*ip));
+	ip->ihl = 5;
+	ip->version = 4;
+	ip->ttl = 64;
+	ip->tos = tos;
+	ip->tot_len = htons(HWSIM_IP_LEN);
+	ip->protocol = 1;
+	ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1);
+	ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2);
+	ip->check = ipv4_hdr_checksum(ip, sizeof(*ip));
+	dpos = (u8 *) (ip + 1);
+	for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++)
+		*dpos++ = i;
+
+	if (l2_packet_send(hapd->l2_test, dst, ETHERTYPE_IP, &buf[2],
+			   HWSIM_PACKETLEN) < 0)
+		return -1;
+
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX dst=" MACSTR
+		" src=" MACSTR " tos=0x%x", MAC2STR(dst), MAC2STR(src), tos);
+
+	return 0;
+}
+
+
+static int hostapd_ctrl_iface_data_test_frame(struct hostapd_data *hapd,
+					      char *cmd)
+{
+	u8 *buf;
+	struct ether_header *eth;
+	struct l2_packet_data *l2 = NULL;
+	size_t len;
+	u16 ethertype;
+	int res = -1;
+	const char *ifname = hapd->conf->iface;
+
+	if (os_strncmp(cmd, "ifname=", 7) == 0) {
+		cmd += 7;
+		ifname = cmd;
+		cmd = os_strchr(cmd, ' ');
+		if (cmd == NULL)
+			return -1;
+		*cmd++ = '\0';
+	}
+
+	len = os_strlen(cmd);
+	if (len & 1 || len < ETH_HLEN * 2)
+		return -1;
+	len /= 2;
+
+	buf = os_malloc(len);
+	if (buf == NULL)
+		return -1;
+
+	if (hexstr2bin(cmd, buf, len) < 0)
+		goto done;
+
+	eth = (struct ether_header *) buf;
+	ethertype = ntohs(eth->ether_type);
+
+	l2 = l2_packet_init(ifname, hapd->own_addr, ethertype,
+			    hostapd_data_test_rx, hapd, 1);
+	if (l2 == NULL)
+		goto done;
+
+	res = l2_packet_send(l2, eth->ether_dhost, ethertype, buf, len);
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "test data: TX frame res=%d", res);
+done:
+	if (l2)
+		l2_packet_deinit(l2);
+	os_free(buf);
+
+	return res < 0 ? -1 : 0;
+}
+
+
+static int hostapd_ctrl_test_alloc_fail(struct hostapd_data *hapd, char *cmd)
+{
+#ifdef WPA_TRACE_BFD
+	char *pos;
+
+	wpa_trace_fail_after = atoi(cmd);
+	pos = os_strchr(cmd, ':');
+	if (pos) {
+		pos++;
+		os_strlcpy(wpa_trace_fail_func, pos,
+			   sizeof(wpa_trace_fail_func));
+	} else {
+		wpa_trace_fail_after = 0;
+	}
+
+	return 0;
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int hostapd_ctrl_get_alloc_fail(struct hostapd_data *hapd,
+				       char *buf, size_t buflen)
+{
+#ifdef WPA_TRACE_BFD
+	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_fail_after,
+			   wpa_trace_fail_func);
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int hostapd_ctrl_test_fail(struct hostapd_data *hapd, char *cmd)
+{
+#ifdef WPA_TRACE_BFD
+	char *pos;
+
+	wpa_trace_test_fail_after = atoi(cmd);
+	pos = os_strchr(cmd, ':');
+	if (pos) {
+		pos++;
+		os_strlcpy(wpa_trace_test_fail_func, pos,
+			   sizeof(wpa_trace_test_fail_func));
+	} else {
+		wpa_trace_test_fail_after = 0;
+	}
+
+	return 0;
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+
+static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
+				 char *buf, size_t buflen)
+{
+#ifdef WPA_TRACE_BFD
+	return os_snprintf(buf, buflen, "%u:%s", wpa_trace_test_fail_after,
+			   wpa_trace_test_fail_func);
+#else /* WPA_TRACE_BFD */
+	return -1;
+#endif /* WPA_TRACE_BFD */
+}
+
+#endif /* CONFIG_TESTING_OPTIONS */
+
+
+static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+					  char *pos)
+{
+#ifdef NEED_AP_MLME
+	struct csa_settings settings;
+	int ret;
+	unsigned int i;
+
+	ret = hostapd_parse_csa_settings(pos, &settings);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < iface->num_bss; i++) {
+		ret = hostapd_switch_channel(iface->bss[i], &settings);
+		if (ret) {
+			/* FIX: What do we do if CSA fails in the middle of
+			 * submitting multi-BSS CSA requests? */
+			return ret;
+		}
+	}
+
+	return 0;
+#else /* NEED_AP_MLME */
+	return -1;
+#endif /* NEED_AP_MLME */
+}
+
+
+static int hostapd_ctrl_iface_mib(struct hostapd_data *hapd, char *reply,
+				  int reply_size, const char *param)
+{
+#ifdef RADIUS_SERVER
+	if (os_strcmp(param, "radius_server") == 0) {
+		return radius_server_get_mib(hapd->radius_srv, reply,
+					     reply_size);
+	}
+#endif /* RADIUS_SERVER */
+	return -1;
+}
+
+
+static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd,
+				     char *buf, size_t buflen)
+{
+	int ret;
+	char *pos;
+	u8 *data = NULL;
+	unsigned int vendor_id, subcmd;
+	struct wpabuf *reply;
+	size_t data_len = 0;
+
+	/* cmd: <vendor id> <subcommand id> [<hex formatted data>] */
+	vendor_id = strtoul(cmd, &pos, 16);
+	if (!isblank((unsigned char) *pos))
+		return -EINVAL;
+
+	subcmd = strtoul(pos, &pos, 10);
+
+	if (*pos != '\0') {
+		if (!isblank((unsigned char) *pos++))
+			return -EINVAL;
+		data_len = os_strlen(pos);
+	}
+
+	if (data_len) {
+		data_len /= 2;
+		data = os_malloc(data_len);
+		if (!data)
+			return -ENOBUFS;
+
+		if (hexstr2bin(pos, data, data_len)) {
+			wpa_printf(MSG_DEBUG,
+				   "Vendor command: wrong parameter format");
+			os_free(data);
+			return -EINVAL;
+		}
+	}
+
+	reply = wpabuf_alloc((buflen - 1) / 2);
+	if (!reply) {
+		os_free(data);
+		return -ENOBUFS;
+	}
+
+	ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len,
+				     reply);
+
+	if (ret == 0)
+		ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply),
+				       wpabuf_len(reply));
+
+	wpabuf_free(reply);
+	os_free(data);
+
+	return ret;
+}
+
+
+static int hostapd_ctrl_iface_eapol_reauth(struct hostapd_data *hapd,
+					   const char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+
+	if (hwaddr_aton(cmd, addr))
+		return -1;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta || !sta->eapol_sm)
+		return -1;
+
+	eapol_auth_reauthenticate(sta->eapol_sm);
+	return 0;
+}
+
+
+static int hostapd_ctrl_iface_eapol_set(struct hostapd_data *hapd, char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+	char *pos = cmd, *param;
+
+	if (hwaddr_aton(pos, addr) || pos[17] != ' ')
+		return -1;
+	pos += 18;
+	param = pos;
+	pos = os_strchr(pos, ' ');
+	if (!pos)
+		return -1;
+	*pos++ = '\0';
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta || !sta->eapol_sm)
+		return -1;
+
+	return eapol_auth_set_conf(sta->eapol_sm, param, pos);
+}
+
+
+static int hostapd_ctrl_iface_log_level(struct hostapd_data *hapd, char *cmd,
+					char *buf, size_t buflen)
+{
+	char *pos, *end, *stamp;
+	int ret;
+
+	/* cmd: "LOG_LEVEL [<level>]" */
+	if (*cmd == '\0') {
+		pos = buf;
+		end = buf + buflen;
+		ret = os_snprintf(pos, end - pos, "Current level: %s\n"
+				  "Timestamp: %d\n",
+				  debug_level_str(wpa_debug_level),
+				  wpa_debug_timestamp);
+		if (os_snprintf_error(end - pos, ret))
+			ret = 0;
+
+		return ret;
+	}
+
+	while (*cmd == ' ')
+		cmd++;
+
+	stamp = os_strchr(cmd, ' ');
+	if (stamp) {
+		*stamp++ = '\0';
+		while (*stamp == ' ') {
+			stamp++;
+		}
+	}
+
+	if (os_strlen(cmd)) {
+		int level = str_to_debug_level(cmd);
+		if (level < 0)
+			return -1;
+		wpa_debug_level = level;
+	}
+
+	if (stamp && os_strlen(stamp))
+		wpa_debug_timestamp = atoi(stamp);
+
+	os_memcpy(buf, "OK\n", 3);
+	return 3;
+}
+
+
+#ifdef NEED_AP_MLME
+static int hostapd_ctrl_iface_track_sta_list(struct hostapd_data *hapd,
+					     char *buf, size_t buflen)
+{
+	struct hostapd_iface *iface = hapd->iface;
+	char *pos, *end;
+	struct hostapd_sta_info *info;
+	struct os_reltime now;
+
+	if (!iface->num_sta_seen)
+		return 0;
+
+	sta_track_expire(iface, 0);
+
+	pos = buf;
+	end = buf + buflen;
+
+	os_get_reltime(&now);
+	dl_list_for_each_reverse(info, &iface->sta_seen,
+				 struct hostapd_sta_info, list) {
+		struct os_reltime age;
+		int ret;
+
+		os_reltime_sub(&now, &info->last_seen, &age);
+		ret = os_snprintf(pos, end - pos, MACSTR " %u\n",
+				  MAC2STR(info->addr), (unsigned int) age.sec);
+		if (os_snprintf_error(end - pos, ret))
+			break;
+		pos += ret;
+	}
+
+	return pos - buf;
+}
+#endif /* NEED_AP_MLME */
+
+
+static int hostapd_ctrl_iface_req_lci(struct hostapd_data *hapd,
+				      const char *cmd)
+{
+	u8 addr[ETH_ALEN];
+
+	if (hwaddr_aton(cmd, addr)) {
+		wpa_printf(MSG_INFO, "CTRL: REQ_LCI: Invalid MAC address");
+		return -1;
+	}
+
+	return hostapd_send_lci_req(hapd, addr);
+}
+
+
+static int hostapd_ctrl_iface_req_range(struct hostapd_data *hapd, char *cmd)
+{
+	u8 addr[ETH_ALEN];
+	char *token, *context = NULL;
+	int random_interval, min_ap;
+	u8 responders[ETH_ALEN * RRM_RANGE_REQ_MAX_RESPONDERS];
+	unsigned int n_responders;
+
+	token = str_token(cmd, " ", &context);
+	if (!token || hwaddr_aton(token, addr)) {
+		wpa_printf(MSG_INFO,
+			   "CTRL: REQ_RANGE - Bad destination address");
+		return -1;
+	}
+
+	token = str_token(cmd, " ", &context);
+	if (!token)
+		return -1;
+
+	random_interval = atoi(token);
+	if (random_interval < 0 || random_interval > 0xffff)
+		return -1;
+
+	token = str_token(cmd, " ", &context);
+	if (!token)
+		return -1;
+
+	min_ap = atoi(token);
+	if (min_ap <= 0 || min_ap > WLAN_RRM_RANGE_REQ_MAX_MIN_AP)
+		return -1;
+
+	n_responders = 0;
+	while ((token = str_token(cmd, " ", &context))) {
+		if (n_responders == RRM_RANGE_REQ_MAX_RESPONDERS) {
+			wpa_printf(MSG_INFO,
+				   "CTRL: REQ_RANGE: Too many responders");
+			return -1;
+		}
+
+		if (hwaddr_aton(token, responders + n_responders * ETH_ALEN)) {
+			wpa_printf(MSG_INFO,
+				   "CTRL: REQ_RANGE: Bad responder address");
+			return -1;
+		}
+
+		n_responders++;
+	}
+
+	if (!n_responders) {
+		wpa_printf(MSG_INFO,
+			   "CTRL: REQ_RANGE - No FTM responder address");
+		return -1;
+	}
+
+	return hostapd_send_range_req(hapd, addr, random_interval, min_ap,
+				      responders, n_responders);
+}
+
+
+static int hostapd_ctrl_iface_set_neighbor(struct hostapd_data *hapd, char *buf)
+{
+	struct wpa_ssid_value ssid;
+	u8 bssid[ETH_ALEN];
+	struct wpabuf *nr, *lci = NULL, *civic = NULL;
+	char *tmp;
+	int ret;
+
+	if (!(hapd->conf->radio_measurements[0] &
+	      WLAN_RRM_CAPS_NEIGHBOR_REPORT)) {
+		wpa_printf(MSG_ERROR,
+			   "CTRL: SET_NEIGHBOR: Neighbor report is not enabled");
+		return -1;
+	}
+
+	if (hwaddr_aton(buf, bssid)) {
+		wpa_printf(MSG_ERROR, "CTRL: SET_NEIGHBOR: Bad BSSID");
+		return -1;
+	}
+
+	tmp = os_strstr(buf, "ssid=");
+	if (!tmp || ssid_parse(tmp + 5, &ssid)) {
+		wpa_printf(MSG_ERROR,
+			   "CTRL: SET_NEIGHBOR: Bad or missing SSID");
+		return -1;
+	}
+	buf = os_strchr(tmp + 6, tmp[5] == '"' ? '"' : ' ');
+	if (!buf)
+		return -1;
+
+	tmp = os_strstr(buf, "nr=");
+	if (!tmp) {
+		wpa_printf(MSG_ERROR,
+			   "CTRL: SET_NEIGHBOR: Missing Neighbor Report element");
+		return -1;
+	}
+
+	buf = os_strchr(tmp, ' ');
+	if (buf)
+		*buf++ = '\0';
+
+	nr = wpabuf_parse_bin(tmp + 3);
+	if (!nr) {
+		wpa_printf(MSG_ERROR,
+			   "CTRL: SET_NEIGHBOR: Bad Neighbor Report element");
+		return -1;
+	}
+
+	if (!buf)
+		goto set;
+
+	tmp = os_strstr(buf, "lci=");
+	if (tmp) {
+		buf = os_strchr(tmp, ' ');
+		if (buf)
+			*buf++ = '\0';
+		lci = wpabuf_parse_bin(tmp + 4);
+		if (!lci) {
+			wpa_printf(MSG_ERROR,
+				   "CTRL: SET_NEIGHBOR: Bad LCI subelement");
+			wpabuf_free(nr);
+			return -1;
+		}
+	}
+
+	if (!buf)
+		goto set;
+
+	tmp = os_strstr(buf, "civic=");
+	if (tmp) {
+		buf = os_strchr(tmp, ' ');
+		if (buf)
+			*buf++ = '\0';
+		civic = wpabuf_parse_bin(tmp + 6);
+		if (!civic) {
+			wpa_printf(MSG_ERROR,
+				   "CTRL: SET_NEIGHBOR: Bad civic subelement");
+			wpabuf_free(nr);
+			wpabuf_free(lci);
+			return -1;
+		}
+	}
+
+set:
+	ret = hostapd_neighbor_set(hapd, bssid, &ssid, nr, lci, civic);
+
+	wpabuf_free(nr);
+	wpabuf_free(lci);
+	wpabuf_free(civic);
+
+	return ret;
+}
+
+
+static int hostapd_ctrl_iface_remove_neighbor(struct hostapd_data *hapd,
+					      char *buf)
+{
+	struct wpa_ssid_value ssid;
+	u8 bssid[ETH_ALEN];
+	char *tmp;
+
+	if (hwaddr_aton(buf, bssid)) {
+		wpa_printf(MSG_ERROR, "CTRL: REMOVE_NEIGHBOR: Bad BSSID");
+		return -1;
+	}
+
+	tmp = os_strstr(buf, "ssid=");
+	if (!tmp || ssid_parse(tmp + 5, &ssid)) {
+		wpa_printf(MSG_ERROR,
+			   "CTRL: REMOVE_NEIGHBORr: Bad or missing SSID");
+		return -1;
+	}
+
+	return hostapd_neighbor_remove(hapd, bssid, &ssid);
+}
+
+
+static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
+				     size_t buflen)
+{
+	int ret, i;
+	char *pos, *end;
+
+	ret = os_snprintf(buf, buflen, "%016llX:\n",
+			  (long long unsigned) iface->drv_flags);
+	if (os_snprintf_error(buflen, ret))
+		return -1;
+
+	pos = buf + ret;
+	end = buf + buflen;
+
+	for (i = 0; i < 64; i++) {
+		if (iface->drv_flags & (1LLU << i)) {
+			ret = os_snprintf(pos, end - pos, "%s\n",
+					  driver_flag_to_string(1LLU << i));
+			if (os_snprintf_error(end - pos, ret))
+				return -1;
+			pos += ret;
+		}
+	}
+
+	return pos - buf;
+}
+
+
+static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+					      char *buf, char *reply,
+					      int reply_size,
+					      struct sockaddr_storage *from,
+					      socklen_t fromlen)
+{
+	int reply_len, res;
+
+	os_memcpy(reply, "OK\n", 3);
+	reply_len = 3;
+
+	if (os_strcmp(buf, "PING") == 0) {
+		os_memcpy(reply, "PONG\n", 5);
+		reply_len = 5;
+	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
+		if (wpa_debug_reopen_file() < 0)
+			reply_len = -1;
+	} else if (os_strcmp(buf, "STATUS") == 0) {
+		reply_len = hostapd_ctrl_iface_status(hapd, reply,
+						      reply_size);
+	} else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
+		reply_len = hostapd_drv_status(hapd, reply, reply_size);
+	} else if (os_strcmp(buf, "MIB") == 0) {
+		reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
+		if (reply_len >= 0) {
+			res = wpa_get_mib(hapd->wpa_auth, reply + reply_len,
+					  reply_size - reply_len);
+			if (res < 0)
+				reply_len = -1;
+			else
+				reply_len += res;
+		}
+		if (reply_len >= 0) {
+			res = ieee802_1x_get_mib(hapd, reply + reply_len,
+						 reply_size - reply_len);
+			if (res < 0)
+				reply_len = -1;
+			else
+				reply_len += res;
+		}
+#ifndef CONFIG_NO_RADIUS
+		if (reply_len >= 0) {
+			res = radius_client_get_mib(hapd->radius,
+						    reply + reply_len,
+						    reply_size - reply_len);
+			if (res < 0)
+				reply_len = -1;
+			else
+				reply_len += res;
+		}
+#endif /* CONFIG_NO_RADIUS */
+	} else if (os_strncmp(buf, "MIB ", 4) == 0) {
+		reply_len = hostapd_ctrl_iface_mib(hapd, reply, reply_size,
+						   buf + 4);
+	} else if (os_strcmp(buf, "STA-FIRST") == 0) {
+		reply_len = hostapd_ctrl_iface_sta_first(hapd, reply,
+							 reply_size);
+	} else if (os_strncmp(buf, "STA ", 4) == 0) {
+		reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply,
+						   reply_size);
+	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
+		reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
+							reply_size);
+	} else if (os_strcmp(buf, "ATTACH") == 0) {
+		if (hostapd_ctrl_iface_attach(hapd, from, fromlen))
+			reply_len = -1;
+	} else if (os_strcmp(buf, "DETACH") == 0) {
+		if (hostapd_ctrl_iface_detach(hapd, from, fromlen))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "LEVEL ", 6) == 0) {
+		if (hostapd_ctrl_iface_level(hapd, from, fromlen,
+						    buf + 6))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "NEW_STA ", 8) == 0) {
+		if (hostapd_ctrl_iface_new_sta(hapd, buf + 8))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
+		if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
+		if (hostapd_ctrl_iface_disassociate(hapd, buf + 13))
+			reply_len = -1;
+#ifdef CONFIG_TAXONOMY
+	} else if (os_strncmp(buf, "SIGNATURE ", 10) == 0) {
+		reply_len = hostapd_ctrl_iface_signature(hapd, buf + 10,
+							 reply, reply_size);
+#endif /* CONFIG_TAXONOMY */
+	} else if (os_strncmp(buf, "POLL_STA ", 9) == 0) {
+		if (hostapd_ctrl_iface_poll_sta(hapd, buf + 9))
+			reply_len = -1;
+	} else if (os_strcmp(buf, "STOP_AP") == 0) {
+		if (hostapd_ctrl_iface_stop_ap(hapd))
+			reply_len = -1;
+#ifdef CONFIG_IEEE80211W
+#ifdef NEED_AP_MLME
+	} else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) {
+		if (hostapd_ctrl_iface_sa_query(hapd, buf + 9))
+			reply_len = -1;
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_WPS
+	} else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) {
+		if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) {
+		reply_len = hostapd_ctrl_iface_wps_check_pin(
+			hapd, buf + 14, reply, reply_size);
+	} else if (os_strcmp(buf, "WPS_PBC") == 0) {
+		if (hostapd_wps_button_pushed(hapd, NULL))
+			reply_len = -1;
+	} else if (os_strcmp(buf, "WPS_CANCEL") == 0) {
+		if (hostapd_wps_cancel(hapd))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
+		reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
+							  reply, reply_size);
+	} else if (os_strncmp(buf, "WPS_CONFIG ", 11) == 0) {
+		if (hostapd_ctrl_iface_wps_config(hapd, buf + 11) < 0)
+			reply_len = -1;
+	} else if (os_strncmp(buf, "WPS_GET_STATUS", 13) == 0) {
+		reply_len = hostapd_ctrl_iface_wps_get_status(hapd, reply,
+							      reply_size);
+#ifdef CONFIG_WPS_NFC
+	} else if (os_strncmp(buf, "WPS_NFC_TAG_READ ", 17) == 0) {
+		if (hostapd_ctrl_iface_wps_nfc_tag_read(hapd, buf + 17))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "WPS_NFC_CONFIG_TOKEN ", 21) == 0) {
+		reply_len = hostapd_ctrl_iface_wps_nfc_config_token(
+			hapd, buf + 21, reply, reply_size);
+	} else if (os_strncmp(buf, "WPS_NFC_TOKEN ", 14) == 0) {
+		reply_len = hostapd_ctrl_iface_wps_nfc_token(
+			hapd, buf + 14, reply, reply_size);
+	} else if (os_strncmp(buf, "NFC_GET_HANDOVER_SEL ", 21) == 0) {
+		reply_len = hostapd_ctrl_iface_nfc_get_handover_sel(
+			hapd, buf + 21, reply, reply_size);
+	} else if (os_strncmp(buf, "NFC_REPORT_HANDOVER ", 20) == 0) {
+		if (hostapd_ctrl_iface_nfc_report_handover(hapd, buf + 20))
+			reply_len = -1;
+#endif /* CONFIG_WPS_NFC */
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_INTERWORKING
+	} else if (os_strncmp(buf, "SET_QOS_MAP_SET ", 16) == 0) {
+		if (hostapd_ctrl_iface_set_qos_map_set(hapd, buf + 16))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "SEND_QOS_MAP_CONF ", 18) == 0) {
+		if (hostapd_ctrl_iface_send_qos_map_conf(hapd, buf + 18))
+			reply_len = -1;
+#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_HS20
+	} else if (os_strncmp(buf, "HS20_WNM_NOTIF ", 15) == 0) {
+		if (hostapd_ctrl_iface_hs20_wnm_notif(hapd, buf + 15))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "HS20_DEAUTH_REQ ", 16) == 0) {
+		if (hostapd_ctrl_iface_hs20_deauth_req(hapd, buf + 16))
+			reply_len = -1;
+#endif /* CONFIG_HS20 */
+#ifdef CONFIG_WNM
+	} else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
+		if (hostapd_ctrl_iface_disassoc_imminent(hapd, buf + 18))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "ESS_DISASSOC ", 13) == 0) {
+		if (hostapd_ctrl_iface_ess_disassoc(hapd, buf + 13))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
+		if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
+			reply_len = -1;
+#endif /* CONFIG_WNM */
+	} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
+		reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
+							  reply_size);
+	} else if (os_strncmp(buf, "SET ", 4) == 0) {
+		if (hostapd_ctrl_iface_set(hapd, buf + 4))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "GET ", 4) == 0) {
+		reply_len = hostapd_ctrl_iface_get(hapd, buf + 4, reply,
+						   reply_size);
+	} else if (os_strncmp(buf, "ENABLE", 6) == 0) {
+		if (hostapd_ctrl_iface_enable(hapd->iface))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "RELOAD", 6) == 0) {
+		if (hostapd_ctrl_iface_reload(hapd->iface))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "DISABLE", 7) == 0) {
+		if (hostapd_ctrl_iface_disable(hapd->iface))
+			reply_len = -1;
+	} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
+		if (ieee802_11_set_beacon(hapd))
+			reply_len = -1;
+#ifdef CONFIG_TESTING_OPTIONS
+	} else if (os_strncmp(buf, "RADAR ", 6) == 0) {
+		if (hostapd_ctrl_iface_radar(hapd, buf + 6))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "MGMT_TX ", 8) == 0) {
+		if (hostapd_ctrl_iface_mgmt_tx(hapd, buf + 8))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "EAPOL_RX ", 9) == 0) {
+		if (hostapd_ctrl_iface_eapol_rx(hapd, buf + 9) < 0)
+			reply_len = -1;
+	} else if (os_strncmp(buf, "DATA_TEST_CONFIG ", 17) == 0) {
+		if (hostapd_ctrl_iface_data_test_config(hapd, buf + 17) < 0)
+			reply_len = -1;
+	} else if (os_strncmp(buf, "DATA_TEST_TX ", 13) == 0) {
+		if (hostapd_ctrl_iface_data_test_tx(hapd, buf + 13) < 0)
+			reply_len = -1;
+	} else if (os_strncmp(buf, "DATA_TEST_FRAME ", 16) == 0) {
+		if (hostapd_ctrl_iface_data_test_frame(hapd, buf + 16) < 0)
+			reply_len = -1;
+	} else if (os_strncmp(buf, "TEST_ALLOC_FAIL ", 16) == 0) {
+		if (hostapd_ctrl_test_alloc_fail(hapd, buf + 16) < 0)
+			reply_len = -1;
+	} else if (os_strcmp(buf, "GET_ALLOC_FAIL") == 0) {
+		reply_len = hostapd_ctrl_get_alloc_fail(hapd, reply,
+							reply_size);
+	} else if (os_strncmp(buf, "TEST_FAIL ", 10) == 0) {
+		if (hostapd_ctrl_test_fail(hapd, buf + 10) < 0)
+			reply_len = -1;
+	} else if (os_strcmp(buf, "GET_FAIL") == 0) {
+		reply_len = hostapd_ctrl_get_fail(hapd, reply, reply_size);
+#endif /* CONFIG_TESTING_OPTIONS */
+	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
+		if (hostapd_ctrl_iface_chan_switch(hapd->iface, buf + 12))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
+		reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
+						      reply_size);
+	} else if (os_strcmp(buf, "ERP_FLUSH") == 0) {
+		ieee802_1x_erp_flush(hapd);
+#ifdef RADIUS_SERVER
+		radius_server_erp_flush(hapd->radius_srv);
+#endif /* RADIUS_SERVER */
+	} else if (os_strncmp(buf, "EAPOL_REAUTH ", 13) == 0) {
+		if (hostapd_ctrl_iface_eapol_reauth(hapd, buf + 13))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "EAPOL_SET ", 10) == 0) {
+		if (hostapd_ctrl_iface_eapol_set(hapd, buf + 10))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
+		reply_len = hostapd_ctrl_iface_log_level(
+			hapd, buf + 9, reply, reply_size);
+#ifdef NEED_AP_MLME
+	} else if (os_strcmp(buf, "TRACK_STA_LIST") == 0) {
+		reply_len = hostapd_ctrl_iface_track_sta_list(
+			hapd, reply, reply_size);
+#endif /* NEED_AP_MLME */
+	} else if (os_strcmp(buf, "PMKSA") == 0) {
+		reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply,
+							  reply_size);
+	} else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) {
+		hostapd_ctrl_iface_pmksa_flush(hapd);
+	} else if (os_strncmp(buf, "SET_NEIGHBOR ", 13) == 0) {
+		if (hostapd_ctrl_iface_set_neighbor(hapd, buf + 13))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "REMOVE_NEIGHBOR ", 16) == 0) {
+		if (hostapd_ctrl_iface_remove_neighbor(hapd, buf + 16))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "REQ_LCI ", 8) == 0) {
+		if (hostapd_ctrl_iface_req_lci(hapd, buf + 8))
+			reply_len = -1;
+	} else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) {
+		if (hostapd_ctrl_iface_req_range(hapd, buf + 10))
+			reply_len = -1;
+	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
+		reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
+						      reply_size);
+	} else {
+		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+		reply_len = 16;
+	}
+
+	if (reply_len < 0) {
+		os_memcpy(reply, "FAIL\n", 5);
+		reply_len = 5;
+	}
+
+	return reply_len;
+}
+
+
+static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
+				       void *sock_ctx)
+{
+	struct hostapd_data *hapd = eloop_ctx;
+	char buf[4096];
+	int res;
+	struct sockaddr_storage from;
+	socklen_t fromlen = sizeof(from);
+	char *reply, *pos = buf;
+	const int reply_size = 4096;
+	int reply_len;
+	int level = MSG_DEBUG;
+#ifdef CONFIG_CTRL_IFACE_UDP
+	unsigned char lcookie[COOKIE_LEN];
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+	res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
+		       (struct sockaddr *) &from, &fromlen);
+	if (res < 0) {
+		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
+			   strerror(errno));
+		return;
+	}
+	buf[res] = '\0';
+
+	reply = os_malloc(reply_size);
+	if (reply == NULL) {
+		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
+			   fromlen) < 0) {
+			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
+				   strerror(errno));
+		}
+		return;
+	}
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+	if (os_strcmp(buf, "GET_COOKIE") == 0) {
+		os_memcpy(reply, "COOKIE=", 7);
+		wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
+				 cookie, COOKIE_LEN);
+		reply_len = 7 + 2 * COOKIE_LEN;
+		goto done;
+	}
+
+	if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
+	    hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
+		wpa_printf(MSG_DEBUG,
+			   "CTRL: No cookie in the request - drop request");
+		os_free(reply);
+		return;
+	}
+
+	if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) {
+		wpa_printf(MSG_DEBUG,
+			   "CTRL: Invalid cookie in the request - drop request");
+		os_free(reply);
+		return;
+	}
+
+	pos = buf + 7 + 2 * COOKIE_LEN;
+	while (*pos == ' ')
+		pos++;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+	if (os_strcmp(pos, "PING") == 0)
+		level = MSG_EXCESSIVE;
+	wpa_hexdump_ascii(level, "RX ctrl_iface", pos, res);
+
+	reply_len = hostapd_ctrl_iface_receive_process(hapd, pos,
+						       reply, reply_size,
+						       &from, fromlen);
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+done:
+#endif /* CONFIG_CTRL_IFACE_UDP */
+	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
+		   fromlen) < 0) {
+		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
+			   strerror(errno));
+	}
+	os_free(reply);
+}
+
+
+#ifndef CONFIG_CTRL_IFACE_UDP
+static char * hostapd_ctrl_iface_path(struct hostapd_data *hapd)
+{
+	char *buf;
+	size_t len;
+
+	if (hapd->conf->ctrl_interface == NULL)
+		return NULL;
+
+	len = os_strlen(hapd->conf->ctrl_interface) +
+		os_strlen(hapd->conf->iface) + 2;
+	buf = os_malloc(len);
+	if (buf == NULL)
+		return NULL;
+
+	os_snprintf(buf, len, "%s/%s",
+		    hapd->conf->ctrl_interface, hapd->conf->iface);
+	buf[len - 1] = '\0';
+	return buf;
+}
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+
+static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
+				      enum wpa_msg_type type,
+				      const char *txt, size_t len)
+{
+	struct hostapd_data *hapd = ctx;
+	if (hapd == NULL)
+		return;
+	hostapd_ctrl_iface_send(hapd, level, type, txt, len);
+}
+
+
+int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
+{
+#ifdef CONFIG_CTRL_IFACE_UDP
+	int port = HOSTAPD_CTRL_IFACE_PORT;
+	char p[32] = { 0 };
+	char port_str[40], *tmp;
+	char *pos;
+	struct addrinfo hints = { 0 }, *res, *saveres;
+	int n;
+
+	if (hapd->ctrl_sock > -1) {
+		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
+		return 0;
+	}
+
+	if (hapd->conf->ctrl_interface == NULL)
+		return 0;
+
+	pos = os_strstr(hapd->conf->ctrl_interface, "udp:");
+	if (pos) {
+		pos += 4;
+		port = atoi(pos);
+		if (port <= 0) {
+			wpa_printf(MSG_ERROR, "Invalid ctrl_iface UDP port");
+			goto fail;
+		}
+	}
+
+	dl_list_init(&hapd->ctrl_dst);
+	hapd->ctrl_sock = -1;
+	os_get_random(cookie, COOKIE_LEN);
+
+#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
+	hints.ai_flags = AI_PASSIVE;
+#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
+
+#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
+	hints.ai_family = AF_INET6;
+#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
+	hints.ai_family = AF_INET;
+#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
+	hints.ai_socktype = SOCK_DGRAM;
+
+try_again:
+	os_snprintf(p, sizeof(p), "%d", port);
+	n = getaddrinfo(NULL, p, &hints, &res);
+	if (n) {
+		wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
+		goto fail;
+	}
+
+	saveres = res;
+	hapd->ctrl_sock = socket(res->ai_family, res->ai_socktype,
+				 res->ai_protocol);
+	if (hapd->ctrl_sock < 0) {
+		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
+		goto fail;
+	}
+
+	if (bind(hapd->ctrl_sock, res->ai_addr, res->ai_addrlen) < 0) {
+		port--;
+		if ((HOSTAPD_CTRL_IFACE_PORT - port) <
+		    HOSTAPD_CTRL_IFACE_PORT_LIMIT && !pos)
+			goto try_again;
+		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
+		goto fail;
+	}
+
+	freeaddrinfo(saveres);
+
+	os_snprintf(port_str, sizeof(port_str), "udp:%d", port);
+	tmp = os_strdup(port_str);
+	if (tmp) {
+		os_free(hapd->conf->ctrl_interface);
+		hapd->conf->ctrl_interface = tmp;
+	}
+	wpa_printf(MSG_DEBUG, "ctrl_iface_init UDP port: %d", port);
+
+	if (eloop_register_read_sock(hapd->ctrl_sock,
+				     hostapd_ctrl_iface_receive, hapd, NULL) <
+	    0) {
+		hostapd_ctrl_iface_deinit(hapd);
+		return -1;
+	}
+
+	hapd->msg_ctx = hapd;
+	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
+	return 0;
+
+fail:
+	if (hapd->ctrl_sock >= 0)
+		close(hapd->ctrl_sock);
+	return -1;
+#else /* CONFIG_CTRL_IFACE_UDP */
+	struct sockaddr_un addr;
+	int s = -1;
+	char *fname = NULL;
+
+	if (hapd->ctrl_sock > -1) {
+		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
+		return 0;
+	}
+
+	dl_list_init(&hapd->ctrl_dst);
+
+	if (hapd->conf->ctrl_interface == NULL)
+		return 0;
+
+	if (mkdir(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
+		if (errno == EEXIST) {
+			wpa_printf(MSG_DEBUG, "Using existing control "
+				   "interface directory.");
+		} else {
+			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
+				   strerror(errno));
+			goto fail;
+		}
+	}
+
+	if (hapd->conf->ctrl_interface_gid_set &&
+	    chown(hapd->conf->ctrl_interface, -1,
+		  hapd->conf->ctrl_interface_gid) < 0) {
+		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
+			   strerror(errno));
+		return -1;
+	}
+
+	if (!hapd->conf->ctrl_interface_gid_set &&
+	    hapd->iface->interfaces->ctrl_iface_group &&
+	    chown(hapd->conf->ctrl_interface, -1,
+		  hapd->iface->interfaces->ctrl_iface_group) < 0) {
+		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
+			   strerror(errno));
+		return -1;
+	}
+
+#ifdef ANDROID
+	/*
+	 * Android is using umask 0077 which would leave the control interface
+	 * directory without group access. This breaks things since Wi-Fi
+	 * framework assumes that this directory can be accessed by other
+	 * applications in the wifi group. Fix this by adding group access even
+	 * if umask value would prevent this.
+	 */
+	if (chmod(hapd->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
+		wpa_printf(MSG_ERROR, "CTRL: Could not chmod directory: %s",
+			   strerror(errno));
+		/* Try to continue anyway */
+	}
+#endif /* ANDROID */
+
+	if (os_strlen(hapd->conf->ctrl_interface) + 1 +
+	    os_strlen(hapd->conf->iface) >= sizeof(addr.sun_path))
+		goto fail;
+
+	s = socket(PF_UNIX, SOCK_DGRAM, 0);
+	if (s < 0) {
+		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
+		goto fail;
+	}
+
+	os_memset(&addr, 0, sizeof(addr));
+#ifdef __FreeBSD__
+	addr.sun_len = sizeof(addr);
+#endif /* __FreeBSD__ */
+	addr.sun_family = AF_UNIX;
+	fname = hostapd_ctrl_iface_path(hapd);
+	if (fname == NULL)
+		goto fail;
+	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
+	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
+			   strerror(errno));
+		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
+				   " allow connections - assuming it was left"
+				   "over from forced program termination");
+			if (unlink(fname) < 0) {
+				wpa_printf(MSG_ERROR,
+					   "Could not unlink existing ctrl_iface socket '%s': %s",
+					   fname, strerror(errno));
+				goto fail;
+			}
+			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
+			    0) {
+				wpa_printf(MSG_ERROR,
+					   "hostapd-ctrl-iface: bind(PF_UNIX): %s",
+					   strerror(errno));
+				goto fail;
+			}
+			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
+				   "ctrl_iface socket '%s'", fname);
+		} else {
+			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
+				   "be in use - cannot override it");
+			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
+				   "not used anymore", fname);
+			os_free(fname);
+			fname = NULL;
+			goto fail;
+		}
+	}
+
+	if (hapd->conf->ctrl_interface_gid_set &&
+	    chown(fname, -1, hapd->conf->ctrl_interface_gid) < 0) {
+		wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
+			   strerror(errno));
+		goto fail;
+	}
+
+	if (!hapd->conf->ctrl_interface_gid_set &&
+	    hapd->iface->interfaces->ctrl_iface_group &&
+	    chown(fname, -1, hapd->iface->interfaces->ctrl_iface_group) < 0) {
+		wpa_printf(MSG_ERROR, "chown[ctrl_interface/ifname]: %s",
+			   strerror(errno));
+		goto fail;
+	}
+
+	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
+		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
+			   strerror(errno));
+		goto fail;
+	}
+	os_free(fname);
+
+	hapd->ctrl_sock = s;
+	if (eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
+				     NULL) < 0) {
+		hostapd_ctrl_iface_deinit(hapd);
+		return -1;
+	}
+	hapd->msg_ctx = hapd;
+	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
+
+	return 0;
+
+fail:
+	if (s >= 0)
+		close(s);
+	if (fname) {
+		unlink(fname);
+		os_free(fname);
+	}
+	return -1;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+}
+
+
+void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
+{
+	struct wpa_ctrl_dst *dst, *prev;
+
+	if (hapd->ctrl_sock > -1) {
+#ifndef CONFIG_CTRL_IFACE_UDP
+		char *fname;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
+
+		eloop_unregister_read_sock(hapd->ctrl_sock);
+		close(hapd->ctrl_sock);
+		hapd->ctrl_sock = -1;
+#ifndef CONFIG_CTRL_IFACE_UDP
+		fname = hostapd_ctrl_iface_path(hapd);
+		if (fname)
+			unlink(fname);
+		os_free(fname);
+
+		if (hapd->conf->ctrl_interface &&
+		    rmdir(hapd->conf->ctrl_interface) < 0) {
+			if (errno == ENOTEMPTY) {
+				wpa_printf(MSG_DEBUG, "Control interface "
+					   "directory not empty - leaving it "
+					   "behind");
+			} else {
+				wpa_printf(MSG_ERROR,
+					   "rmdir[ctrl_interface=%s]: %s",
+					   hapd->conf->ctrl_interface,
+					   strerror(errno));
+			}
+		}
+#endif /* !CONFIG_CTRL_IFACE_UDP */
+	}
+
+	dl_list_for_each_safe(dst, prev, &hapd->ctrl_dst, struct wpa_ctrl_dst,
+			      list)
+		os_free(dst);
+
+#ifdef CONFIG_TESTING_OPTIONS
+	l2_packet_deinit(hapd->l2_test);
+	hapd->l2_test = NULL;
+#endif /* CONFIG_TESTING_OPTIONS */
+}
+
+
+static int hostapd_ctrl_iface_add(struct hapd_interfaces *interfaces,
+				  char *buf)
+{
+	if (hostapd_add_iface(interfaces, buf) < 0) {
+		wpa_printf(MSG_ERROR, "Adding interface %s failed", buf);
+		return -1;
+	}
+	return 0;
+}
+
+
+static int hostapd_ctrl_iface_remove(struct hapd_interfaces *interfaces,
+				     char *buf)
+{
+	if (hostapd_remove_iface(interfaces, buf) < 0) {
+		wpa_printf(MSG_ERROR, "Removing interface %s failed", buf);
+		return -1;
+	}
+	return 0;
+}
+
+
+static int hostapd_global_ctrl_iface_attach(struct hapd_interfaces *interfaces,
+					    struct sockaddr_storage *from,
+					    socklen_t fromlen)
+{
+	return ctrl_iface_attach(&interfaces->global_ctrl_dst, from, fromlen);
+}
+
+
+static int hostapd_global_ctrl_iface_detach(struct hapd_interfaces *interfaces,
+					    struct sockaddr_storage *from,
+					    socklen_t fromlen)
+{
+	return ctrl_iface_detach(&interfaces->global_ctrl_dst, from, fromlen);
+}
+
+
+static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces)
+{
+#ifdef CONFIG_WPS_TESTING
+	wps_version_number = 0x20;
+	wps_testing_dummy_cred = 0;
+	wps_corrupt_pkhash = 0;
+#endif /* CONFIG_WPS_TESTING */
+}
+
+
+#ifdef CONFIG_FST
+
+static int
+hostapd_global_ctrl_iface_fst_attach(struct hapd_interfaces *interfaces,
+				     const char *cmd)
+{
+	char ifname[IFNAMSIZ + 1];
+	struct fst_iface_cfg cfg;
+	struct hostapd_data *hapd;
+	struct fst_wpa_obj iface_obj;
+
+	if (!fst_parse_attach_command(cmd, ifname, sizeof(ifname), &cfg)) {
+		hapd = hostapd_get_iface(interfaces, ifname);
+		if (hapd) {
+			if (hapd->iface->fst) {
+				wpa_printf(MSG_INFO, "FST: Already attached");
+				return -1;
+			}
+			fst_hostapd_fill_iface_obj(hapd, &iface_obj);
+			hapd->iface->fst = fst_attach(ifname, hapd->own_addr,
+						      &iface_obj, &cfg);
+			if (hapd->iface->fst)
+				return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+
+static int
+hostapd_global_ctrl_iface_fst_detach(struct hapd_interfaces *interfaces,
+				     const char *cmd)
+{
+	char ifname[IFNAMSIZ + 1];
+	struct hostapd_data * hapd;
+
+	if (!fst_parse_detach_command(cmd, ifname, sizeof(ifname))) {
+		hapd = hostapd_get_iface(interfaces, ifname);
+		if (hapd) {
+			if (!fst_iface_detach(ifname)) {
+				hapd->iface->fst = NULL;
+				hapd->iface->fst_ies = NULL;
+				return 0;
+			}
+		}
+	}
+
+	return -EINVAL;
+}
+
+#endif /* CONFIG_FST */
+
+
+static struct hostapd_data *
+hostapd_interfaces_get_hapd(struct hapd_interfaces *interfaces,
+			    const char *ifname)
+{
+	size_t i, j;
+
+	for (i = 0; i < interfaces->count; i++) {
+		struct hostapd_iface *iface = interfaces->iface[i];
+
+		for (j = 0; j < iface->num_bss; j++) {
+			struct hostapd_data *hapd;
+
+			hapd = iface->bss[j];
+			if (os_strcmp(ifname, hapd->conf->iface) == 0)
+				return hapd;
+		}
+	}
+
+	return NULL;
+}
+
+
+static int hostapd_ctrl_iface_dup_param(struct hostapd_data *src_hapd,
+					struct hostapd_data *dst_hapd,
+					const char *param)
+{
+	int res;
+	char *value;
+
+	value = os_zalloc(HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
+	if (!value) {
+		wpa_printf(MSG_ERROR,
+			   "DUP: cannot allocate buffer to stringify %s",
+			   param);
+		goto error_return;
+	}
+
+	if (os_strcmp(param, "wpa") == 0) {
+		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%d",
+			    src_hapd->conf->wpa);
+	} else if (os_strcmp(param, "wpa_key_mgmt") == 0 &&
+		   src_hapd->conf->wpa_key_mgmt) {
+		res = hostapd_ctrl_iface_get_key_mgmt(
+			src_hapd, value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN);
+		if (os_snprintf_error(HOSTAPD_CLI_DUP_VALUE_MAX_LEN, res))
+			goto error_stringify;
+	} else if (os_strcmp(param, "wpa_pairwise") == 0 &&
+		   src_hapd->conf->wpa_pairwise) {
+		res = wpa_write_ciphers(value,
+					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
+					src_hapd->conf->wpa_pairwise, " ");
+		if (res < 0)
+			goto error_stringify;
+	} else if (os_strcmp(param, "rsn_pairwise") == 0 &&
+		   src_hapd->conf->rsn_pairwise) {
+		res = wpa_write_ciphers(value,
+					value + HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
+					src_hapd->conf->rsn_pairwise, " ");
+		if (res < 0)
+			goto error_stringify;
+	} else if (os_strcmp(param, "wpa_passphrase") == 0 &&
+		   src_hapd->conf->ssid.wpa_passphrase) {
+		os_snprintf(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN, "%s",
+			    src_hapd->conf->ssid.wpa_passphrase);
+	} else if (os_strcmp(param, "wpa_psk") == 0 &&
+		   src_hapd->conf->ssid.wpa_psk_set) {
+		wpa_snprintf_hex(value, HOSTAPD_CLI_DUP_VALUE_MAX_LEN,
+			src_hapd->conf->ssid.wpa_psk->psk, PMK_LEN);
+	} else {
+		wpa_printf(MSG_WARNING, "DUP: %s cannot be duplicated", param);
+		goto error_return;
+	}
+
+	res = hostapd_set_iface(dst_hapd->iconf, dst_hapd->conf, param, value);
+	os_free(value);
+	return res;
+
+error_stringify:
+	wpa_printf(MSG_ERROR, "DUP: cannot stringify %s", param);
+error_return:
+	os_free(value);
+	return -1;
+}
+
+
+static int
+hostapd_global_ctrl_iface_interfaces(struct hapd_interfaces *interfaces,
+				     const char *input,
+				     char *reply, int reply_size)
+{
+	size_t i, j;
+	int res;
+	char *pos, *end;
+	struct hostapd_iface *iface;
+	int show_ctrl = 0;
+
+	if (input)
+		show_ctrl = !!os_strstr(input, "ctrl");
+
+	pos = reply;
+	end = reply + reply_size;
+
+	for (i = 0; i < interfaces->count; i++) {
+		iface = interfaces->iface[i];
+
+		for (j = 0; j < iface->num_bss; j++) {
+			struct hostapd_bss_config *conf;
+
+			conf = iface->conf->bss[j];
+			if (show_ctrl)
+				res = os_snprintf(pos, end - pos,
+						  "%s ctrl_iface=%s\n",
+						  conf->iface,
+						  conf->ctrl_interface ?
+						  conf->ctrl_interface : "N/A");
+			else
+				res = os_snprintf(pos, end - pos, "%s\n",
+						  conf->iface);
+			if (os_snprintf_error(end - pos, res)) {
+				*pos = '\0';
+				return pos - reply;
+			}
+			pos += res;
+		}
+	}
+
+	return pos - reply;
+}
+
+
+static int
+hostapd_global_ctrl_iface_dup_network(struct hapd_interfaces *interfaces,
+				      char *cmd)
+{
+	char *p_start = cmd, *p_end;
+	struct hostapd_data *src_hapd, *dst_hapd;
+
+	/* cmd: "<src ifname> <dst ifname> <variable name> */
+
+	p_end = os_strchr(p_start, ' ');
+	if (!p_end) {
+		wpa_printf(MSG_ERROR, "DUP: no src ifname found in cmd: '%s'",
+			   cmd);
+		return -1;
+	}
+
+	*p_end = '\0';
+	src_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
+	if (!src_hapd) {
+		wpa_printf(MSG_ERROR, "DUP: no src ifname found: '%s'",
+			   p_start);
+		return -1;
+	}
+
+	p_start = p_end + 1;
+	p_end = os_strchr(p_start, ' ');
+	if (!p_end) {
+		wpa_printf(MSG_ERROR, "DUP: no dst ifname found in cmd: '%s'",
+			   cmd);
+		return -1;
+	}
+
+	*p_end = '\0';
+	dst_hapd = hostapd_interfaces_get_hapd(interfaces, p_start);
+	if (!dst_hapd) {
+		wpa_printf(MSG_ERROR, "DUP: no dst ifname found: '%s'",
+			   p_start);
+		return -1;
+	}
+
+	p_start = p_end + 1;
+	return hostapd_ctrl_iface_dup_param(src_hapd, dst_hapd, p_start);
+}
+
+
+static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces,
+					    const char *ifname,
+					    char *buf, char *reply,
+					    int reply_size,
+					    struct sockaddr_storage *from,
+					    socklen_t fromlen)
+{
+	struct hostapd_data *hapd;
+
+	hapd = hostapd_interfaces_get_hapd(interfaces, ifname);
+	if (hapd == NULL) {
+		int res;
+
+		res = os_snprintf(reply, reply_size, "FAIL-NO-IFNAME-MATCH\n");
+		if (os_snprintf_error(reply_size, res))
+			return -1;
+		return res;
+	}
+
+	return hostapd_ctrl_iface_receive_process(hapd, buf, reply,reply_size,
+						  from, fromlen);
+}
+
+
+static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
+					      void *sock_ctx)
+{
+	void *interfaces = eloop_ctx;
+	char buffer[256], *buf = buffer;
+	int res;
+	struct sockaddr_storage from;
+	socklen_t fromlen = sizeof(from);
+	char *reply;
+	int reply_len;
+	const int reply_size = 4096;
+#ifdef CONFIG_CTRL_IFACE_UDP
+	unsigned char lcookie[COOKIE_LEN];
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+	res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0,
+		       (struct sockaddr *) &from, &fromlen);
+	if (res < 0) {
+		wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s",
+			   strerror(errno));
+		return;
+	}
+	buf[res] = '\0';
+	wpa_printf(MSG_DEBUG, "Global ctrl_iface command: %s", buf);
+
+	reply = os_malloc(reply_size);
+	if (reply == NULL) {
+		if (sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
+			   fromlen) < 0) {
+			wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
+				   strerror(errno));
+		}
+		return;
+	}
+
+	os_memcpy(reply, "OK\n", 3);
+	reply_len = 3;
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+	if (os_strcmp(buf, "GET_COOKIE") == 0) {
+		os_memcpy(reply, "COOKIE=", 7);
+		wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
+				 gcookie, COOKIE_LEN);
+		reply_len = 7 + 2 * COOKIE_LEN;
+		goto send_reply;
+	}
+
+	if (os_strncmp(buf, "COOKIE=", 7) != 0 ||
+	    hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) {
+		wpa_printf(MSG_DEBUG,
+			   "CTRL: No cookie in the request - drop request");
+		os_free(reply);
+		return;
+	}
+
+	if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) {
+		wpa_printf(MSG_DEBUG,
+			   "CTRL: Invalid cookie in the request - drop request");
+		os_free(reply);
+		return;
+	}
+
+	buf += 7 + 2 * COOKIE_LEN;
+	while (*buf == ' ')
+		buf++;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+	if (os_strncmp(buf, "IFNAME=", 7) == 0) {
+		char *pos = os_strchr(buf + 7, ' ');
+
+		if (pos) {
+			*pos++ = '\0';
+			reply_len = hostapd_global_ctrl_iface_ifname(
+				interfaces, buf + 7, pos, reply, reply_size,
+				&from, fromlen);
+			goto send_reply;
+		}
+	}
+
+	if (os_strcmp(buf, "PING") == 0) {
+		os_memcpy(reply, "PONG\n", 5);
+		reply_len = 5;
+	} else if (os_strncmp(buf, "RELOG", 5) == 0) {
+		if (wpa_debug_reopen_file() < 0)
+			reply_len = -1;
+	} else if (os_strcmp(buf, "FLUSH") == 0) {
+		hostapd_ctrl_iface_flush(interfaces);
+	} else if (os_strncmp(buf, "ADD ", 4) == 0) {
+		if (hostapd_ctrl_iface_add(interfaces, buf + 4) < 0)
+			reply_len = -1;
+	} else if (os_strncmp(buf, "REMOVE ", 7) == 0) {
+		if (hostapd_ctrl_iface_remove(interfaces, buf + 7) < 0)
+			reply_len = -1;
+	} else if (os_strcmp(buf, "ATTACH") == 0) {
+		if (hostapd_global_ctrl_iface_attach(interfaces, &from,
+						     fromlen))
+			reply_len = -1;
+	} else if (os_strcmp(buf, "DETACH") == 0) {
+		if (hostapd_global_ctrl_iface_detach(interfaces, &from,
+			fromlen))
+			reply_len = -1;
+#ifdef CONFIG_MODULE_TESTS
+	} else if (os_strcmp(buf, "MODULE_TESTS") == 0) {
+		if (hapd_module_tests() < 0)
+			reply_len = -1;
+#endif /* CONFIG_MODULE_TESTS */
+#ifdef CONFIG_FST
+	} else if (os_strncmp(buf, "FST-ATTACH ", 11) == 0) {
+		if (!hostapd_global_ctrl_iface_fst_attach(interfaces, buf + 11))
+			reply_len = os_snprintf(reply, reply_size, "OK\n");
+		else
+			reply_len = -1;
+	} else if (os_strncmp(buf, "FST-DETACH ", 11) == 0) {
+		if (!hostapd_global_ctrl_iface_fst_detach(interfaces, buf + 11))
+			reply_len = os_snprintf(reply, reply_size, "OK\n");
+		else
+			reply_len = -1;
+	} else if (os_strncmp(buf, "FST-MANAGER ", 12) == 0) {
+		reply_len = fst_ctrl_iface_receive(buf + 12, reply, reply_size);
+#endif /* CONFIG_FST */
+	} else if (os_strncmp(buf, "DUP_NETWORK ", 12) == 0) {
+		if (!hostapd_global_ctrl_iface_dup_network(interfaces,
+							   buf + 12))
+			reply_len = os_snprintf(reply, reply_size, "OK\n");
+		else
+			reply_len = -1;
+	} else if (os_strncmp(buf, "INTERFACES", 10) == 0) {
+		reply_len = hostapd_global_ctrl_iface_interfaces(
+			interfaces, buf + 10, reply, sizeof(buffer));
+	} else if (os_strcmp(buf, "TERMINATE") == 0) {
+		eloop_terminate();
+	} else {
+		wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
+			   "ignored");
+		reply_len = -1;
+	}
+
+send_reply:
+	if (reply_len < 0) {
+		os_memcpy(reply, "FAIL\n", 5);
+		reply_len = 5;
+	}
+
+	if (sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
+		   fromlen) < 0) {
+		wpa_printf(MSG_DEBUG, "CTRL: sendto failed: %s",
+			   strerror(errno));
+	}
+	os_free(reply);
+}
+
+
+#ifndef CONFIG_CTRL_IFACE_UDP
+static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
+{
+	char *buf;
+	size_t len;
+
+	if (interface->global_iface_path == NULL)
+		return NULL;
+
+	len = os_strlen(interface->global_iface_path) +
+		os_strlen(interface->global_iface_name) + 2;
+	buf = os_malloc(len);
+	if (buf == NULL)
+		return NULL;
+
+	os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
+		    interface->global_iface_name);
+	buf[len - 1] = '\0';
+	return buf;
+}
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+
+int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
+{
+#ifdef CONFIG_CTRL_IFACE_UDP
+	int port = HOSTAPD_GLOBAL_CTRL_IFACE_PORT;
+	char p[32] = { 0 };
+	char *pos;
+	struct addrinfo hints = { 0 }, *res, *saveres;
+	int n;
+
+	if (interface->global_ctrl_sock > -1) {
+		wpa_printf(MSG_DEBUG, "ctrl_iface already exists!");
+		return 0;
+	}
+
+	if (interface->global_iface_path == NULL)
+		return 0;
+
+	pos = os_strstr(interface->global_iface_path, "udp:");
+	if (pos) {
+		pos += 4;
+		port = atoi(pos);
+		if (port <= 0) {
+			wpa_printf(MSG_ERROR, "Invalid global ctrl UDP port");
+			goto fail;
+		}
+	}
+
+	dl_list_init(&interface->global_ctrl_dst);
+	interface->global_ctrl_sock = -1;
+	os_get_random(gcookie, COOKIE_LEN);
+
+#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
+	hints.ai_flags = AI_PASSIVE;
+#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
+
+#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
+	hints.ai_family = AF_INET6;
+#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
+	hints.ai_family = AF_INET;
+#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
+	hints.ai_socktype = SOCK_DGRAM;
+
+try_again:
+	os_snprintf(p, sizeof(p), "%d", port);
+	n = getaddrinfo(NULL, p, &hints, &res);
+	if (n) {
+		wpa_printf(MSG_ERROR, "getaddrinfo(): %s", gai_strerror(n));
+		goto fail;
+	}
+
+	saveres = res;
+	interface->global_ctrl_sock = socket(res->ai_family, res->ai_socktype,
+					     res->ai_protocol);
+	if (interface->global_ctrl_sock < 0) {
+		wpa_printf(MSG_ERROR, "socket(PF_INET): %s", strerror(errno));
+		goto fail;
+	}
+
+	if (bind(interface->global_ctrl_sock, res->ai_addr, res->ai_addrlen) <
+	    0) {
+		port++;
+		if ((port - HOSTAPD_GLOBAL_CTRL_IFACE_PORT) <
+		    HOSTAPD_GLOBAL_CTRL_IFACE_PORT_LIMIT && !pos)
+			goto try_again;
+		wpa_printf(MSG_ERROR, "bind(AF_INET): %s", strerror(errno));
+		goto fail;
+	}
+
+	freeaddrinfo(saveres);
+
+	wpa_printf(MSG_DEBUG, "global ctrl_iface_init UDP port: %d", port);
+
+	if (eloop_register_read_sock(interface->global_ctrl_sock,
+				     hostapd_global_ctrl_iface_receive,
+				     interface, NULL) < 0) {
+		hostapd_global_ctrl_iface_deinit(interface);
+		return -1;
+	}
+
+	return 0;
+
+fail:
+	if (interface->global_ctrl_sock >= 0)
+		close(interface->global_ctrl_sock);
+	return -1;
+#else /* CONFIG_CTRL_IFACE_UDP */
+	struct sockaddr_un addr;
+	int s = -1;
+	char *fname = NULL;
+
+	if (interface->global_iface_path == NULL) {
+		wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
+		return 0;
+	}
+
+	if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
+		if (errno == EEXIST) {
+			wpa_printf(MSG_DEBUG, "Using existing control "
+				   "interface directory.");
+		} else {
+			wpa_printf(MSG_ERROR, "mkdir[ctrl_interface]: %s",
+				   strerror(errno));
+			goto fail;
+		}
+	} else if (interface->ctrl_iface_group &&
+		   chown(interface->global_iface_path, -1,
+			 interface->ctrl_iface_group) < 0) {
+		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
+			   strerror(errno));
+		goto fail;
+	}
+
+	if (os_strlen(interface->global_iface_path) + 1 +
+	    os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
+		goto fail;
+
+	s = socket(PF_UNIX, SOCK_DGRAM, 0);
+	if (s < 0) {
+		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
+		goto fail;
+	}
+
+	os_memset(&addr, 0, sizeof(addr));
+#ifdef __FreeBSD__
+	addr.sun_len = sizeof(addr);
+#endif /* __FreeBSD__ */
+	addr.sun_family = AF_UNIX;
+	fname = hostapd_global_ctrl_iface_path(interface);
+	if (fname == NULL)
+		goto fail;
+	os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
+	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
+			   strerror(errno));
+		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
+				   " allow connections - assuming it was left"
+				   "over from forced program termination");
+			if (unlink(fname) < 0) {
+				wpa_printf(MSG_ERROR,
+					   "Could not unlink existing ctrl_iface socket '%s': %s",
+					   fname, strerror(errno));
+				goto fail;
+			}
+			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
+			    0) {
+				wpa_printf(MSG_ERROR, "bind(PF_UNIX): %s",
+					   strerror(errno));
+				goto fail;
+			}
+			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
+				   "ctrl_iface socket '%s'", fname);
+		} else {
+			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
+				   "be in use - cannot override it");
+			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
+				   "not used anymore", fname);
+			os_free(fname);
+			fname = NULL;
+			goto fail;
+		}
+	}
+
+	if (interface->ctrl_iface_group &&
+	    chown(fname, -1, interface->ctrl_iface_group) < 0) {
+		wpa_printf(MSG_ERROR, "chown[ctrl_interface]: %s",
+			   strerror(errno));
+		goto fail;
+	}
+
+	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
+		wpa_printf(MSG_ERROR, "chmod[ctrl_interface/ifname]: %s",
+			   strerror(errno));
+		goto fail;
+	}
+	os_free(fname);
+
+	interface->global_ctrl_sock = s;
+	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
+				 interface, NULL);
+
+	return 0;
+
+fail:
+	if (s >= 0)
+		close(s);
+	if (fname) {
+		unlink(fname);
+		os_free(fname);
+	}
+	return -1;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+}
+
+
+void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
+{
+#ifndef CONFIG_CTRL_IFACE_UDP
+	char *fname = NULL;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+	struct wpa_ctrl_dst *dst, *prev;
+
+	if (interfaces->global_ctrl_sock > -1) {
+		eloop_unregister_read_sock(interfaces->global_ctrl_sock);
+		close(interfaces->global_ctrl_sock);
+		interfaces->global_ctrl_sock = -1;
+#ifndef CONFIG_CTRL_IFACE_UDP
+		fname = hostapd_global_ctrl_iface_path(interfaces);
+		if (fname) {
+			unlink(fname);
+			os_free(fname);
+		}
+
+		if (interfaces->global_iface_path &&
+		    rmdir(interfaces->global_iface_path) < 0) {
+			if (errno == ENOTEMPTY) {
+				wpa_printf(MSG_DEBUG, "Control interface "
+					   "directory not empty - leaving it "
+					   "behind");
+			} else {
+				wpa_printf(MSG_ERROR,
+					   "rmdir[ctrl_interface=%s]: %s",
+					   interfaces->global_iface_path,
+					   strerror(errno));
+			}
+		}
+#endif /* CONFIG_CTRL_IFACE_UDP */
+	}
+
+	os_free(interfaces->global_iface_path);
+	interfaces->global_iface_path = NULL;
+
+	dl_list_for_each_safe(dst, prev, &interfaces->global_ctrl_dst,
+			      struct wpa_ctrl_dst, list)
+		os_free(dst);
+}
+
+
+static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+				    enum wpa_msg_type type,
+				    const char *buf, size_t len)
+{
+	struct wpa_ctrl_dst *dst, *next;
+	struct dl_list *ctrl_dst;
+	struct msghdr msg;
+	int idx;
+	struct iovec io[2];
+	char levelstr[10];
+	int s;
+
+	if (type != WPA_MSG_ONLY_GLOBAL) {
+		s = hapd->ctrl_sock;
+		ctrl_dst = &hapd->ctrl_dst;
+	} else {
+		s = hapd->iface->interfaces->global_ctrl_sock;
+		ctrl_dst = &hapd->iface->interfaces->global_ctrl_dst;
+	}
+
+	if (s < 0 || dl_list_empty(ctrl_dst))
+		return;
+
+	os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
+	io[0].iov_base = levelstr;
+	io[0].iov_len = os_strlen(levelstr);
+	io[1].iov_base = (char *) buf;
+	io[1].iov_len = len;
+	os_memset(&msg, 0, sizeof(msg));
+	msg.msg_iov = io;
+	msg.msg_iovlen = 2;
+
+	idx = 0;
+	dl_list_for_each_safe(dst, next, ctrl_dst, struct wpa_ctrl_dst, list) {
+		if (level >= dst->debug_level) {
+			sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor send",
+				       &dst->addr, dst->addrlen);
+			msg.msg_name = &dst->addr;
+			msg.msg_namelen = dst->addrlen;
+			if (sendmsg(s, &msg, 0) < 0) {
+				int _errno = errno;
+				wpa_printf(MSG_INFO, "CTRL_IFACE monitor[%d]: "
+					   "%d - %s",
+					   idx, errno, strerror(errno));
+				dst->errors++;
+				if (dst->errors > 10 || _errno == ENOENT) {
+					if (type != WPA_MSG_ONLY_GLOBAL)
+						hostapd_ctrl_iface_detach(
+							hapd, &dst->addr,
+							dst->addrlen);
+					else
+						hostapd_global_ctrl_iface_detach(
+							hapd->iface->interfaces,
+							&dst->addr,
+							dst->addrlen);
+				}
+			} else
+				dst->errors = 0;
+		}
+		idx++;
+	}
+}
+
+#endif /* CONFIG_NATIVE_WINDOWS */

+ 49 - 0
EVSE/GPL/hostapd-2.6/hostapd/ctrl_iface.d

@@ -0,0 +1,49 @@
+ctrl_iface.o: ctrl_iface.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/eloop.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/module_tests.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/version.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ctrl_iface_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/crypto/tls.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eapol_auth/eapol_auth_sm.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius_client.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius_server.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/l2_packet/l2_packet.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/hostapd.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/vlan.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/ieee802_1x.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/wpa_auth.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/eapol_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/ieee802_11.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/wps_hostapd.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/ctrl_iface_ap.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/ap_drv_ops.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/hs20.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/wnm_ap.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/beacon.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/neighbor_db.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/rrm.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst_ctrl_iface.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst_ctrl_aux.h \
+ config_file.h ctrl_iface.h

+ 39 - 0
EVSE/GPL/hostapd-2.6/hostapd/ctrl_iface.h

@@ -0,0 +1,39 @@
+/*
+ * hostapd / UNIX domain socket -based control interface
+ * Copyright (c) 2004, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef CTRL_IFACE_H
+#define CTRL_IFACE_H
+
+#ifndef CONFIG_NO_CTRL_IFACE
+int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
+void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
+int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface);
+void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface);
+#else /* CONFIG_NO_CTRL_IFACE */
+static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
+{
+	return 0;
+}
+
+static inline void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
+{
+}
+
+static inline int
+hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
+{
+	return 0;
+}
+
+static inline void
+hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface)
+{
+}
+#endif /* CONFIG_NO_CTRL_IFACE */
+
+#endif /* CTRL_IFACE_H */

+ 345 - 0
EVSE/GPL/hostapd-2.6/hostapd/defconfig

@@ -0,0 +1,345 @@
+# Example hostapd build time configuration
+#
+# This file lists the configuration options that are used when building the
+# hostapd binary. All lines starting with # are ignored. Configuration option
+# lines must be commented out complete, if they are not to be included, i.e.,
+# just setting VARIABLE=n is not disabling that variable.
+#
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
+# be modified from here. In most cass, these lines should use += in order not
+# to override previous values of the variables.
+
+# Driver interface for Host AP driver
+CONFIG_DRIVER_HOSTAP=y
+
+# Driver interface for wired authenticator
+#CONFIG_DRIVER_WIRED=y
+
+# Driver interface for drivers using the nl80211 kernel interface
+CONFIG_DRIVER_NL80211=y
+
+# QCA vendor extensions to nl80211
+#CONFIG_DRIVER_NL80211_QCA=y
+
+# driver_nl80211.c requires libnl. If you are compiling it yourself
+# you may need to point hostapd to your version of libnl.
+#
+#CFLAGS += -I$<path to libnl include files>
+#LIBS += -L$<path to libnl library files>
+
+# Use libnl v2.0 (or 3.0) libraries.
+#CONFIG_LIBNL20=y
+
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
+#CONFIG_LIBNL32=y
+
+
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
+#CONFIG_DRIVER_BSD=y
+#CFLAGS += -I/usr/local/include
+#LIBS += -L/usr/local/lib
+#LIBS_p += -L/usr/local/lib
+#LIBS_c += -L/usr/local/lib
+
+# Driver interface for no driver (e.g., RADIUS server only)
+#CONFIG_DRIVER_NONE=y
+
+# IEEE 802.11F/IAPP
+CONFIG_IAPP=y
+
+# WPA2/IEEE 802.11i RSN pre-authentication
+CONFIG_RSN_PREAUTH=y
+
+# PeerKey handshake for Station to Station Link (IEEE 802.11e DLS)
+CONFIG_PEERKEY=y
+
+# IEEE 802.11w (management frame protection)
+CONFIG_IEEE80211W=y
+
+# Integrated EAP server
+CONFIG_EAP=y
+
+# EAP Re-authentication Protocol (ERP) in integrated EAP server
+CONFIG_ERP=y
+
+# EAP-MD5 for the integrated EAP server
+CONFIG_EAP_MD5=y
+
+# EAP-TLS for the integrated EAP server
+CONFIG_EAP_TLS=y
+
+# EAP-MSCHAPv2 for the integrated EAP server
+CONFIG_EAP_MSCHAPV2=y
+
+# EAP-PEAP for the integrated EAP server
+CONFIG_EAP_PEAP=y
+
+# EAP-GTC for the integrated EAP server
+CONFIG_EAP_GTC=y
+
+# EAP-TTLS for the integrated EAP server
+CONFIG_EAP_TTLS=y
+
+# EAP-SIM for the integrated EAP server
+#CONFIG_EAP_SIM=y
+
+# EAP-AKA for the integrated EAP server
+#CONFIG_EAP_AKA=y
+
+# EAP-AKA' for the integrated EAP server
+# This requires CONFIG_EAP_AKA to be enabled, too.
+#CONFIG_EAP_AKA_PRIME=y
+
+# EAP-PAX for the integrated EAP server
+#CONFIG_EAP_PAX=y
+
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
+#CONFIG_EAP_PSK=y
+
+# EAP-pwd for the integrated EAP server (secure authentication with a password)
+#CONFIG_EAP_PWD=y
+
+# EAP-SAKE for the integrated EAP server
+#CONFIG_EAP_SAKE=y
+
+# EAP-GPSK for the integrated EAP server
+#CONFIG_EAP_GPSK=y
+# Include support for optional SHA256 cipher suite in EAP-GPSK
+#CONFIG_EAP_GPSK_SHA256=y
+
+# EAP-FAST for the integrated EAP server
+# Note: If OpenSSL is used as the TLS library, OpenSSL 1.0 or newer is needed
+# for EAP-FAST support. Older OpenSSL releases would need to be patched, e.g.,
+# with openssl-0.9.8x-tls-extensions.patch, to add the needed functions.
+#CONFIG_EAP_FAST=y
+
+# Wi-Fi Protected Setup (WPS)
+#CONFIG_WPS=y
+# Enable UPnP support for external WPS Registrars
+#CONFIG_WPS_UPNP=y
+# Enable WPS support with NFC config method
+#CONFIG_WPS_NFC=y
+
+# EAP-IKEv2
+#CONFIG_EAP_IKEV2=y
+
+# Trusted Network Connect (EAP-TNC)
+#CONFIG_EAP_TNC=y
+
+# EAP-EKE for the integrated EAP server
+#CONFIG_EAP_EKE=y
+
+# PKCS#12 (PFX) support (used to read private key and certificate file from
+# a file that usually has extension .p12 or .pfx)
+CONFIG_PKCS12=y
+
+# RADIUS authentication server. This provides access to the integrated EAP
+# server from external hosts using RADIUS.
+#CONFIG_RADIUS_SERVER=y
+
+# Build IPv6 support for RADIUS operations
+CONFIG_IPV6=y
+
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
+#CONFIG_IEEE80211R=y
+
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
+# the IEEE 802.11 Management capability (e.g., FreeBSD/net80211)
+#CONFIG_DRIVER_RADIUS_ACL=y
+
+# IEEE 802.11n (High Throughput) support
+#CONFIG_IEEE80211N=y
+
+# Wireless Network Management (IEEE Std 802.11v-2011)
+# Note: This is experimental and not complete implementation.
+#CONFIG_WNM=y
+
+# IEEE 802.11ac (Very High Throughput) support
+#CONFIG_IEEE80211AC=y
+
+# Remove debugging code that is printing out debug messages to stdout.
+# This can be used to reduce the size of the hostapd considerably if debugging
+# code is not needed.
+#CONFIG_NO_STDOUT_DEBUG=y
+
+# Add support for writing debug log to a file: -f /tmp/hostapd.log
+# Disabled by default.
+#CONFIG_DEBUG_FILE=y
+
+# Add support for sending all debug messages (regardless of debug verbosity)
+# to the Linux kernel tracing facility. This helps debug the entire stack by
+# making it easy to record everything happening from the driver up into the
+# same file, e.g., using trace-cmd.
+#CONFIG_DEBUG_LINUX_TRACING=y
+
+# Remove support for RADIUS accounting
+#CONFIG_NO_ACCOUNTING=y
+
+# Remove support for RADIUS
+#CONFIG_NO_RADIUS=y
+
+# Remove support for VLANs
+#CONFIG_NO_VLAN=y
+
+# Enable support for fully dynamic VLANs. This enables hostapd to
+# automatically create bridge and VLAN interfaces if necessary.
+#CONFIG_FULL_DYNAMIC_VLAN=y
+
+# Use netlink-based kernel API for VLAN operations instead of ioctl()
+# Note: This requires libnl 3.1 or newer.
+#CONFIG_VLAN_NETLINK=y
+
+# Remove support for dumping internal state through control interface commands
+# This can be used to reduce binary size at the cost of disabling a debugging
+# option.
+#CONFIG_NO_DUMP_STATE=y
+
+# Enable tracing code for developer debugging
+# This tracks use of memory allocations and other registrations and reports
+# incorrect use with a backtrace of call (or allocation) location.
+#CONFIG_WPA_TRACE=y
+# For BSD, comment out these.
+#LIBS += -lexecinfo
+#LIBS_p += -lexecinfo
+#LIBS_c += -lexecinfo
+
+# Use libbfd to get more details for developer debugging
+# This enables use of libbfd to get more detailed symbols for the backtraces
+# generated by CONFIG_WPA_TRACE=y.
+#CONFIG_WPA_TRACE_BFD=y
+# For BSD, comment out these.
+#LIBS += -lbfd -liberty -lz
+#LIBS_p += -lbfd -liberty -lz
+#LIBS_c += -lbfd -liberty -lz
+
+# hostapd depends on strong random number generation being available from the
+# operating system. os_get_random() function is used to fetch random data when
+# needed, e.g., for key generation. On Linux and BSD systems, this works by
+# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
+# properly initialized before hostapd is started. This is important especially
+# on embedded devices that do not have a hardware random number generator and
+# may by default start up with minimal entropy available for random number
+# generation.
+#
+# As a safety net, hostapd is by default trying to internally collect
+# additional entropy for generating random data to mix in with the data
+# fetched from the OS. This by itself is not considered to be very strong, but
+# it may help in cases where the system pool is not initialized properly.
+# However, it is very strongly recommended that the system pool is initialized
+# with enough entropy either by using hardware assisted random number
+# generator or by storing state over device reboots.
+#
+# hostapd can be configured to maintain its own entropy store over restarts to
+# enhance random number generation. This is not perfect, but it is much more
+# secure than using the same sequence of random numbers after every reboot.
+# This can be enabled with -e<entropy file> command line option. The specified
+# file needs to be readable and writable by hostapd.
+#
+# If the os_get_random() is known to provide strong random data (e.g., on
+# Linux/BSD, the board in question is known to have reliable source of random
+# data from /dev/urandom), the internal hostapd random pool can be disabled.
+# This will save some in binary size and CPU use. However, this should only be
+# considered for builds that are known to be used on devices that meet the
+# requirements described above.
+#CONFIG_NO_RANDOM_POOL=y
+
+# Should we use poll instead of select? Select is used by default.
+#CONFIG_ELOOP_POLL=y
+
+# Should we use epoll instead of select? Select is used by default.
+#CONFIG_ELOOP_EPOLL=y
+
+# Should we use kqueue instead of select? Select is used by default.
+#CONFIG_ELOOP_KQUEUE=y
+
+# Select TLS implementation
+# openssl = OpenSSL (default)
+# gnutls = GnuTLS
+# internal = Internal TLSv1 implementation (experimental)
+# none = Empty template
+#CONFIG_TLS=openssl
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
+# can be enabled to get a stronger construction of messages when block ciphers
+# are used.
+#CONFIG_TLSV11=y
+
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
+# can be enabled to enable use of stronger crypto algorithms.
+#CONFIG_TLSV12=y
+
+# If CONFIG_TLS=internal is used, additional library and include paths are
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
+# and drawbacks of this option.
+#CONFIG_INTERNAL_LIBTOMMATH=y
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
+#LTM_PATH=/usr/src/libtommath-0.39
+#CFLAGS += -I$(LTM_PATH)
+#LIBS += -L$(LTM_PATH)
+#LIBS_p += -L$(LTM_PATH)
+#endif
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
+# can be configured to include faster routines for exptmod, sqr, and div to
+# speed up DH and RSA calculation considerably
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
+
+# Interworking (IEEE 802.11u)
+# This can be used to enable functionality to improve interworking with
+# external networks.
+#CONFIG_INTERWORKING=y
+
+# Hotspot 2.0
+#CONFIG_HS20=y
+
+# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
+#CONFIG_SQLITE=y
+
+# Enable Fast Session Transfer (FST)
+#CONFIG_FST=y
+
+# Enable CLI commands for FST testing
+#CONFIG_FST_TEST=y
+
+# Testing options
+# This can be used to enable some testing options (see also the example
+# configuration file) that are really useful only for testing clients that
+# connect to this hostapd. These options allow, for example, to drop a
+# certain percentage of probe requests or auth/(re)assoc frames.
+#
+#CONFIG_TESTING_OPTIONS=y
+
+# Automatic Channel Selection
+# This will allow hostapd to pick the channel automatically when channel is set
+# to "acs_survey" or "0". Eventually, other ACS algorithms can be added in
+# similar way.
+#
+# Automatic selection is currently only done through initialization, later on
+# we hope to do background checks to keep us moving to more ideal channels as
+# time goes by. ACS is currently only supported through the nl80211 driver and
+# your driver must have survey dump capability that is filled by the driver
+# during scanning.
+#
+# You can customize the ACS survey algorithm with the hostapd.conf variable
+# acs_num_scans.
+#
+# Supported ACS drivers:
+# * ath9k
+# * ath5k
+# * ath10k
+#
+# For more details refer to:
+# http://wireless.kernel.org/en/users/Documentation/acs
+#
+#CONFIG_ACS=y
+
+# Multiband Operation support
+# These extentions facilitate efficient use of multiple frequency bands
+# available to the AP and the devices that may associate with it.
+#CONFIG_MBO=y
+
+# Client Taxonomy
+# Has the AP retain the Probe Request and (Re)Association Request frames from
+# a client, from which a signature can be produced which can identify the model
+# of client device like "Nexus 6P" or "iPhone 5s".
+#CONFIG_TAXONOMY=y

+ 150 - 0
EVSE/GPL/hostapd-2.6/hostapd/eap_register.c

@@ -0,0 +1,150 @@
+/*
+ * EAP method registration
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "eap_server/eap_methods.h"
+#include "eap_register.h"
+
+
+/**
+ * eap_server_register_methods - Register statically linked EAP server methods
+ * Returns: 0 on success, -1 or -2 on failure
+ *
+ * This function is called at program initialization to register all EAP
+ * methods that were linked in statically.
+ */
+int eap_server_register_methods(void)
+{
+	int ret = 0;
+
+#ifdef EAP_SERVER_IDENTITY
+	if (ret == 0)
+		ret = eap_server_identity_register();
+#endif /* EAP_SERVER_IDENTITY */
+
+#ifdef EAP_SERVER_MD5
+	if (ret == 0)
+		ret = eap_server_md5_register();
+#endif /* EAP_SERVER_MD5 */
+
+#ifdef EAP_SERVER_TLS
+	if (ret == 0)
+		ret = eap_server_tls_register();
+#endif /* EAP_SERVER_TLS */
+
+#ifdef EAP_SERVER_UNAUTH_TLS
+	if (ret == 0)
+		ret = eap_server_unauth_tls_register();
+#endif /* EAP_SERVER_TLS */
+
+#ifdef EAP_SERVER_TLS
+#ifdef CONFIG_HS20
+	if (ret == 0)
+		ret = eap_server_wfa_unauth_tls_register();
+#endif /* CONFIG_HS20 */
+#endif /* EAP_SERVER_TLS */
+
+#ifdef EAP_SERVER_MSCHAPV2
+	if (ret == 0)
+		ret = eap_server_mschapv2_register();
+#endif /* EAP_SERVER_MSCHAPV2 */
+
+#ifdef EAP_SERVER_PEAP
+	if (ret == 0)
+		ret = eap_server_peap_register();
+#endif /* EAP_SERVER_PEAP */
+
+#ifdef EAP_SERVER_TLV
+	if (ret == 0)
+		ret = eap_server_tlv_register();
+#endif /* EAP_SERVER_TLV */
+
+#ifdef EAP_SERVER_GTC
+	if (ret == 0)
+		ret = eap_server_gtc_register();
+#endif /* EAP_SERVER_GTC */
+
+#ifdef EAP_SERVER_TTLS
+	if (ret == 0)
+		ret = eap_server_ttls_register();
+#endif /* EAP_SERVER_TTLS */
+
+#ifdef EAP_SERVER_SIM
+	if (ret == 0)
+		ret = eap_server_sim_register();
+#endif /* EAP_SERVER_SIM */
+
+#ifdef EAP_SERVER_AKA
+	if (ret == 0)
+		ret = eap_server_aka_register();
+#endif /* EAP_SERVER_AKA */
+
+#ifdef EAP_SERVER_AKA_PRIME
+	if (ret == 0)
+		ret = eap_server_aka_prime_register();
+#endif /* EAP_SERVER_AKA_PRIME */
+
+#ifdef EAP_SERVER_PAX
+	if (ret == 0)
+		ret = eap_server_pax_register();
+#endif /* EAP_SERVER_PAX */
+
+#ifdef EAP_SERVER_PSK
+	if (ret == 0)
+		ret = eap_server_psk_register();
+#endif /* EAP_SERVER_PSK */
+
+#ifdef EAP_SERVER_SAKE
+	if (ret == 0)
+		ret = eap_server_sake_register();
+#endif /* EAP_SERVER_SAKE */
+
+#ifdef EAP_SERVER_GPSK
+	if (ret == 0)
+		ret = eap_server_gpsk_register();
+#endif /* EAP_SERVER_GPSK */
+
+#ifdef EAP_SERVER_VENDOR_TEST
+	if (ret == 0)
+		ret = eap_server_vendor_test_register();
+#endif /* EAP_SERVER_VENDOR_TEST */
+
+#ifdef EAP_SERVER_FAST
+	if (ret == 0)
+		ret = eap_server_fast_register();
+#endif /* EAP_SERVER_FAST */
+
+#ifdef EAP_SERVER_WSC
+	if (ret == 0)
+		ret = eap_server_wsc_register();
+#endif /* EAP_SERVER_WSC */
+
+#ifdef EAP_SERVER_IKEV2
+	if (ret == 0)
+		ret = eap_server_ikev2_register();
+#endif /* EAP_SERVER_IKEV2 */
+
+#ifdef EAP_SERVER_TNC
+	if (ret == 0)
+		ret = eap_server_tnc_register();
+#endif /* EAP_SERVER_TNC */
+
+#ifdef EAP_SERVER_PWD
+	if (ret == 0)
+		ret = eap_server_pwd_register();
+#endif /* EAP_SERVER_PWD */
+
+#ifdef EAP_SERVER_EKE
+	if (ret == 0)
+		ret = eap_server_eke_register();
+#endif /* EAP_SERVER_EKE */
+
+	return ret;
+}

+ 10 - 0
EVSE/GPL/hostapd-2.6/hostapd/eap_register.d

@@ -0,0 +1,10 @@
+eap_register.o: eap_register.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap_methods.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_common/eap_defs.h \
+ eap_register.h

+ 14 - 0
EVSE/GPL/hostapd-2.6/hostapd/eap_register.h

@@ -0,0 +1,14 @@
+/*
+ * EAP method registration
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_REGISTER_H
+#define EAP_REGISTER_H
+
+int eap_server_register_methods(void);
+
+#endif /* EAP_REGISTER_H */

+ 77 - 0
EVSE/GPL/hostapd-2.6/hostapd/eap_testing.txt

@@ -0,0 +1,77 @@
+Interoperability testing of hostapd's IEEE 802.1X/EAPOL authentication
+
+Test matrix
+
++) tested successfully
+F) failed
+-) peer did not support
+?) not tested
+
+XSupplicant --------------------------------.
+Intel PROSet ---------------------------.   |
+Windows XP -------------------------.   |   |
+Mac OS X 10.4 ------------------.   |   |   |
+Nokia S60 ------------------.   |   |   |   |
+wpa_supplicant ---------.   |   |   |   |   |
+			|   |   |   |   |   |
+
+EAP-MD5			+   -   ?   ?   -
+EAP-GTC			+   -   ?   -   -
+EAP-MSCHAPv2		+   -   ?   -   -
+EAP-TLS			+   +   +1  +   +
+EAP-PEAPv0/MSCHAPv2	+   +   +   +   +   +
+EAP-PEAPv0/GTC		+   +   +   -   +
+EAP-PEAPv0/MD5		+   -   +   -   -
+EAP-PEAPv0/TLS		+   F   -   +   +
+EAP-PEAPv0/SIM		+   +   -   -   -
+EAP-PEAPv0/AKA		+   +   -   -   -
+EAP-PEAPv0/PSK		+   -   -   -   -
+EAP-PEAPv0/PAX		+   -   -   -   -
+EAP-PEAPv0/SAKE		+   -   -   -   -
+EAP-PEAPv0/GPSK		+   -   -   -   -
+EAP-PEAPv1/MSCHAPv2	+   +   +   -   +   +
+EAP-PEAPv1/GTC		+   +   +   -   +
+EAP-PEAPv1/MD5		+   -   +   -   -
+EAP-PEAPv1/TLS		+   F   -   -   +
+EAP-PEAPv1/SIM		+   +   -   -   -
+EAP-PEAPv1/AKA		+   +   -   -   -
+EAP-PEAPv1/PSK		+   -   -   -   -
+EAP-PEAPv1/PAX		+   -   -   -   -
+EAP-PEAPv1/SAKE		+   -   -   -   -
+EAP-PEAPv1/GPSK		+   -   -   -   -
+EAP-TTLS/CHAP		+   -   +   -   +   +
+EAP-TTLS/MSCHAP		+   -   +   -   +   +
+EAP-TTLS/MSCHAPv2	+   +   +   -   +   +
+EAP-TTLS/PAP		+   -   +   -   +   +
+EAP-TTLS/EAP-MD5	+   -   -   -   -   +
+EAP-TTLS/EAP-GTC	+   +   -   -   -
+EAP-TTLS/EAP-MSCHAPv2	+   +   -   -   -
+EAP-TTLS/EAP-TLS	+   F   -   -   -
+EAP-TTLS/EAP-SIM	+   +   -   -   -
+EAP-TTLS/EAP-AKA	+   +   -   -   -
+EAP-TTLS + TNC		+   -   -   -   -
+EAP-SIM			+   +   -   -   +
+EAP-AKA			+   +   -   -   -
+EAP-PAX			+   -   -   -   -
+EAP-SAKE		+   -   -   -   -
+EAP-GPSK		+   -   -   -   -
+EAP-FAST/MSCHAPv2(prov)	+   -   F   -   F
+EAP-FAST/GTC(auth)	+   -   +   -   +
+EAP-FAST/MSCHAPv2(aprov)+   -   F   -   F
+EAP-FAST/GTC(aprov)	+   -   F   -   F
+EAP-FAST/MD5(aprov)	+   -   -   -   -
+EAP-FAST/TLS(aprov)	+   -   -   -   -
+EAP-FAST/SIM(aprov)	+   -   -   -   -
+EAP-FAST/AKA(aprov)	+   -   -   -   -
+EAP-FAST/MSCHAPv2(auth)	+   -   +   -   +
+EAP-FAST/MD5(auth)	+   -   +   -   -
+EAP-FAST/TLS(auth)	+   -   -   -   -
+EAP-FAST/SIM(auth)	+   -   -   -   -
+EAP-FAST/AKA(auth)	+   -   -   -   -
+EAP-FAST + TNC		+   -   -   -   -
+EAP-IKEv2		+   -   -   -   -
+EAP-TNC			+   -   -   -   -
+
+1) EAP-TLS itself worked, but peer certificate validation failed at
+   least when using the internal TLS server (peer included incorrect
+   certificates in the chain?)

+ 18 - 0
EVSE/GPL/hostapd-2.6/hostapd/hapd_module_tests.c

@@ -0,0 +1,18 @@
+/*
+ * hostapd module tests
+ * Copyright (c) 2014, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "utils/module_tests.h"
+
+int hapd_module_tests(void)
+{
+	wpa_printf(MSG_INFO, "hostapd module tests");
+	return 0;
+}

+ 1109 - 0
EVSE/GPL/hostapd-2.6/hostapd/hlr_auc_gw.c

@@ -0,0 +1,1109 @@
+/*
+ * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
+ * Copyright (c) 2005-2007, 2012-2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ *
+ * This is an example implementation of the EAP-SIM/AKA database/authentication
+ * gateway interface to HLR/AuC. It is expected to be replaced with an
+ * implementation of SS7 gateway to GSM/UMTS authentication center (HLR/AuC) or
+ * a local implementation of SIM triplet and AKA authentication data generator.
+ *
+ * hostapd will send SIM/AKA authentication queries over a UNIX domain socket
+ * to and external program, e.g., this hlr_auc_gw. This interface uses simple
+ * text-based format:
+ *
+ * EAP-SIM / GSM triplet query/response:
+ * SIM-REQ-AUTH <IMSI> <max_chal>
+ * SIM-RESP-AUTH <IMSI> Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3]
+ * SIM-RESP-AUTH <IMSI> FAILURE
+ * GSM-AUTH-REQ <IMSI> RAND1:RAND2[:RAND3]
+ * GSM-AUTH-RESP <IMSI> Kc1:SRES1:Kc2:SRES2[:Kc3:SRES3]
+ * GSM-AUTH-RESP <IMSI> FAILURE
+ *
+ * EAP-AKA / UMTS query/response:
+ * AKA-REQ-AUTH <IMSI>
+ * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES>
+ * AKA-RESP-AUTH <IMSI> FAILURE
+ *
+ * EAP-AKA / UMTS AUTS (re-synchronization):
+ * AKA-AUTS <IMSI> <AUTS> <RAND>
+ *
+ * IMSI and max_chal are sent as an ASCII string,
+ * Kc/SRES/RAND/AUTN/IK/CK/RES/AUTS as hex strings.
+ *
+ * An example implementation here reads GSM authentication triplets from a
+ * text file in IMSI:Kc:SRES:RAND format, IMSI in ASCII, other fields as hex
+ * strings. This is used to simulate an HLR/AuC. As such, it is not very useful
+ * for real life authentication, but it is useful both as an example
+ * implementation and for EAP-SIM/AKA/AKA' testing.
+ *
+ * For a stronger example design, Milenage and GSM-Milenage algorithms can be
+ * used to dynamically generate authenticatipn information for EAP-AKA/AKA' and
+ * EAP-SIM, respectively, if Ki is known.
+ *
+ * SQN generation follows the not time-based Profile 2 described in
+ * 3GPP TS 33.102 Annex C.3.2. The length of IND is 5 bits by default, but this
+ * can be changed with a command line options if needed.
+ */
+
+#include "includes.h"
+#include <sys/un.h>
+#ifdef CONFIG_SQLITE
+#include <sqlite3.h>
+#endif /* CONFIG_SQLITE */
+
+#include "common.h"
+#include "crypto/milenage.h"
+#include "crypto/random.h"
+
+static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
+static const char *socket_path;
+static int serv_sock = -1;
+static char *milenage_file = NULL;
+static int update_milenage = 0;
+static int sqn_changes = 0;
+static int ind_len = 5;
+static int stdout_debug = 1;
+
+/* GSM triplets */
+struct gsm_triplet {
+	struct gsm_triplet *next;
+	char imsi[20];
+	u8 kc[8];
+	u8 sres[4];
+	u8 _rand[16];
+};
+
+static struct gsm_triplet *gsm_db = NULL, *gsm_db_pos = NULL;
+
+/* OPc and AMF parameters for Milenage (Example algorithms for AKA). */
+struct milenage_parameters {
+	struct milenage_parameters *next;
+	char imsi[20];
+	u8 ki[16];
+	u8 opc[16];
+	u8 amf[2];
+	u8 sqn[6];
+	int set;
+	size_t res_len;
+};
+
+static struct milenage_parameters *milenage_db = NULL;
+
+#define EAP_SIM_MAX_CHAL 3
+
+#define EAP_AKA_RAND_LEN 16
+#define EAP_AKA_AUTN_LEN 16
+#define EAP_AKA_AUTS_LEN 14
+#define EAP_AKA_RES_MIN_LEN 4
+#define EAP_AKA_RES_MAX_LEN 16
+#define EAP_AKA_IK_LEN 16
+#define EAP_AKA_CK_LEN 16
+
+
+#ifdef CONFIG_SQLITE
+
+static sqlite3 *sqlite_db = NULL;
+static struct milenage_parameters db_tmp_milenage;
+
+
+static int db_table_exists(sqlite3 *db, const char *name)
+{
+	char cmd[128];
+	os_snprintf(cmd, sizeof(cmd), "SELECT 1 FROM %s;", name);
+	return sqlite3_exec(db, cmd, NULL, NULL, NULL) == SQLITE_OK;
+}
+
+
+static int db_table_create_milenage(sqlite3 *db)
+{
+	char *err = NULL;
+	const char *sql =
+		"CREATE TABLE milenage("
+		"  imsi INTEGER PRIMARY KEY NOT NULL,"
+		"  ki CHAR(32) NOT NULL,"
+		"  opc CHAR(32) NOT NULL,"
+		"  amf CHAR(4) NOT NULL,"
+		"  sqn CHAR(12) NOT NULL,"
+		"  res_len INTEGER"
+		");";
+
+	printf("Adding database table for milenage information\n");
+	if (sqlite3_exec(db, sql, NULL, NULL, &err) != SQLITE_OK) {
+		printf("SQLite error: %s\n", err);
+		sqlite3_free(err);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static sqlite3 * db_open(const char *db_file)
+{
+	sqlite3 *db;
+
+	if (sqlite3_open(db_file, &db)) {
+		printf("Failed to open database %s: %s\n",
+		       db_file, sqlite3_errmsg(db));
+		sqlite3_close(db);
+		return NULL;
+	}
+
+	if (!db_table_exists(db, "milenage") &&
+	    db_table_create_milenage(db) < 0) {
+		sqlite3_close(db);
+		return NULL;
+	}
+
+	return db;
+}
+
+
+static int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[])
+{
+	struct milenage_parameters *m = ctx;
+	int i;
+
+	m->set = 1;
+
+	for (i = 0; i < argc; i++) {
+		if (os_strcmp(col[i], "ki") == 0 && argv[i] &&
+		    hexstr2bin(argv[i], m->ki, sizeof(m->ki))) {
+			printf("Invalid ki value in database\n");
+			return -1;
+		}
+
+		if (os_strcmp(col[i], "opc") == 0 && argv[i] &&
+		    hexstr2bin(argv[i], m->opc, sizeof(m->opc))) {
+			printf("Invalid opcvalue in database\n");
+			return -1;
+		}
+
+		if (os_strcmp(col[i], "amf") == 0 && argv[i] &&
+		    hexstr2bin(argv[i], m->amf, sizeof(m->amf))) {
+			printf("Invalid amf value in database\n");
+			return -1;
+		}
+
+		if (os_strcmp(col[i], "sqn") == 0 && argv[i] &&
+		    hexstr2bin(argv[i], m->sqn, sizeof(m->sqn))) {
+			printf("Invalid sqn value in database\n");
+			return -1;
+		}
+
+		if (os_strcmp(col[i], "res_len") == 0 && argv[i]) {
+			m->res_len = atoi(argv[i]);
+		}
+	}
+
+	return 0;
+}
+
+
+static struct milenage_parameters * db_get_milenage(const char *imsi_txt)
+{
+	char cmd[128];
+	unsigned long long imsi;
+
+	os_memset(&db_tmp_milenage, 0, sizeof(db_tmp_milenage));
+	imsi = atoll(imsi_txt);
+	os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi),
+		    "%llu", imsi);
+	os_snprintf(cmd, sizeof(cmd),
+		    "SELECT * FROM milenage WHERE imsi=%llu;", imsi);
+	if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage,
+			 NULL) != SQLITE_OK)
+		return NULL;
+
+	if (!db_tmp_milenage.set)
+		return NULL;
+	return &db_tmp_milenage;
+}
+
+
+static int db_update_milenage_sqn(struct milenage_parameters *m)
+{
+	char cmd[128], val[13], *pos;
+
+	if (sqlite_db == NULL)
+		return 0;
+
+	pos = val;
+	pos += wpa_snprintf_hex(pos, sizeof(val), m->sqn, 6);
+	*pos = '\0';
+	os_snprintf(cmd, sizeof(cmd),
+		    "UPDATE milenage SET sqn='%s' WHERE imsi=%s;",
+		    val, m->imsi);
+	if (sqlite3_exec(sqlite_db, cmd, NULL, NULL, NULL) != SQLITE_OK) {
+		printf("Failed to update SQN in database for IMSI %s\n",
+		       m->imsi);
+		return -1;
+	}
+	return 0;
+}
+
+#endif /* CONFIG_SQLITE */
+
+
+static int open_socket(const char *path)
+{
+	struct sockaddr_un addr;
+	int s;
+
+	s = socket(PF_UNIX, SOCK_DGRAM, 0);
+	if (s < 0) {
+		perror("socket(PF_UNIX)");
+		return -1;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	os_strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
+	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+		perror("hlr-auc-gw: bind(PF_UNIX)");
+		close(s);
+		return -1;
+	}
+
+	return s;
+}
+
+
+static int read_gsm_triplets(const char *fname)
+{
+	FILE *f;
+	char buf[200], *pos, *pos2;
+	struct gsm_triplet *g = NULL;
+	int line, ret = 0;
+
+	if (fname == NULL)
+		return -1;
+
+	f = fopen(fname, "r");
+	if (f == NULL) {
+		printf("Could not open GSM triplet data file '%s'\n", fname);
+		return -1;
+	}
+
+	line = 0;
+	while (fgets(buf, sizeof(buf), f)) {
+		line++;
+
+		/* Parse IMSI:Kc:SRES:RAND */
+		buf[sizeof(buf) - 1] = '\0';
+		if (buf[0] == '#')
+			continue;
+		pos = buf;
+		while (*pos != '\0' && *pos != '\n')
+			pos++;
+		if (*pos == '\n')
+			*pos = '\0';
+		pos = buf;
+		if (*pos == '\0')
+			continue;
+
+		g = os_zalloc(sizeof(*g));
+		if (g == NULL) {
+			ret = -1;
+			break;
+		}
+
+		/* IMSI */
+		pos2 = NULL;
+		pos = str_token(buf, ":", &pos2);
+		if (!pos || os_strlen(pos) >= sizeof(g->imsi)) {
+			printf("%s:%d - Invalid IMSI\n", fname, line);
+			ret = -1;
+			break;
+		}
+		os_strlcpy(g->imsi, pos, sizeof(g->imsi));
+
+		/* Kc */
+		pos = str_token(buf, ":", &pos2);
+		if (!pos || os_strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) {
+			printf("%s:%d - Invalid Kc\n", fname, line);
+			ret = -1;
+			break;
+		}
+
+		/* SRES */
+		pos = str_token(buf, ":", &pos2);
+		if (!pos || os_strlen(pos) != 8 ||
+		    hexstr2bin(pos, g->sres, 4)) {
+			printf("%s:%d - Invalid SRES\n", fname, line);
+			ret = -1;
+			break;
+		}
+
+		/* RAND */
+		pos = str_token(buf, ":", &pos2);
+		if (!pos || os_strlen(pos) != 32 ||
+		    hexstr2bin(pos, g->_rand, 16)) {
+			printf("%s:%d - Invalid RAND\n", fname, line);
+			ret = -1;
+			break;
+		}
+
+		g->next = gsm_db;
+		gsm_db = g;
+		g = NULL;
+	}
+	os_free(g);
+
+	fclose(f);
+
+	return ret;
+}
+
+
+static struct gsm_triplet * get_gsm_triplet(const char *imsi)
+{
+	struct gsm_triplet *g = gsm_db_pos;
+
+	while (g) {
+		if (strcmp(g->imsi, imsi) == 0) {
+			gsm_db_pos = g->next;
+			return g;
+		}
+		g = g->next;
+	}
+
+	g = gsm_db;
+	while (g && g != gsm_db_pos) {
+		if (strcmp(g->imsi, imsi) == 0) {
+			gsm_db_pos = g->next;
+			return g;
+		}
+		g = g->next;
+	}
+
+	return NULL;
+}
+
+
+static int read_milenage(const char *fname)
+{
+	FILE *f;
+	char buf[200], *pos, *pos2;
+	struct milenage_parameters *m = NULL;
+	int line, ret = 0;
+
+	if (fname == NULL)
+		return -1;
+
+	f = fopen(fname, "r");
+	if (f == NULL) {
+		printf("Could not open Milenage data file '%s'\n", fname);
+		return -1;
+	}
+
+	line = 0;
+	while (fgets(buf, sizeof(buf), f)) {
+		line++;
+
+		/* Parse IMSI Ki OPc AMF SQN [RES_len] */
+		buf[sizeof(buf) - 1] = '\0';
+		if (buf[0] == '#')
+			continue;
+		pos = buf;
+		while (*pos != '\0' && *pos != '\n')
+			pos++;
+		if (*pos == '\n')
+			*pos = '\0';
+		pos = buf;
+		if (*pos == '\0')
+			continue;
+
+		m = os_zalloc(sizeof(*m));
+		if (m == NULL) {
+			ret = -1;
+			break;
+		}
+
+		/* IMSI */
+		pos2 = NULL;
+		pos = str_token(buf, " ", &pos2);
+		if (!pos || os_strlen(pos) >= sizeof(m->imsi)) {
+			printf("%s:%d - Invalid IMSI\n", fname, line);
+			ret = -1;
+			break;
+		}
+		os_strlcpy(m->imsi, pos, sizeof(m->imsi));
+
+		/* Ki */
+		pos = str_token(buf, " ", &pos2);
+		if (!pos || os_strlen(pos) != 32 ||
+		    hexstr2bin(pos, m->ki, 16)) {
+			printf("%s:%d - Invalid Ki\n", fname, line);
+			ret = -1;
+			break;
+		}
+
+		/* OPc */
+		pos = str_token(buf, " ", &pos2);
+		if (!pos || os_strlen(pos) != 32 ||
+		    hexstr2bin(pos, m->opc, 16)) {
+			printf("%s:%d - Invalid OPc\n", fname, line);
+			ret = -1;
+			break;
+		}
+
+		/* AMF */
+		pos = str_token(buf, " ", &pos2);
+		if (!pos || os_strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) {
+			printf("%s:%d - Invalid AMF\n", fname, line);
+			ret = -1;
+			break;
+		}
+
+		/* SQN */
+		pos = str_token(buf, " ", &pos2);
+		if (!pos || os_strlen(pos) != 12 ||
+		    hexstr2bin(pos, m->sqn, 6)) {
+			printf("%s:%d - Invalid SEQ\n", fname, line);
+			ret = -1;
+			break;
+		}
+
+		pos = str_token(buf, " ", &pos2);
+		if (pos) {
+			m->res_len = atoi(pos);
+			if (m->res_len &&
+			    (m->res_len < EAP_AKA_RES_MIN_LEN ||
+			     m->res_len > EAP_AKA_RES_MAX_LEN)) {
+				printf("%s:%d - Invalid RES_len\n",
+				       fname, line);
+				ret = -1;
+				break;
+			}
+		}
+
+		m->next = milenage_db;
+		milenage_db = m;
+		m = NULL;
+	}
+	os_free(m);
+
+	fclose(f);
+
+	return ret;
+}
+
+
+static void update_milenage_file(const char *fname)
+{
+	FILE *f, *f2;
+	char name[500], buf[500], *pos;
+	char *end = buf + sizeof(buf);
+	struct milenage_parameters *m;
+	size_t imsi_len;
+
+	f = fopen(fname, "r");
+	if (f == NULL) {
+		printf("Could not open Milenage data file '%s'\n", fname);
+		return;
+	}
+
+	snprintf(name, sizeof(name), "%s.new", fname);
+	f2 = fopen(name, "w");
+	if (f2 == NULL) {
+		printf("Could not write Milenage data file '%s'\n", name);
+		fclose(f);
+		return;
+	}
+
+	while (fgets(buf, sizeof(buf), f)) {
+		/* IMSI Ki OPc AMF SQN */
+		buf[sizeof(buf) - 1] = '\0';
+
+		pos = strchr(buf, ' ');
+		if (buf[0] == '#' || pos == NULL || pos - buf >= 20)
+			goto no_update;
+
+		imsi_len = pos - buf;
+
+		for (m = milenage_db; m; m = m->next) {
+			if (strncmp(buf, m->imsi, imsi_len) == 0 &&
+			    m->imsi[imsi_len] == '\0')
+				break;
+		}
+
+		if (!m)
+			goto no_update;
+
+		pos = buf;
+		pos += snprintf(pos, end - pos, "%s ", m->imsi);
+		pos += wpa_snprintf_hex(pos, end - pos, m->ki, 16);
+		*pos++ = ' ';
+		pos += wpa_snprintf_hex(pos, end - pos, m->opc, 16);
+		*pos++ = ' ';
+		pos += wpa_snprintf_hex(pos, end - pos, m->amf, 2);
+		*pos++ = ' ';
+		pos += wpa_snprintf_hex(pos, end - pos, m->sqn, 6);
+		*pos++ = '\n';
+
+	no_update:
+		fprintf(f2, "%s", buf);
+	}
+
+	fclose(f2);
+	fclose(f);
+
+	snprintf(name, sizeof(name), "%s.bak", fname);
+	if (rename(fname, name) < 0) {
+		perror("rename");
+		return;
+	}
+
+	snprintf(name, sizeof(name), "%s.new", fname);
+	if (rename(name, fname) < 0) {
+		perror("rename");
+		return;
+	}
+
+}
+
+
+static struct milenage_parameters * get_milenage(const char *imsi)
+{
+	struct milenage_parameters *m = milenage_db;
+
+	while (m) {
+		if (strcmp(m->imsi, imsi) == 0)
+			break;
+		m = m->next;
+	}
+
+#ifdef CONFIG_SQLITE
+	if (!m)
+		m = db_get_milenage(imsi);
+#endif /* CONFIG_SQLITE */
+
+	return m;
+}
+
+
+static int sim_req_auth(char *imsi, char *resp, size_t resp_len)
+{
+	int count, max_chal, ret;
+	char *pos;
+	char *rpos, *rend;
+	struct milenage_parameters *m;
+	struct gsm_triplet *g;
+
+	resp[0] = '\0';
+
+	pos = strchr(imsi, ' ');
+	if (pos) {
+		*pos++ = '\0';
+		max_chal = atoi(pos);
+		if (max_chal < 1 || max_chal > EAP_SIM_MAX_CHAL)
+			max_chal = EAP_SIM_MAX_CHAL;
+	} else
+		max_chal = EAP_SIM_MAX_CHAL;
+
+	rend = resp + resp_len;
+	rpos = resp;
+	ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi);
+	if (ret < 0 || ret >= rend - rpos)
+		return -1;
+	rpos += ret;
+
+	m = get_milenage(imsi);
+	if (m) {
+		u8 _rand[16], sres[4], kc[8];
+		for (count = 0; count < max_chal; count++) {
+			if (random_get_bytes(_rand, 16) < 0)
+				return -1;
+			gsm_milenage(m->opc, m->ki, _rand, sres, kc);
+			*rpos++ = ' ';
+			rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
+			*rpos++ = ':';
+			rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4);
+			*rpos++ = ':';
+			rpos += wpa_snprintf_hex(rpos, rend - rpos, _rand, 16);
+		}
+		*rpos = '\0';
+		return 0;
+	}
+
+	count = 0;
+	while (count < max_chal && (g = get_gsm_triplet(imsi))) {
+		if (strcmp(g->imsi, imsi) != 0)
+			continue;
+
+		if (rpos < rend)
+			*rpos++ = ' ';
+		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->kc, 8);
+		if (rpos < rend)
+			*rpos++ = ':';
+		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->sres, 4);
+		if (rpos < rend)
+			*rpos++ = ':';
+		rpos += wpa_snprintf_hex(rpos, rend - rpos, g->_rand, 16);
+		count++;
+	}
+
+	if (count == 0) {
+		printf("No GSM triplets found for %s\n", imsi);
+		ret = snprintf(rpos, rend - rpos, " FAILURE");
+		if (ret < 0 || ret >= rend - rpos)
+			return -1;
+		rpos += ret;
+	}
+
+	return 0;
+}
+
+
+static int gsm_auth_req(char *imsi, char *resp, size_t resp_len)
+{
+	int count, ret;
+	char *pos, *rpos, *rend;
+	struct milenage_parameters *m;
+
+	resp[0] = '\0';
+
+	pos = os_strchr(imsi, ' ');
+	if (!pos)
+		return -1;
+	*pos++ = '\0';
+
+	rend = resp + resp_len;
+	rpos = resp;
+	ret = os_snprintf(rpos, rend - rpos, "GSM-AUTH-RESP %s", imsi);
+	if (os_snprintf_error(rend - rpos, ret))
+		return -1;
+	rpos += ret;
+
+	m = get_milenage(imsi);
+	if (m) {
+		u8 _rand[16], sres[4], kc[8];
+		for (count = 0; count < EAP_SIM_MAX_CHAL; count++) {
+			if (hexstr2bin(pos, _rand, 16) != 0)
+				return -1;
+			gsm_milenage(m->opc, m->ki, _rand, sres, kc);
+			*rpos++ = count == 0 ? ' ' : ':';
+			rpos += wpa_snprintf_hex(rpos, rend - rpos, kc, 8);
+			*rpos++ = ':';
+			rpos += wpa_snprintf_hex(rpos, rend - rpos, sres, 4);
+			pos += 16 * 2;
+			if (*pos != ':')
+				break;
+			pos++;
+		}
+		*rpos = '\0';
+		return 0;
+	}
+
+	printf("No GSM triplets found for %s\n", imsi);
+	ret = os_snprintf(rpos, rend - rpos, " FAILURE");
+	if (os_snprintf_error(rend - rpos, ret))
+		return -1;
+	rpos += ret;
+
+	return 0;
+}
+
+
+static void inc_sqn(u8 *sqn)
+{
+	u64 val, seq, ind;
+
+	/*
+	 * SQN = SEQ | IND = SEQ1 | SEQ2 | IND
+	 *
+	 * The mechanism used here is not time-based, so SEQ2 is void and
+	 * SQN = SEQ1 | IND. The length of IND is ind_len bits and the length
+	 * of SEQ1 is 48 - ind_len bits.
+	 */
+
+	/* Increment both SEQ and IND by one */
+	val = ((u64) WPA_GET_BE32(sqn) << 16) | ((u64) WPA_GET_BE16(sqn + 4));
+	seq = (val >> ind_len) + 1;
+	ind = (val + 1) & ((1 << ind_len) - 1);
+	val = (seq << ind_len) | ind;
+	WPA_PUT_BE32(sqn, val >> 16);
+	WPA_PUT_BE16(sqn + 4, val & 0xffff);
+}
+
+
+static int aka_req_auth(char *imsi, char *resp, size_t resp_len)
+{
+	/* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */
+	char *pos, *end;
+	u8 _rand[EAP_AKA_RAND_LEN];
+	u8 autn[EAP_AKA_AUTN_LEN];
+	u8 ik[EAP_AKA_IK_LEN];
+	u8 ck[EAP_AKA_CK_LEN];
+	u8 res[EAP_AKA_RES_MAX_LEN];
+	size_t res_len;
+	int ret;
+	struct milenage_parameters *m;
+	int failed = 0;
+
+	m = get_milenage(imsi);
+	if (m) {
+		if (random_get_bytes(_rand, EAP_AKA_RAND_LEN) < 0)
+			return -1;
+		res_len = EAP_AKA_RES_MAX_LEN;
+		inc_sqn(m->sqn);
+#ifdef CONFIG_SQLITE
+		db_update_milenage_sqn(m);
+#endif /* CONFIG_SQLITE */
+		sqn_changes = 1;
+		if (stdout_debug) {
+			printf("AKA: Milenage with SQN=%02x%02x%02x%02x%02x%02x\n",
+			       m->sqn[0], m->sqn[1], m->sqn[2],
+			       m->sqn[3], m->sqn[4], m->sqn[5]);
+		}
+		milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
+				  autn, ik, ck, res, &res_len);
+		if (m->res_len >= EAP_AKA_RES_MIN_LEN &&
+		    m->res_len <= EAP_AKA_RES_MAX_LEN &&
+		    m->res_len < res_len)
+			res_len = m->res_len;
+	} else {
+		printf("Unknown IMSI: %s\n", imsi);
+#ifdef AKA_USE_FIXED_TEST_VALUES
+		printf("Using fixed test values for AKA\n");
+		memset(_rand, '0', EAP_AKA_RAND_LEN);
+		memset(autn, '1', EAP_AKA_AUTN_LEN);
+		memset(ik, '3', EAP_AKA_IK_LEN);
+		memset(ck, '4', EAP_AKA_CK_LEN);
+		memset(res, '2', EAP_AKA_RES_MAX_LEN);
+		res_len = EAP_AKA_RES_MAX_LEN;
+#else /* AKA_USE_FIXED_TEST_VALUES */
+		failed = 1;
+#endif /* AKA_USE_FIXED_TEST_VALUES */
+	}
+
+	pos = resp;
+	end = resp + resp_len;
+	ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi);
+	if (ret < 0 || ret >= end - pos)
+		return -1;
+	pos += ret;
+	if (failed) {
+		ret = snprintf(pos, end - pos, "FAILURE");
+		if (ret < 0 || ret >= end - pos)
+			return -1;
+		pos += ret;
+		return 0;
+	}
+	pos += wpa_snprintf_hex(pos, end - pos, _rand, EAP_AKA_RAND_LEN);
+	*pos++ = ' ';
+	pos += wpa_snprintf_hex(pos, end - pos, autn, EAP_AKA_AUTN_LEN);
+	*pos++ = ' ';
+	pos += wpa_snprintf_hex(pos, end - pos, ik, EAP_AKA_IK_LEN);
+	*pos++ = ' ';
+	pos += wpa_snprintf_hex(pos, end - pos, ck, EAP_AKA_CK_LEN);
+	*pos++ = ' ';
+	pos += wpa_snprintf_hex(pos, end - pos, res, res_len);
+
+	return 0;
+}
+
+
+static int aka_auts(char *imsi, char *resp, size_t resp_len)
+{
+	char *auts, *__rand;
+	u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6];
+	struct milenage_parameters *m;
+
+	resp[0] = '\0';
+
+	/* AKA-AUTS <IMSI> <AUTS> <RAND> */
+
+	auts = strchr(imsi, ' ');
+	if (auts == NULL)
+		return -1;
+	*auts++ = '\0';
+
+	__rand = strchr(auts, ' ');
+	if (__rand == NULL)
+		return -1;
+	*__rand++ = '\0';
+
+	if (stdout_debug) {
+		printf("AKA-AUTS: IMSI=%s AUTS=%s RAND=%s\n",
+		       imsi, auts, __rand);
+	}
+	if (hexstr2bin(auts, _auts, EAP_AKA_AUTS_LEN) ||
+	    hexstr2bin(__rand, _rand, EAP_AKA_RAND_LEN)) {
+		printf("Could not parse AUTS/RAND\n");
+		return -1;
+	}
+
+	m = get_milenage(imsi);
+	if (m == NULL) {
+		printf("Unknown IMSI: %s\n", imsi);
+		return -1;
+	}
+
+	if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) {
+		printf("AKA-AUTS: Incorrect MAC-S\n");
+	} else {
+		memcpy(m->sqn, sqn, 6);
+		if (stdout_debug) {
+			printf("AKA-AUTS: Re-synchronized: "
+			       "SQN=%02x%02x%02x%02x%02x%02x\n",
+			       sqn[0], sqn[1], sqn[2], sqn[3], sqn[4], sqn[5]);
+		}
+#ifdef CONFIG_SQLITE
+		db_update_milenage_sqn(m);
+#endif /* CONFIG_SQLITE */
+		sqn_changes = 1;
+	}
+
+	return 0;
+}
+
+
+static int process_cmd(char *cmd, char *resp, size_t resp_len)
+{
+	if (os_strncmp(cmd, "SIM-REQ-AUTH ", 13) == 0)
+		return sim_req_auth(cmd + 13, resp, resp_len);
+
+	if (os_strncmp(cmd, "GSM-AUTH-REQ ", 13) == 0)
+		return gsm_auth_req(cmd + 13, resp, resp_len);
+
+	if (os_strncmp(cmd, "AKA-REQ-AUTH ", 13) == 0)
+		return aka_req_auth(cmd + 13, resp, resp_len);
+
+	if (os_strncmp(cmd, "AKA-AUTS ", 9) == 0)
+		return aka_auts(cmd + 9, resp, resp_len);
+
+	printf("Unknown request: %s\n", cmd);
+	return -1;
+}
+
+
+static int process(int s)
+{
+	char buf[1000], resp[1000];
+	struct sockaddr_un from;
+	socklen_t fromlen;
+	ssize_t res;
+
+	fromlen = sizeof(from);
+	res = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *) &from,
+		       &fromlen);
+	if (res < 0) {
+		perror("recvfrom");
+		return -1;
+	}
+
+	if (res == 0)
+		return 0;
+
+	if ((size_t) res >= sizeof(buf))
+		res = sizeof(buf) - 1;
+	buf[res] = '\0';
+
+	printf("Received: %s\n", buf);
+
+	if (process_cmd(buf, resp, sizeof(resp)) < 0) {
+		printf("Failed to process request\n");
+		return -1;
+	}
+
+	if (resp[0] == '\0') {
+		printf("No response\n");
+		return 0;
+	}
+
+	printf("Send: %s\n", resp);
+
+	if (sendto(s, resp, os_strlen(resp), 0, (struct sockaddr *) &from,
+		   fromlen) < 0)
+		perror("send");
+
+	return 0;
+}
+
+
+static void cleanup(void)
+{
+	struct gsm_triplet *g, *gprev;
+	struct milenage_parameters *m, *prev;
+
+	if (update_milenage && milenage_file && sqn_changes)
+		update_milenage_file(milenage_file);
+
+	g = gsm_db;
+	while (g) {
+		gprev = g;
+		g = g->next;
+		os_free(gprev);
+	}
+
+	m = milenage_db;
+	while (m) {
+		prev = m;
+		m = m->next;
+		os_free(prev);
+	}
+
+	if (serv_sock >= 0)
+		close(serv_sock);
+	if (socket_path)
+		unlink(socket_path);
+
+#ifdef CONFIG_SQLITE
+	if (sqlite_db) {
+		sqlite3_close(sqlite_db);
+		sqlite_db = NULL;
+	}
+#endif /* CONFIG_SQLITE */
+}
+
+
+static void handle_term(int sig)
+{
+	printf("Signal %d - terminate\n", sig);
+	exit(0);
+}
+
+
+static void usage(void)
+{
+	printf("HLR/AuC testing gateway for hostapd EAP-SIM/AKA "
+	       "database/authenticator\n"
+	       "Copyright (c) 2005-2016, Jouni Malinen <j@w1.fi>\n"
+	       "\n"
+	       "usage:\n"
+	       "hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] "
+	       "[-m<milenage file>] \\\n"
+	       "        [-D<DB file>] [-i<IND len in bits>] [command]\n"
+	       "\n"
+	       "options:\n"
+	       "  -h = show this usage help\n"
+	       "  -u = update SQN in Milenage file on exit\n"
+	       "  -s<socket path> = path for UNIX domain socket\n"
+	       "                    (default: %s)\n"
+	       "  -g<triplet file> = path for GSM authentication triplets\n"
+	       "  -m<milenage file> = path for Milenage keys\n"
+	       "  -D<DB file> = path to SQLite database\n"
+	       "  -i<IND len in bits> = IND length for SQN (default: 5)\n"
+	       "\n"
+	       "If the optional command argument, like "
+	       "\"AKA-REQ-AUTH <IMSI>\" is used, a single\n"
+	       "command is processed with response sent to stdout. Otherwise, "
+	       "hlr_auc_gw opens\n"
+	       "a control interface and processes commands sent through it "
+	       "(e.g., by EAP server\n"
+	       "in hostapd).\n",
+	       default_socket_path);
+}
+
+
+int main(int argc, char *argv[])
+{
+	int c;
+	char *gsm_triplet_file = NULL;
+	char *sqlite_db_file = NULL;
+	int ret = 0;
+
+	if (os_program_init())
+		return -1;
+
+	socket_path = default_socket_path;
+
+	for (;;) {
+		c = getopt(argc, argv, "D:g:hi:m:s:u");
+		if (c < 0)
+			break;
+		switch (c) {
+		case 'D':
+#ifdef CONFIG_SQLITE
+			sqlite_db_file = optarg;
+			break;
+#else /* CONFIG_SQLITE */
+			printf("No SQLite support included in the build\n");
+			return -1;
+#endif /* CONFIG_SQLITE */
+		case 'g':
+			gsm_triplet_file = optarg;
+			break;
+		case 'h':
+			usage();
+			return 0;
+		case 'i':
+			ind_len = atoi(optarg);
+			if (ind_len < 0 || ind_len > 32) {
+				printf("Invalid IND length\n");
+				return -1;
+			}
+			break;
+		case 'm':
+			milenage_file = optarg;
+			break;
+		case 's':
+			socket_path = optarg;
+			break;
+		case 'u':
+			update_milenage = 1;
+			break;
+		default:
+			usage();
+			return -1;
+		}
+	}
+
+	if (!gsm_triplet_file && !milenage_file && !sqlite_db_file) {
+		usage();
+		return -1;
+	}
+
+#ifdef CONFIG_SQLITE
+	if (sqlite_db_file && (sqlite_db = db_open(sqlite_db_file)) == NULL)
+		return -1;
+#endif /* CONFIG_SQLITE */
+
+	if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0)
+		return -1;
+
+	if (milenage_file && read_milenage(milenage_file) < 0)
+		return -1;
+
+	if (optind == argc) {
+		serv_sock = open_socket(socket_path);
+		if (serv_sock < 0)
+			return -1;
+
+		printf("Listening for requests on %s\n", socket_path);
+
+		atexit(cleanup);
+		signal(SIGTERM, handle_term);
+		signal(SIGINT, handle_term);
+
+		for (;;)
+			process(serv_sock);
+	} else {
+		char buf[1000];
+		socket_path = NULL;
+		stdout_debug = 0;
+		if (process_cmd(argv[optind], buf, sizeof(buf)) < 0) {
+			printf("FAIL\n");
+			ret = -1;
+		} else {
+			printf("%s\n", buf);
+		}
+		cleanup();
+	}
+
+#ifdef CONFIG_SQLITE
+	if (sqlite_db) {
+		sqlite3_close(sqlite_db);
+		sqlite_db = NULL;
+	}
+#endif /* CONFIG_SQLITE */
+
+	os_program_deinit();
+
+	return ret;
+}

+ 15 - 0
EVSE/GPL/hostapd-2.6/hostapd/hlr_auc_gw.milenage_db

@@ -0,0 +1,15 @@
+# Parameters for Milenage (Example algorithms for AKA).
+# The example Ki, OPc, and AMF values here are from 3GPP TS 35.208 v6.0.0
+# 4.3.20 Test Set 20. SQN is the last used SQN value.
+# These values can be used for both UMTS (EAP-AKA) and GSM (EAP-SIM)
+# authentication. In case of GSM/EAP-SIM, AMF and SQN values are not used, but
+# dummy values will need to be included in this file.
+
+# IMSI Ki OPc AMF SQN [RES_len]
+232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
+# Example using truncated 32-bit RES instead of 64-bit default
+232010000000001 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000 4
+
+# These values are from Test Set 19 which has the AMF separation bit set to 1
+# and as such, is suitable for EAP-AKA' test.
+555444333222111 5122250214c33e723a5dd523fc145fc0 981d464c7c52eb6e5036234984ad0bcf c3ab 16f3b3f70fc1

+ 104 - 0
EVSE/GPL/hostapd-2.6/hostapd/hlr_auc_gw.txt

@@ -0,0 +1,104 @@
+HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
+
+hlr_auc_gw is an example implementation of the EAP-SIM/AKA/AKA'
+database/authentication gateway interface to HLR/AuC. It could be
+replaced with an implementation of SS7 gateway to GSM/UMTS
+authentication center (HLR/AuC). hostapd will send SIM/AKA
+authentication queries over a UNIX domain socket to and external
+program, e.g., hlr_auc_gw.
+
+hlr_auc_gw can be configured with GSM and UMTS authentication data with
+text files: GSM triplet file (see hostapd.sim_db) and Milenage file (see
+hlr_auc_gw.milenage_db). Milenage parameters can be used to generate
+dynamic authentication data for EAP-SIM, EAP-AKA, and EAP-AKA' while the
+GSM triplet data is used for a more static configuration (e.g., triplets
+extracted from a SIM card).
+
+Alternatively, hlr_auc_gw can be built with support for an SQLite
+database for more dynamic operations. This is enabled by adding
+"CONFIG_SQLITE=y" into hostapd/.config before building hlr_auc_gw ("make
+clean; make hlr_auc_gw" in this directory).
+
+hostapd is configured to use hlr_auc_gw with the eap_sim_db parameter in
+hostapd.conf (e.g., "eap_sim_db=unix:/tmp/hlr_auc_gw.sock"). hlr_auc_gw
+is configured with command line parameters:
+
+hlr_auc_gw [-hu] [-s<socket path>] [-g<triplet file>] [-m<milenage file>] \
+        [-D<DB file>] [-i<IND len in bits>]
+
+options:
+  -h = show this usage help
+  -u = update SQN in Milenage file on exit
+  -s<socket path> = path for UNIX domain socket
+                    (default: /tmp/hlr_auc_gw.sock)
+  -g<triplet file> = path for GSM authentication triplets
+  -m<milenage file> = path for Milenage keys
+  -D<DB file> = path to SQLite database
+  -i<IND len in bits> = IND length for SQN (default: 5)
+
+
+The SQLite database can be initialized with sqlite, e.g., by running
+following commands in "sqlite3 /path/to/hlr_auc_gw.db":
+
+CREATE TABLE milenage(
+	imsi INTEGER PRIMARY KEY NOT NULL,
+	ki CHAR(32) NOT NULL,
+	opc CHAR(32) NOT NULL,
+	amf CHAR(4) NOT NULL,
+	sqn CHAR(12) NOT NULL
+);
+INSERT INTO milenage(imsi,ki,opc,amf,sqn) VALUES(
+	232010000000000,
+	'90dca4eda45b53cf0f12d7c9c3bc6a89',
+	'cb9cccc4b9258e6dca4760379fb82581',
+	'61df',
+	'000000000000'
+);
+INSERT INTO milenage(imsi,ki,opc,amf,sqn) VALUES(
+	555444333222111,
+	'5122250214c33e723a5dd523fc145fc0',
+	'981d464c7c52eb6e5036234984ad0bcf',
+	'c3ab',
+	'16f3b3f70fc1'
+);
+
+
+hostapd (EAP server) can also be configured to store the EAP-SIM/AKA
+pseudonyms and reauth information into a SQLite database. This is
+configured with the db parameter within the eap_sim_db configuration
+option.
+
+
+"hlr_auc_gw -D /path/to/hlr_auc_gw.db" can then be used to fetch
+Milenage parameters based on IMSI from the database. The database can be
+updated dynamically while hlr_auc_gw is running to add/remove/modify
+entries.
+
+
+Example configuration files for hostapd to operate as a RADIUS
+authentication server for EAP-SIM/AKA/AKA':
+
+hostapd.conf:
+
+driver=none
+radius_server_clients=hostapd.radius_clients
+eap_server=1
+eap_user_file=hostapd.eap_user
+eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/eap_sim.db
+eap_sim_aka_result_ind=1
+
+hostapd.radius_clients:
+
+0.0.0.0/0	radius
+
+hostapd.eap_user:
+
+"0"*	AKA
+"1"*	SIM
+"2"*	AKA
+"3"*	SIM
+"4"*	AKA
+"5"*	SIM
+"6"*	AKA'
+"7"*	AKA'
+"8"*	AKA'

BIN
EVSE/GPL/hostapd-2.6/hostapd/hostapd


+ 59 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.8

@@ -0,0 +1,59 @@
+.TH HOSTAPD 8 "April  7, 2005" hostapd hostapd
+.SH NAME
+hostapd \- IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
+.SH SYNOPSIS
+.B hostapd
+[\-hdBKtv] [\-P <PID file>] <configuration file(s)>
+.SH DESCRIPTION
+This manual page documents briefly the
+.B hostapd
+daemon.
+.PP
+.B hostapd
+is a user space daemon for access point and authentication servers.
+It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and RADIUS authentication server.
+The current version supports Linux (Host AP, mac80211-based drivers) and FreeBSD (net80211).
+
+.B hostapd
+is designed to be a "daemon" program that runs in the background and acts as the backend component controlling authentication.
+.B hostapd
+supports separate frontend programs and an example text-based frontend,
+.BR hostapd_cli ,
+is included with
+.BR hostapd .
+.SH OPTIONS
+A summary of options is included below.
+For a complete description, run
+.BR hostapd
+from the command line.
+.TP
+.B \-h
+Show usage.
+.TP
+.B \-d
+Show more debug messages.
+.TP
+.B \-dd
+Show even more debug messages.
+.TP
+.B \-B
+Run daemon in the background.
+.TP
+.B \-P <PID file>
+Path to PID file.
+.TP
+.B \-K
+Include key data in debug messages.
+.TP
+.B \-t
+Include timestamps in some debug messages.
+.TP
+.B \-v
+Show hostapd version.
+.SH SEE ALSO
+.BR hostapd_cli (1).
+.SH AUTHOR
+hostapd was written by Jouni Malinen <j@w1.fi>. 
+.PP
+This manual page was written by Faidon Liambotis <faidon@cube.gr>,
+for the Debian project (but may be used by others).

+ 6 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.accept

@@ -0,0 +1,6 @@
+# List of MAC addresses that are allowed to authenticate (IEEE 802.11)
+# with the AP. Optional VLAN ID can be assigned for clients based on the
+# MAC address if dynamic VLANs (hostapd.conf dynamic_vlan option) are used.
+00:11:22:33:44:55
+00:66:77:88:99:aa
+00:00:22:33:44:55	1

+ 20 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.android.rc

@@ -0,0 +1,20 @@
+#
+# init.rc fragment for hostapd on Android
+# Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi>
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+#
+
+on post-fs-data
+    mkdir /data/misc/wifi/hostapd 0770 wifi wifi
+
+service hostapd /system/bin/hostapd \
+        -e /data/misc/wifi/entropy.bin \
+        /data/misc/wifi/hostapd.conf
+    class main
+    user wifi
+    writepid /data/misc/wifi/hostapd.pid
+    group wifi
+    disabled
+    oneshot

+ 1996 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.conf

@@ -0,0 +1,1996 @@
+##### hostapd configuration file ##############################################
+# Empty lines and lines starting with # are ignored
+
+# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for
+# management frames with the Host AP driver); wlan0 with many nl80211 drivers
+# Note: This attribute can be overridden by the values supplied with the '-i'
+# command line parameter.
+interface=wlan0
+
+# In case of atheros and nl80211 driver interfaces, an additional
+# configuration parameter, bridge, may be used to notify hostapd if the
+# interface is included in a bridge. This parameter is not used with Host AP
+# driver. If the bridge parameter is not set, the drivers will automatically
+# figure out the bridge interface (assuming sysfs is enabled and mounted to
+# /sys) and this parameter may not be needed.
+#
+# For nl80211, this parameter can be used to request the AP interface to be
+# added to the bridge automatically (brctl may refuse to do this before hostapd
+# has been started to change the interface mode). If needed, the bridge
+# interface is also created.
+#bridge=br0
+
+# Driver interface type (hostap/wired/none/nl80211/bsd);
+# default: hostap). nl80211 is used with all Linux mac80211 drivers.
+# Use driver=none if building hostapd as a standalone RADIUS server that does
+# not control any wireless/wired driver.
+# driver=hostap
+
+# Driver interface parameters (mainly for development testing use)
+# driver_params=<params>
+
+# hostapd event logger configuration
+#
+# Two output method: syslog and stdout (only usable if not forking to
+# background).
+#
+# Module bitfield (ORed bitfield of modules that will be logged; -1 = all
+# modules):
+# bit 0 (1) = IEEE 802.11
+# bit 1 (2) = IEEE 802.1X
+# bit 2 (4) = RADIUS
+# bit 3 (8) = WPA
+# bit 4 (16) = driver interface
+# bit 5 (32) = IAPP
+# bit 6 (64) = MLME
+#
+# Levels (minimum value for logged events):
+#  0 = verbose debugging
+#  1 = debugging
+#  2 = informational messages
+#  3 = notification
+#  4 = warning
+#
+logger_syslog=-1
+logger_syslog_level=2
+logger_stdout=-1
+logger_stdout_level=2
+
+# Interface for separate control program. If this is specified, hostapd
+# will create this directory and a UNIX domain socket for listening to requests
+# from external programs (CLI/GUI, etc.) for status information and
+# configuration. The socket file will be named based on the interface name, so
+# multiple hostapd processes/interfaces can be run at the same time if more
+# than one interface is used.
+# /var/run/hostapd is the recommended directory for sockets and by default,
+# hostapd_cli will use it when trying to connect with hostapd.
+ctrl_interface=/var/run/hostapd
+
+# Access control for the control interface can be configured by setting the
+# directory to allow only members of a group to use sockets. This way, it is
+# possible to run hostapd as root (since it needs to change network
+# configuration and open raw sockets) and still allow GUI/CLI components to be
+# run as non-root users. However, since the control interface can be used to
+# change the network configuration, this access needs to be protected in many
+# cases. By default, hostapd is configured to use gid 0 (root). If you
+# want to allow non-root users to use the contron interface, add a new group
+# and change this value to match with that group. Add users that should have
+# control interface access to this group.
+#
+# This variable can be a group name or gid.
+#ctrl_interface_group=wheel
+ctrl_interface_group=0
+
+
+##### IEEE 802.11 related configuration #######################################
+
+# SSID to be used in IEEE 802.11 management frames
+ssid=test
+# Alternative formats for configuring SSID
+# (double quoted string, hexdump, printf-escaped string)
+#ssid2="test"
+#ssid2=74657374
+#ssid2=P"hello\nthere"
+
+# UTF-8 SSID: Whether the SSID is to be interpreted using UTF-8 encoding
+#utf8_ssid=1
+
+# Country code (ISO/IEC 3166-1). Used to set regulatory domain.
+# Set as needed to indicate country in which device is operating.
+# This can limit available channels and transmit power.
+#country_code=US
+
+# Enable IEEE 802.11d. This advertises the country_code and the set of allowed
+# channels and transmit power levels based on the regulatory limits. The
+# country_code setting must be configured with the correct country for
+# IEEE 802.11d functions.
+# (default: 0 = disabled)
+#ieee80211d=1
+
+# Enable IEEE 802.11h. This enables radar detection and DFS support if
+# available. DFS support is required on outdoor 5 GHz channels in most countries
+# of the world. This can be used only with ieee80211d=1.
+# (default: 0 = disabled)
+#ieee80211h=1
+
+# Add Power Constraint element to Beacon and Probe Response frames
+# This config option adds Power Constraint element when applicable and Country
+# element is added. Power Constraint element is required by Transmit Power
+# Control. This can be used only with ieee80211d=1.
+# Valid values are 0..255.
+#local_pwr_constraint=3
+
+# Set Spectrum Management subfield in the Capability Information field.
+# This config option forces the Spectrum Management bit to be set. When this
+# option is not set, the value of the Spectrum Management bit depends on whether
+# DFS or TPC is required by regulatory authorities. This can be used only with
+# ieee80211d=1 and local_pwr_constraint configured.
+#spectrum_mgmt_required=1
+
+# Operation mode (a = IEEE 802.11a (5 GHz), b = IEEE 802.11b (2.4 GHz),
+# g = IEEE 802.11g (2.4 GHz), ad = IEEE 802.11ad (60 GHz); a/g options are used
+# with IEEE 802.11n (HT), too, to specify band). For IEEE 802.11ac (VHT), this
+# needs to be set to hw_mode=a. When using ACS (see channel parameter), a
+# special value "any" can be used to indicate that any support band can be used.
+# This special case is currently supported only with drivers with which
+# offloaded ACS is used.
+# Default: IEEE 802.11b
+hw_mode=g
+
+# Channel number (IEEE 802.11)
+# (default: 0, i.e., not set)
+# Please note that some drivers do not use this value from hostapd and the
+# channel will need to be configured separately with iwconfig.
+#
+# If CONFIG_ACS build option is enabled, the channel can be selected
+# automatically at run time by setting channel=acs_survey or channel=0, both of
+# which will enable the ACS survey based algorithm.
+channel=1
+
+# ACS tuning - Automatic Channel Selection
+# See: http://wireless.kernel.org/en/users/Documentation/acs
+#
+# You can customize the ACS survey algorithm with following variables:
+#
+# acs_num_scans requirement is 1..100 - number of scans to be performed that
+# are used to trigger survey data gathering of an underlying device driver.
+# Scans are passive and typically take a little over 100ms (depending on the
+# driver) on each available channel for given hw_mode. Increasing this value
+# means sacrificing startup time and gathering more data wrt channel
+# interference that may help choosing a better channel. This can also help fine
+# tune the ACS scan time in case a driver has different scan dwell times.
+#
+# acs_chan_bias is a space-separated list of <channel>:<bias> pairs. It can be
+# used to increase (or decrease) the likelihood of a specific channel to be
+# selected by the ACS algorithm. The total interference factor for each channel
+# gets multiplied by the specified bias value before finding the channel with
+# the lowest value. In other words, values between 0.0 and 1.0 can be used to
+# make a channel more likely to be picked while values larger than 1.0 make the
+# specified channel less likely to be picked. This can be used, e.g., to prefer
+# the commonly used 2.4 GHz band channels 1, 6, and 11 (which is the default
+# behavior on 2.4 GHz band if no acs_chan_bias parameter is specified).
+#
+# Defaults:
+#acs_num_scans=5
+#acs_chan_bias=1:0.8 6:0.8 11:0.8
+
+# Channel list restriction. This option allows hostapd to select one of the
+# provided channels when a channel should be automatically selected.
+# Channel list can be provided as range using hyphen ('-') or individual
+# channels can be specified by space (' ') separated values
+# Default: all channels allowed in selected hw_mode
+#chanlist=100 104 108 112 116
+#chanlist=1 6 11-13
+
+# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
+beacon_int=100
+
+# DTIM (delivery traffic information message) period (range 1..255):
+# number of beacons between DTIMs (1 = every beacon includes DTIM element)
+# (default: 2)
+dtim_period=2
+
+# Maximum number of stations allowed in station table. New stations will be
+# rejected after the station table is full. IEEE 802.11 has a limit of 2007
+# different association IDs, so this number should not be larger than that.
+# (default: 2007)
+max_num_sta=255
+
+# RTS/CTS threshold; -1 = disabled (default); range -1..65535
+# If this field is not included in hostapd.conf, hostapd will not control
+# RTS threshold and 'iwconfig wlan# rts <val>' can be used to set it.
+rts_threshold=-1
+
+# Fragmentation threshold; -1 = disabled (default); range -1, 256..2346
+# If this field is not included in hostapd.conf, hostapd will not control
+# fragmentation threshold and 'iwconfig wlan# frag <val>' can be used to set
+# it.
+fragm_threshold=-1
+
+# Rate configuration
+# Default is to enable all rates supported by the hardware. This configuration
+# item allows this list be filtered so that only the listed rates will be left
+# in the list. If the list is empty, all rates are used. This list can have
+# entries that are not in the list of rates the hardware supports (such entries
+# are ignored). The entries in this list are in 100 kbps, i.e., 11 Mbps = 110.
+# If this item is present, at least one rate have to be matching with the rates
+# hardware supports.
+# default: use the most common supported rate setting for the selected
+# hw_mode (i.e., this line can be removed from configuration file in most
+# cases)
+#supported_rates=10 20 55 110 60 90 120 180 240 360 480 540
+
+# Basic rate set configuration
+# List of rates (in 100 kbps) that are included in the basic rate set.
+# If this item is not included, usually reasonable default set is used.
+#basic_rates=10 20
+#basic_rates=10 20 55 110
+#basic_rates=60 120 240
+
+# Short Preamble
+# This parameter can be used to enable optional use of short preamble for
+# frames sent at 2 Mbps, 5.5 Mbps, and 11 Mbps to improve network performance.
+# This applies only to IEEE 802.11b-compatible networks and this should only be
+# enabled if the local hardware supports use of short preamble. If any of the
+# associated STAs do not support short preamble, use of short preamble will be
+# disabled (and enabled when such STAs disassociate) dynamically.
+# 0 = do not allow use of short preamble (default)
+# 1 = allow use of short preamble
+#preamble=1
+
+# Station MAC address -based authentication
+# Please note that this kind of access control requires a driver that uses
+# hostapd to take care of management frame processing and as such, this can be
+# used with driver=hostap or driver=nl80211, but not with driver=atheros.
+# 0 = accept unless in deny list
+# 1 = deny unless in accept list
+# 2 = use external RADIUS server (accept/deny lists are searched first)
+macaddr_acl=0
+
+# Accept/deny lists are read from separate files (containing list of
+# MAC addresses, one per line). Use absolute path name to make sure that the
+# files can be read on SIGHUP configuration reloads.
+#accept_mac_file=/etc/hostapd.accept
+#deny_mac_file=/etc/hostapd.deny
+
+# IEEE 802.11 specifies two authentication algorithms. hostapd can be
+# configured to allow both of these or only one. Open system authentication
+# should be used with IEEE 802.1X.
+# Bit fields of allowed authentication algorithms:
+# bit 0 = Open System Authentication
+# bit 1 = Shared Key Authentication (requires WEP)
+auth_algs=3
+
+# Send empty SSID in beacons and ignore probe request frames that do not
+# specify full SSID, i.e., require stations to know SSID.
+# default: disabled (0)
+# 1 = send empty (length=0) SSID in beacon and ignore probe request for
+#     broadcast SSID
+# 2 = clear SSID (ASCII 0), but keep the original length (this may be required
+#     with some clients that do not support empty SSID) and ignore probe
+#     requests for broadcast SSID
+ignore_broadcast_ssid=0
+
+# Do not reply to broadcast Probe Request frames from unassociated STA if there
+# is no room for additional stations (max_num_sta). This can be used to
+# discourage a STA from trying to associate with this AP if the association
+# would be rejected due to maximum STA limit.
+# Default: 0 (disabled)
+#no_probe_resp_if_max_sta=0
+
+# Additional vendor specific elements for Beacon and Probe Response frames
+# This parameter can be used to add additional vendor specific element(s) into
+# the end of the Beacon and Probe Response frames. The format for these
+# element(s) is a hexdump of the raw information elements (id+len+payload for
+# one or more elements)
+#vendor_elements=dd0411223301
+
+# Additional vendor specific elements for (Re)Association Response frames
+# This parameter can be used to add additional vendor specific element(s) into
+# the end of the (Re)Association Response frames. The format for these
+# element(s) is a hexdump of the raw information elements (id+len+payload for
+# one or more elements)
+#assocresp_elements=dd0411223301
+
+# TX queue parameters (EDCF / bursting)
+# tx_queue_<queue name>_<param>
+# queues: data0, data1, data2, data3, after_beacon, beacon
+#		(data0 is the highest priority queue)
+# parameters:
+#   aifs: AIFS (default 2)
+#   cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191,
+#	   16383, 32767)
+#   cwmax: cwMax (same values as cwMin, cwMax >= cwMin)
+#   burst: maximum length (in milliseconds with precision of up to 0.1 ms) for
+#          bursting
+#
+# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e):
+# These parameters are used by the access point when transmitting frames
+# to the clients.
+#
+# Low priority / AC_BK = background
+#tx_queue_data3_aifs=7
+#tx_queue_data3_cwmin=15
+#tx_queue_data3_cwmax=1023
+#tx_queue_data3_burst=0
+# Note: for IEEE 802.11b mode: cWmin=31 cWmax=1023 burst=0
+#
+# Normal priority / AC_BE = best effort
+#tx_queue_data2_aifs=3
+#tx_queue_data2_cwmin=15
+#tx_queue_data2_cwmax=63
+#tx_queue_data2_burst=0
+# Note: for IEEE 802.11b mode: cWmin=31 cWmax=127 burst=0
+#
+# High priority / AC_VI = video
+#tx_queue_data1_aifs=1
+#tx_queue_data1_cwmin=7
+#tx_queue_data1_cwmax=15
+#tx_queue_data1_burst=3.0
+# Note: for IEEE 802.11b mode: cWmin=15 cWmax=31 burst=6.0
+#
+# Highest priority / AC_VO = voice
+#tx_queue_data0_aifs=1
+#tx_queue_data0_cwmin=3
+#tx_queue_data0_cwmax=7
+#tx_queue_data0_burst=1.5
+# Note: for IEEE 802.11b mode: cWmin=7 cWmax=15 burst=3.3
+
+# 802.1D Tag (= UP) to AC mappings
+# WMM specifies following mapping of data frames to different ACs. This mapping
+# can be configured using Linux QoS/tc and sch_pktpri.o module.
+# 802.1D Tag	802.1D Designation	Access Category	WMM Designation
+# 1		BK			AC_BK		Background
+# 2		-			AC_BK		Background
+# 0		BE			AC_BE		Best Effort
+# 3		EE			AC_BE		Best Effort
+# 4		CL			AC_VI		Video
+# 5		VI			AC_VI		Video
+# 6		VO			AC_VO		Voice
+# 7		NC			AC_VO		Voice
+# Data frames with no priority information: AC_BE
+# Management frames: AC_VO
+# PS-Poll frames: AC_BE
+
+# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e):
+# for 802.11a or 802.11g networks
+# These parameters are sent to WMM clients when they associate.
+# The parameters will be used by WMM clients for frames transmitted to the
+# access point.
+#
+# note - txop_limit is in units of 32microseconds
+# note - acm is admission control mandatory flag. 0 = admission control not
+# required, 1 = mandatory
+# note - Here cwMin and cmMax are in exponent form. The actual cw value used
+# will be (2^n)-1 where n is the value given here. The allowed range for these
+# wmm_ac_??_{cwmin,cwmax} is 0..15 with cwmax >= cwmin.
+#
+wmm_enabled=1
+#
+# WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD]
+# Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver)
+#uapsd_advertisement_enabled=1
+#
+# Low priority / AC_BK = background
+wmm_ac_bk_cwmin=4
+wmm_ac_bk_cwmax=10
+wmm_ac_bk_aifs=7
+wmm_ac_bk_txop_limit=0
+wmm_ac_bk_acm=0
+# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10
+#
+# Normal priority / AC_BE = best effort
+wmm_ac_be_aifs=3
+wmm_ac_be_cwmin=4
+wmm_ac_be_cwmax=10
+wmm_ac_be_txop_limit=0
+wmm_ac_be_acm=0
+# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7
+#
+# High priority / AC_VI = video
+wmm_ac_vi_aifs=2
+wmm_ac_vi_cwmin=3
+wmm_ac_vi_cwmax=4
+wmm_ac_vi_txop_limit=94
+wmm_ac_vi_acm=0
+# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188
+#
+# Highest priority / AC_VO = voice
+wmm_ac_vo_aifs=2
+wmm_ac_vo_cwmin=2
+wmm_ac_vo_cwmax=3
+wmm_ac_vo_txop_limit=47
+wmm_ac_vo_acm=0
+# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102
+
+# Static WEP key configuration
+#
+# The key number to use when transmitting.
+# It must be between 0 and 3, and the corresponding key must be set.
+# default: not set
+#wep_default_key=0
+# The WEP keys to use.
+# A key may be a quoted string or unquoted hexadecimal digits.
+# The key length should be 5, 13, or 16 characters, or 10, 26, or 32
+# digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or
+# 128-bit (152-bit) WEP is used.
+# Only the default key must be supplied; the others are optional.
+# default: not set
+#wep_key0=123456789a
+#wep_key1="vwxyz"
+#wep_key2=0102030405060708090a0b0c0d
+#wep_key3=".2.4.6.8.0.23"
+
+# Station inactivity limit
+#
+# If a station does not send anything in ap_max_inactivity seconds, an
+# empty data frame is sent to it in order to verify whether it is
+# still in range. If this frame is not ACKed, the station will be
+# disassociated and then deauthenticated. This feature is used to
+# clear station table of old entries when the STAs move out of the
+# range.
+#
+# The station can associate again with the AP if it is still in range;
+# this inactivity poll is just used as a nicer way of verifying
+# inactivity; i.e., client will not report broken connection because
+# disassociation frame is not sent immediately without first polling
+# the STA with a data frame.
+# default: 300 (i.e., 5 minutes)
+#ap_max_inactivity=300
+#
+# The inactivity polling can be disabled to disconnect stations based on
+# inactivity timeout so that idle stations are more likely to be disconnected
+# even if they are still in range of the AP. This can be done by setting
+# skip_inactivity_poll to 1 (default 0).
+#skip_inactivity_poll=0
+
+# Disassociate stations based on excessive transmission failures or other
+# indications of connection loss. This depends on the driver capabilities and
+# may not be available with all drivers.
+#disassoc_low_ack=1
+
+# Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to
+# remain asleep). Default: 65535 (no limit apart from field size)
+#max_listen_interval=100
+
+# WDS (4-address frame) mode with per-station virtual interfaces
+# (only supported with driver=nl80211)
+# This mode allows associated stations to use 4-address frames to allow layer 2
+# bridging to be used.
+#wds_sta=1
+
+# If bridge parameter is set, the WDS STA interface will be added to the same
+# bridge by default. This can be overridden with the wds_bridge parameter to
+# use a separate bridge.
+#wds_bridge=wds-br0
+
+# Start the AP with beaconing disabled by default.
+#start_disabled=0
+
+# Client isolation can be used to prevent low-level bridging of frames between
+# associated stations in the BSS. By default, this bridging is allowed.
+#ap_isolate=1
+
+# BSS Load update period (in BUs)
+# This field is used to enable and configure adding a BSS Load element into
+# Beacon and Probe Response frames.
+#bss_load_update_period=50
+
+# Fixed BSS Load value for testing purposes
+# This field can be used to configure hostapd to add a fixed BSS Load element
+# into Beacon and Probe Response frames for testing purposes. The format is
+# <station count>:<channel utilization>:<available admission capacity>
+#bss_load_test=12:80:20000
+
+##### IEEE 802.11n related configuration ######################################
+
+# ieee80211n: Whether IEEE 802.11n (HT) is enabled
+# 0 = disabled (default)
+# 1 = enabled
+# Note: You will also need to enable WMM for full HT functionality.
+# Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band.
+#ieee80211n=1
+
+# ht_capab: HT capabilities (list of flags)
+# LDPC coding capability: [LDPC] = supported
+# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary
+#	channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz
+#	with secondary channel above the primary channel
+#	(20 MHz only if neither is set)
+#	Note: There are limits on which channels can be used with HT40- and
+#	HT40+. Following table shows the channels that may be available for
+#	HT40- and HT40+ use per IEEE 802.11n Annex J:
+#	freq		HT40-		HT40+
+#	2.4 GHz		5-13		1-7 (1-9 in Europe/Japan)
+#	5 GHz		40,48,56,64	36,44,52,60
+#	(depending on the location, not all of these channels may be available
+#	for use)
+#	Please note that 40 MHz channels may switch their primary and secondary
+#	channels if needed or creation of 40 MHz channel maybe rejected based
+#	on overlapping BSSes. These changes are done automatically when hostapd
+#	is setting up the 40 MHz channel.
+# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC]
+#	(SMPS disabled if neither is set)
+# HT-greenfield: [GF] (disabled if not set)
+# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set)
+# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set)
+# Tx STBC: [TX-STBC] (disabled if not set)
+# Rx STBC: [RX-STBC1] (one spatial stream), [RX-STBC12] (one or two spatial
+#	streams), or [RX-STBC123] (one, two, or three spatial streams); Rx STBC
+#	disabled if none of these set
+# HT-delayed Block Ack: [DELAYED-BA] (disabled if not set)
+# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not
+#	set)
+# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set)
+# 40 MHz intolerant [40-INTOLERANT] (not advertised if not set)
+# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)
+#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]
+
+# Require stations to support HT PHY (reject association if they do not)
+#require_ht=1
+
+# If set non-zero, require stations to perform scans of overlapping
+# channels to test for stations which would be affected by 40 MHz traffic.
+# This parameter sets the interval in seconds between these scans. Setting this
+# to non-zero allows 2.4 GHz band AP to move dynamically to a 40 MHz channel if
+# no co-existence issues with neighboring devices are found.
+#obss_interval=0
+
+##### IEEE 802.11ac related configuration #####################################
+
+# ieee80211ac: Whether IEEE 802.11ac (VHT) is enabled
+# 0 = disabled (default)
+# 1 = enabled
+# Note: You will also need to enable WMM for full VHT functionality.
+# Note: hw_mode=a is used to specify that 5 GHz band is used with VHT.
+#ieee80211ac=1
+
+# vht_capab: VHT capabilities (list of flags)
+#
+# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]
+# Indicates maximum MPDU length
+# 0 = 3895 octets (default)
+# 1 = 7991 octets
+# 2 = 11454 octets
+# 3 = reserved
+#
+# supported_chan_width: [VHT160] [VHT160-80PLUS80]
+# Indicates supported Channel widths
+# 0 = 160 MHz & 80+80 channel widths are not supported (default)
+# 1 = 160 MHz channel width is supported
+# 2 = 160 MHz & 80+80 channel widths are supported
+# 3 = reserved
+#
+# Rx LDPC coding capability: [RXLDPC]
+# Indicates support for receiving LDPC coded pkts
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# Short GI for 80 MHz: [SHORT-GI-80]
+# Indicates short GI support for reception of packets transmitted with TXVECTOR
+# params format equal to VHT and CBW = 80Mhz
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# Short GI for 160 MHz: [SHORT-GI-160]
+# Indicates short GI support for reception of packets transmitted with TXVECTOR
+# params format equal to VHT and CBW = 160Mhz
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# Tx STBC: [TX-STBC-2BY1]
+# Indicates support for the transmission of at least 2x1 STBC
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# Rx STBC: [RX-STBC-1] [RX-STBC-12] [RX-STBC-123] [RX-STBC-1234]
+# Indicates support for the reception of PPDUs using STBC
+# 0 = Not supported (default)
+# 1 = support of one spatial stream
+# 2 = support of one and two spatial streams
+# 3 = support of one, two and three spatial streams
+# 4 = support of one, two, three and four spatial streams
+# 5,6,7 = reserved
+#
+# SU Beamformer Capable: [SU-BEAMFORMER]
+# Indicates support for operation as a single user beamformer
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# SU Beamformee Capable: [SU-BEAMFORMEE]
+# Indicates support for operation as a single user beamformee
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# Compressed Steering Number of Beamformer Antennas Supported:
+# [BF-ANTENNA-2] [BF-ANTENNA-3] [BF-ANTENNA-4]
+#   Beamformee's capability indicating the maximum number of beamformer
+#   antennas the beamformee can support when sending compressed beamforming
+#   feedback
+# If SU beamformer capable, set to maximum value minus 1
+# else reserved (default)
+#
+# Number of Sounding Dimensions:
+# [SOUNDING-DIMENSION-2] [SOUNDING-DIMENSION-3] [SOUNDING-DIMENSION-4]
+# Beamformer's capability indicating the maximum value of the NUM_STS parameter
+# in the TXVECTOR of a VHT NDP
+# If SU beamformer capable, set to maximum value minus 1
+# else reserved (default)
+#
+# MU Beamformer Capable: [MU-BEAMFORMER]
+# Indicates support for operation as an MU beamformer
+# 0 = Not supported or sent by Non-AP STA (default)
+# 1 = Supported
+#
+# VHT TXOP PS: [VHT-TXOP-PS]
+# Indicates whether or not the AP supports VHT TXOP Power Save Mode
+#  or whether or not the STA is in VHT TXOP Power Save mode
+# 0 = VHT AP doesn't support VHT TXOP PS mode (OR) VHT STA not in VHT TXOP PS
+#  mode
+# 1 = VHT AP supports VHT TXOP PS mode (OR) VHT STA is in VHT TXOP power save
+#  mode
+#
+# +HTC-VHT Capable: [HTC-VHT]
+# Indicates whether or not the STA supports receiving a VHT variant HT Control
+# field.
+# 0 = Not supported (default)
+# 1 = supported
+#
+# Maximum A-MPDU Length Exponent: [MAX-A-MPDU-LEN-EXP0]..[MAX-A-MPDU-LEN-EXP7]
+# Indicates the maximum length of A-MPDU pre-EOF padding that the STA can recv
+# This field is an integer in the range of 0 to 7.
+# The length defined by this field is equal to
+# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets
+#
+# VHT Link Adaptation Capable: [VHT-LINK-ADAPT2] [VHT-LINK-ADAPT3]
+# Indicates whether or not the STA supports link adaptation using VHT variant
+# HT Control field
+# If +HTC-VHTcapable is 1
+#  0 = (no feedback) if the STA does not provide VHT MFB (default)
+#  1 = reserved
+#  2 = (Unsolicited) if the STA provides only unsolicited VHT MFB
+#  3 = (Both) if the STA can provide VHT MFB in response to VHT MRQ and if the
+#      STA provides unsolicited VHT MFB
+# Reserved if +HTC-VHTcapable is 0
+#
+# Rx Antenna Pattern Consistency: [RX-ANTENNA-PATTERN]
+# Indicates the possibility of Rx antenna pattern change
+# 0 = Rx antenna pattern might change during the lifetime of an association
+# 1 = Rx antenna pattern does not change during the lifetime of an association
+#
+# Tx Antenna Pattern Consistency: [TX-ANTENNA-PATTERN]
+# Indicates the possibility of Tx antenna pattern change
+# 0 = Tx antenna pattern might change during the lifetime of an association
+# 1 = Tx antenna pattern does not change during the lifetime of an association
+#vht_capab=[SHORT-GI-80][HTC-VHT]
+#
+# Require stations to support VHT PHY (reject association if they do not)
+#require_vht=1
+
+# 0 = 20 or 40 MHz operating Channel width
+# 1 = 80 MHz channel width
+# 2 = 160 MHz channel width
+# 3 = 80+80 MHz channel width
+#vht_oper_chwidth=1
+#
+# center freq = 5 GHz + (5 * index)
+# So index 42 gives center freq 5.210 GHz
+# which is channel 42 in 5G band
+#
+#vht_oper_centr_freq_seg0_idx=42
+#
+# center freq = 5 GHz + (5 * index)
+# So index 159 gives center freq 5.795 GHz
+# which is channel 159 in 5G band
+#
+#vht_oper_centr_freq_seg1_idx=159
+
+# Workaround to use station's nsts capability in (Re)Association Response frame
+# This may be needed with some deployed devices as an interoperability
+# workaround for beamforming if the AP's capability is greater than the
+# station's capability. This is disabled by default and can be enabled by
+# setting use_sta_nsts=1.
+#use_sta_nsts=0
+
+##### IEEE 802.1X-2004 related configuration ##################################
+
+# Require IEEE 802.1X authorization
+#ieee8021x=1
+
+# IEEE 802.1X/EAPOL version
+# hostapd is implemented based on IEEE Std 802.1X-2004 which defines EAPOL
+# version 2. However, there are many client implementations that do not handle
+# the new version number correctly (they seem to drop the frames completely).
+# In order to make hostapd interoperate with these clients, the version number
+# can be set to the older version (1) with this configuration value.
+#eapol_version=2
+
+# Optional displayable message sent with EAP Request-Identity. The first \0
+# in this string will be converted to ASCII-0 (nul). This can be used to
+# separate network info (comma separated list of attribute=value pairs); see,
+# e.g., RFC 4284.
+#eap_message=hello
+#eap_message=hello\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com
+
+# WEP rekeying (disabled if key lengths are not set or are set to 0)
+# Key lengths for default/broadcast and individual/unicast keys:
+# 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits)
+# 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits)
+#wep_key_len_broadcast=5
+#wep_key_len_unicast=5
+# Rekeying period in seconds. 0 = do not rekey (i.e., set keys only once)
+#wep_rekey_period=300
+
+# EAPOL-Key index workaround (set bit7) for WinXP Supplicant (needed only if
+# only broadcast keys are used)
+eapol_key_index_workaround=0
+
+# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable
+# reauthentication).
+#eap_reauth_period=3600
+
+# Use PAE group address (01:80:c2:00:00:03) instead of individual target
+# address when sending EAPOL frames with driver=wired. This is the most common
+# mechanism used in wired authentication, but it also requires that the port
+# is only used by one station.
+#use_pae_group_addr=1
+
+# EAP Re-authentication Protocol (ERP) authenticator (RFC 6696)
+#
+# Whether to initiate EAP authentication with EAP-Initiate/Re-auth-Start before
+# EAP-Identity/Request
+#erp_send_reauth_start=1
+#
+# Domain name for EAP-Initiate/Re-auth-Start. Omitted from the message if not
+# set (no local ER server). This is also used by the integrated EAP server if
+# ERP is enabled (eap_server_erp=1).
+#erp_domain=example.com
+
+##### Integrated EAP server ###################################################
+
+# Optionally, hostapd can be configured to use an integrated EAP server
+# to process EAP authentication locally without need for an external RADIUS
+# server. This functionality can be used both as a local authentication server
+# for IEEE 802.1X/EAPOL and as a RADIUS server for other devices.
+
+# Use integrated EAP server instead of external RADIUS authentication
+# server. This is also needed if hostapd is configured to act as a RADIUS
+# authentication server.
+eap_server=0
+
+# Path for EAP server user database
+# If SQLite support is included, this can be set to "sqlite:/path/to/sqlite.db"
+# to use SQLite database instead of a text file.
+#eap_user_file=/etc/hostapd.eap_user
+
+# CA certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS
+#ca_cert=/etc/hostapd.ca.pem
+
+# Server certificate (PEM or DER file) for EAP-TLS/PEAP/TTLS
+#server_cert=/etc/hostapd.server.pem
+
+# Private key matching with the server certificate for EAP-TLS/PEAP/TTLS
+# This may point to the same file as server_cert if both certificate and key
+# are included in a single file. PKCS#12 (PFX) file (.p12/.pfx) can also be
+# used by commenting out server_cert and specifying the PFX file as the
+# private_key.
+#private_key=/etc/hostapd.server.prv
+
+# Passphrase for private key
+#private_key_passwd=secret passphrase
+
+# Server identity
+# EAP methods that provide mechanism for authenticated server identity delivery
+# use this value. If not set, "hostapd" is used as a default.
+#server_id=server.example.com
+
+# Enable CRL verification.
+# Note: hostapd does not yet support CRL downloading based on CDP. Thus, a
+# valid CRL signed by the CA is required to be included in the ca_cert file.
+# This can be done by using PEM format for CA certificate and CRL and
+# concatenating these into one file. Whenever CRL changes, hostapd needs to be
+# restarted to take the new CRL into use.
+# 0 = do not verify CRLs (default)
+# 1 = check the CRL of the user certificate
+# 2 = check all CRLs in the certificate path
+#check_crl=1
+
+# TLS Session Lifetime in seconds
+# This can be used to allow TLS sessions to be cached and resumed with an
+# abbreviated handshake when using EAP-TLS/TTLS/PEAP.
+# (default: 0 = session caching and resumption disabled)
+#tls_session_lifetime=3600
+
+# Cached OCSP stapling response (DER encoded)
+# If set, this file is sent as a certificate status response by the EAP server
+# if the EAP peer requests certificate status in the ClientHello message.
+# This cache file can be updated, e.g., by running following command
+# periodically to get an update from the OCSP responder:
+# openssl ocsp \
+#	-no_nonce \
+#	-CAfile /etc/hostapd.ca.pem \
+#	-issuer /etc/hostapd.ca.pem \
+#	-cert /etc/hostapd.server.pem \
+#	-url http://ocsp.example.com:8888/ \
+#	-respout /tmp/ocsp-cache.der
+#ocsp_stapling_response=/tmp/ocsp-cache.der
+
+# Cached OCSP stapling response list (DER encoded OCSPResponseList)
+# This is similar to ocsp_stapling_response, but the extended version defined in
+# RFC 6961 to allow multiple OCSP responses to be provided.
+#ocsp_stapling_response_multi=/tmp/ocsp-multi-cache.der
+
+# dh_file: File path to DH/DSA parameters file (in PEM format)
+# This is an optional configuration file for setting parameters for an
+# ephemeral DH key exchange. In most cases, the default RSA authentication does
+# not use this configuration. However, it is possible setup RSA to use
+# ephemeral DH key exchange. In addition, ciphers with DSA keys always use
+# ephemeral DH keys. This can be used to achieve forward secrecy. If the file
+# is in DSA parameters format, it will be automatically converted into DH
+# params. This parameter is required if anonymous EAP-FAST is used.
+# You can generate DH parameters file with OpenSSL, e.g.,
+# "openssl dhparam -out /etc/hostapd.dh.pem 2048"
+#dh_file=/etc/hostapd.dh.pem
+
+# OpenSSL cipher string
+#
+# This is an OpenSSL specific configuration option for configuring the default
+# ciphers. If not set, "DEFAULT:!EXP:!LOW" is used as the default.
+# See https://www.openssl.org/docs/apps/ciphers.html for OpenSSL documentation
+# on cipher suite configuration. This is applicable only if hostapd is built to
+# use OpenSSL.
+#openssl_ciphers=DEFAULT:!EXP:!LOW
+
+# Fragment size for EAP methods
+#fragment_size=1400
+
+# Finite cyclic group for EAP-pwd. Number maps to group of domain parameters
+# using the IANA repository for IKE (RFC 2409).
+#pwd_group=19
+
+# Configuration data for EAP-SIM database/authentication gateway interface.
+# This is a text string in implementation specific format. The example
+# implementation in eap_sim_db.c uses this as the UNIX domain socket name for
+# the HLR/AuC gateway (e.g., hlr_auc_gw). In this case, the path uses "unix:"
+# prefix. If hostapd is built with SQLite support (CONFIG_SQLITE=y in .config),
+# database file can be described with an optional db=<path> parameter.
+#eap_sim_db=unix:/tmp/hlr_auc_gw.sock
+#eap_sim_db=unix:/tmp/hlr_auc_gw.sock db=/tmp/hostapd.db
+
+# EAP-SIM DB request timeout
+# This parameter sets the maximum time to wait for a database request response.
+# The parameter value is in seconds.
+#eap_sim_db_timeout=1
+
+# Encryption key for EAP-FAST PAC-Opaque values. This key must be a secret,
+# random value. It is configured as a 16-octet value in hex format. It can be
+# generated, e.g., with the following command:
+# od -tx1 -v -N16 /dev/random | colrm 1 8 | tr -d ' '
+#pac_opaque_encr_key=000102030405060708090a0b0c0d0e0f
+
+# EAP-FAST authority identity (A-ID)
+# A-ID indicates the identity of the authority that issues PACs. The A-ID
+# should be unique across all issuing servers. In theory, this is a variable
+# length field, but due to some existing implementations requiring A-ID to be
+# 16 octets in length, it is strongly recommended to use that length for the
+# field to provid interoperability with deployed peer implementations. This
+# field is configured in hex format.
+#eap_fast_a_id=101112131415161718191a1b1c1d1e1f
+
+# EAP-FAST authority identifier information (A-ID-Info)
+# This is a user-friendly name for the A-ID. For example, the enterprise name
+# and server name in a human-readable format. This field is encoded as UTF-8.
+#eap_fast_a_id_info=test server
+
+# Enable/disable different EAP-FAST provisioning modes:
+#0 = provisioning disabled
+#1 = only anonymous provisioning allowed
+#2 = only authenticated provisioning allowed
+#3 = both provisioning modes allowed (default)
+#eap_fast_prov=3
+
+# EAP-FAST PAC-Key lifetime in seconds (hard limit)
+#pac_key_lifetime=604800
+
+# EAP-FAST PAC-Key refresh time in seconds (soft limit on remaining hard
+# limit). The server will generate a new PAC-Key when this number of seconds
+# (or fewer) of the lifetime remains.
+#pac_key_refresh_time=86400
+
+# EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND
+# (default: 0 = disabled).
+#eap_sim_aka_result_ind=1
+
+# Trusted Network Connect (TNC)
+# If enabled, TNC validation will be required before the peer is allowed to
+# connect. Note: This is only used with EAP-TTLS and EAP-FAST. If any other
+# EAP method is enabled, the peer will be allowed to connect without TNC.
+#tnc=1
+
+# EAP Re-authentication Protocol (ERP) - RFC 6696
+#
+# Whether to enable ERP on the EAP server.
+#eap_server_erp=1
+
+##### IEEE 802.11f - Inter-Access Point Protocol (IAPP) #######################
+
+# Interface to be used for IAPP broadcast packets
+#iapp_interface=eth0
+
+
+##### RADIUS client configuration #############################################
+# for IEEE 802.1X with external Authentication Server, IEEE 802.11
+# authentication with external ACL for MAC addresses, and accounting
+
+# The own IP address of the access point (used as NAS-IP-Address)
+own_ip_addr=127.0.0.1
+
+# NAS-Identifier string for RADIUS messages. When used, this should be unique
+# to the NAS within the scope of the RADIUS server. Please note that hostapd
+# uses a separate RADIUS client for each BSS and as such, a unique
+# nas_identifier value should be configured separately for each BSS. This is
+# particularly important for cases where RADIUS accounting is used
+# (Accounting-On/Off messages are interpreted as clearing all ongoing sessions
+# and that may get interpreted as applying to all BSSes if the same
+# NAS-Identifier value is used.) For example, a fully qualified domain name
+# prefixed with a unique identifier of the BSS (e.g., BSSID) can be used here.
+#
+# When using IEEE 802.11r, nas_identifier must be set and must be between 1 and
+# 48 octets long.
+#
+# It is mandatory to configure either own_ip_addr or nas_identifier to be
+# compliant with the RADIUS protocol. When using RADIUS accounting, it is
+# strongly recommended that nas_identifier is set to a unique value for each
+# BSS.
+#nas_identifier=ap.example.com
+
+# RADIUS client forced local IP address for the access point
+# Normally the local IP address is determined automatically based on configured
+# IP addresses, but this field can be used to force a specific address to be
+# used, e.g., when the device has multiple IP addresses.
+#radius_client_addr=127.0.0.1
+
+# RADIUS authentication server
+#auth_server_addr=127.0.0.1
+#auth_server_port=1812
+#auth_server_shared_secret=secret
+
+# RADIUS accounting server
+#acct_server_addr=127.0.0.1
+#acct_server_port=1813
+#acct_server_shared_secret=secret
+
+# Secondary RADIUS servers; to be used if primary one does not reply to
+# RADIUS packets. These are optional and there can be more than one secondary
+# server listed.
+#auth_server_addr=127.0.0.2
+#auth_server_port=1812
+#auth_server_shared_secret=secret2
+#
+#acct_server_addr=127.0.0.2
+#acct_server_port=1813
+#acct_server_shared_secret=secret2
+
+# Retry interval for trying to return to the primary RADIUS server (in
+# seconds). RADIUS client code will automatically try to use the next server
+# when the current server is not replying to requests. If this interval is set,
+# primary server will be retried after configured amount of time even if the
+# currently used secondary server is still working.
+#radius_retry_primary_interval=600
+
+
+# Interim accounting update interval
+# If this is set (larger than 0) and acct_server is configured, hostapd will
+# send interim accounting updates every N seconds. Note: if set, this overrides
+# possible Acct-Interim-Interval attribute in Access-Accept message. Thus, this
+# value should not be configured in hostapd.conf, if RADIUS server is used to
+# control the interim interval.
+# This value should not be less 600 (10 minutes) and must not be less than
+# 60 (1 minute).
+#radius_acct_interim_interval=600
+
+# Request Chargeable-User-Identity (RFC 4372)
+# This parameter can be used to configure hostapd to request CUI from the
+# RADIUS server by including Chargeable-User-Identity attribute into
+# Access-Request packets.
+#radius_request_cui=1
+
+# Dynamic VLAN mode; allow RADIUS authentication server to decide which VLAN
+# is used for the stations. This information is parsed from following RADIUS
+# attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),
+# Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value
+# VLANID as a string). Optionally, the local MAC ACL list (accept_mac_file) can
+# be used to set static client MAC address to VLAN ID mapping.
+# 0 = disabled (default)
+# 1 = option; use default interface if RADIUS server does not include VLAN ID
+# 2 = required; reject authentication if RADIUS server does not include VLAN ID
+#dynamic_vlan=0
+
+# Per-Station AP_VLAN interface mode
+# If enabled, each station is assigned its own AP_VLAN interface.
+# This implies per-station group keying and ebtables filtering of inter-STA
+# traffic (when passed through the AP).
+# If the sta is not assigned to any VLAN, then its AP_VLAN interface will be
+# added to the bridge given by the "bridge" configuration option (see above).
+# Otherwise, it will be added to the per-VLAN bridge.
+# 0 = disabled (default)
+# 1 = enabled
+#per_sta_vif=0
+
+# VLAN interface list for dynamic VLAN mode is read from a separate text file.
+# This list is used to map VLAN ID from the RADIUS server to a network
+# interface. Each station is bound to one interface in the same way as with
+# multiple BSSIDs or SSIDs. Each line in this text file is defining a new
+# interface and the line must include VLAN ID and interface name separated by
+# white space (space or tab).
+# If no entries are provided by this file, the station is statically mapped
+# to <bss-iface>.<vlan-id> interfaces.
+#vlan_file=/etc/hostapd.vlan
+
+# Interface where 802.1q tagged packets should appear when a RADIUS server is
+# used to determine which VLAN a station is on.  hostapd creates a bridge for
+# each VLAN.  Then hostapd adds a VLAN interface (associated with the interface
+# indicated by 'vlan_tagged_interface') and the appropriate wireless interface
+# to the bridge.
+#vlan_tagged_interface=eth0
+
+# Bridge (prefix) to add the wifi and the tagged interface to. This gets the
+# VLAN ID appended. It defaults to brvlan%d if no tagged interface is given
+# and br%s.%d if a tagged interface is given, provided %s = tagged interface
+# and %d = VLAN ID.
+#vlan_bridge=brvlan
+
+# When hostapd creates a VLAN interface on vlan_tagged_interfaces, it needs
+# to know how to name it.
+# 0 = vlan<XXX>, e.g., vlan1
+# 1 = <vlan_tagged_interface>.<XXX>, e.g. eth0.1
+#vlan_naming=0
+
+# Arbitrary RADIUS attributes can be added into Access-Request and
+# Accounting-Request packets by specifying the contents of the attributes with
+# the following configuration parameters. There can be multiple of these to
+# add multiple attributes. These parameters can also be used to override some
+# of the attributes added automatically by hostapd.
+# Format: <attr_id>[:<syntax:value>]
+# attr_id: RADIUS attribute type (e.g., 26 = Vendor-Specific)
+# syntax: s = string (UTF-8), d = integer, x = octet string
+# value: attribute value in format indicated by the syntax
+# If syntax and value parts are omitted, a null value (single 0x00 octet) is
+# used.
+#
+# Additional Access-Request attributes
+# radius_auth_req_attr=<attr_id>[:<syntax:value>]
+# Examples:
+# Operator-Name = "Operator"
+#radius_auth_req_attr=126:s:Operator
+# Service-Type = Framed (2)
+#radius_auth_req_attr=6:d:2
+# Connect-Info = "testing" (this overrides the automatically generated value)
+#radius_auth_req_attr=77:s:testing
+# Same Connect-Info value set as a hexdump
+#radius_auth_req_attr=77:x:74657374696e67
+
+#
+# Additional Accounting-Request attributes
+# radius_acct_req_attr=<attr_id>[:<syntax:value>]
+# Examples:
+# Operator-Name = "Operator"
+#radius_acct_req_attr=126:s:Operator
+
+# Dynamic Authorization Extensions (RFC 5176)
+# This mechanism can be used to allow dynamic changes to user session based on
+# commands from a RADIUS server (or some other disconnect client that has the
+# needed session information). For example, Disconnect message can be used to
+# request an associated station to be disconnected.
+#
+# This is disabled by default. Set radius_das_port to non-zero UDP port
+# number to enable.
+#radius_das_port=3799
+#
+# DAS client (the host that can send Disconnect/CoA requests) and shared secret
+#radius_das_client=192.168.1.123 shared secret here
+#
+# DAS Event-Timestamp time window in seconds
+#radius_das_time_window=300
+#
+# DAS require Event-Timestamp
+#radius_das_require_event_timestamp=1
+#
+# DAS require Message-Authenticator
+#radius_das_require_message_authenticator=1
+
+##### RADIUS authentication server configuration ##############################
+
+# hostapd can be used as a RADIUS authentication server for other hosts. This
+# requires that the integrated EAP server is also enabled and both
+# authentication services are sharing the same configuration.
+
+# File name of the RADIUS clients configuration for the RADIUS server. If this
+# commented out, RADIUS server is disabled.
+#radius_server_clients=/etc/hostapd.radius_clients
+
+# The UDP port number for the RADIUS authentication server
+#radius_server_auth_port=1812
+
+# The UDP port number for the RADIUS accounting server
+# Commenting this out or setting this to 0 can be used to disable RADIUS
+# accounting while still enabling RADIUS authentication.
+#radius_server_acct_port=1813
+
+# Use IPv6 with RADIUS server (IPv4 will also be supported using IPv6 API)
+#radius_server_ipv6=1
+
+
+##### WPA/IEEE 802.11i configuration ##########################################
+
+# Enable WPA. Setting this variable configures the AP to require WPA (either
+# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either
+# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.
+# Instead of wpa_psk / wpa_passphrase, wpa_psk_radius might suffice.
+# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),
+# RADIUS authentication server must be configured, and WPA-EAP must be included
+# in wpa_key_mgmt.
+# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0)
+# and/or WPA2 (full IEEE 802.11i/RSN):
+# bit0 = WPA
+# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled)
+#wpa=1
+
+# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
+# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
+# (8..63 characters) that will be converted to PSK. This conversion uses SSID
+# so the PSK changes when ASCII passphrase is used and the SSID is changed.
+# wpa_psk (dot11RSNAConfigPSKValue)
+# wpa_passphrase (dot11RSNAConfigPSKPassPhrase)
+#wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
+#wpa_passphrase=secret passphrase
+
+# Optionally, WPA PSKs can be read from a separate text file (containing list
+# of (PSK,MAC address) pairs. This allows more than one PSK to be configured.
+# Use absolute path name to make sure that the files can be read on SIGHUP
+# configuration reloads.
+#wpa_psk_file=/etc/hostapd.wpa_psk
+
+# Optionally, WPA passphrase can be received from RADIUS authentication server
+# This requires macaddr_acl to be set to 2 (RADIUS)
+# 0 = disabled (default)
+# 1 = optional; use default passphrase/psk if RADIUS server does not include
+#	Tunnel-Password
+# 2 = required; reject authentication if RADIUS server does not include
+#	Tunnel-Password
+#wpa_psk_radius=0
+
+# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
+# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
+# added to enable SHA256-based stronger algorithms.
+# (dot11RSNAConfigAuthenticationSuitesTable)
+#wpa_key_mgmt=WPA-PSK WPA-EAP
+
+# Set of accepted cipher suites (encryption algorithms) for pairwise keys
+# (unicast packets). This is a space separated list of algorithms:
+# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
+# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
+# Group cipher suite (encryption algorithm for broadcast and multicast frames)
+# is automatically selected based on this configuration. If only CCMP is
+# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise,
+# TKIP will be used as the group cipher.
+# (dot11RSNAConfigPairwiseCiphersTable)
+# Pairwise cipher for WPA (v1) (default: TKIP)
+#wpa_pairwise=TKIP CCMP
+# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value)
+#rsn_pairwise=CCMP
+
+# Time interval for rekeying GTK (broadcast/multicast encryption keys) in
+# seconds. (dot11RSNAConfigGroupRekeyTime)
+#wpa_group_rekey=600
+
+# Rekey GTK when any STA that possesses the current GTK is leaving the BSS.
+# (dot11RSNAConfigGroupRekeyStrict)
+#wpa_strict_rekey=1
+
+# Time interval for rekeying GMK (master key used internally to generate GTKs
+# (in seconds).
+#wpa_gmk_rekey=86400
+
+# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of
+# PTK to mitigate some attacks against TKIP deficiencies.
+#wpa_ptk_rekey=600
+
+# Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up
+# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN
+# authentication and key handshake before actually associating with a new AP.
+# (dot11RSNAPreauthenticationEnabled)
+#rsn_preauth=1
+#
+# Space separated list of interfaces from which pre-authentication frames are
+# accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all
+# interface that are used for connections to other APs. This could include
+# wired interfaces and WDS links. The normal wireless data interface towards
+# associated stations (e.g., wlan0) should not be added, since
+# pre-authentication is only used with APs other than the currently associated
+# one.
+#rsn_preauth_interfaces=eth0
+
+# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e) is
+# allowed. This is only used with RSN/WPA2.
+# 0 = disabled (default)
+# 1 = enabled
+#peerkey=1
+
+# ieee80211w: Whether management frame protection (MFP) is enabled
+# 0 = disabled (default)
+# 1 = optional
+# 2 = required
+#ieee80211w=0
+
+# Group management cipher suite
+# Default: AES-128-CMAC (BIP)
+# Other options (depending on driver support):
+# BIP-GMAC-128
+# BIP-GMAC-256
+# BIP-CMAC-256
+# Note: All the stations connecting to the BSS will also need to support the
+# selected cipher. The default AES-128-CMAC is the only option that is commonly
+# available in deployed devices.
+#group_mgmt_cipher=AES-128-CMAC
+
+# Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
+# (maximum time to wait for a SA Query response)
+# dot11AssociationSAQueryMaximumTimeout, 1...4294967295
+#assoc_sa_query_max_timeout=1000
+
+# Association SA Query retry timeout (in TU = 1.024 ms; for MFP)
+# (time between two subsequent SA Query requests)
+# dot11AssociationSAQueryRetryTimeout, 1...4294967295
+#assoc_sa_query_retry_timeout=201
+
+# disable_pmksa_caching: Disable PMKSA caching
+# This parameter can be used to disable caching of PMKSA created through EAP
+# authentication. RSN preauthentication may still end up using PMKSA caching if
+# it is enabled (rsn_preauth=1).
+# 0 = PMKSA caching enabled (default)
+# 1 = PMKSA caching disabled
+#disable_pmksa_caching=0
+
+# okc: Opportunistic Key Caching (aka Proactive Key Caching)
+# Allow PMK cache to be shared opportunistically among configured interfaces
+# and BSSes (i.e., all configurations within a single hostapd process).
+# 0 = disabled (default)
+# 1 = enabled
+#okc=1
+
+# SAE threshold for anti-clogging mechanism (dot11RSNASAEAntiCloggingThreshold)
+# This parameter defines how many open SAE instances can be in progress at the
+# same time before the anti-clogging mechanism is taken into use.
+#sae_anti_clogging_threshold=5
+
+# Enabled SAE finite cyclic groups
+# SAE implementation are required to support group 19 (ECC group defined over a
+# 256-bit prime order field). All groups that are supported by the
+# implementation are enabled by default. This configuration parameter can be
+# used to specify a limited set of allowed groups. The group values are listed
+# in the IANA registry:
+# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xml#ipsec-registry-9
+#sae_groups=19 20 21 25 26
+
+##### IEEE 802.11r configuration ##############################################
+
+# Mobility Domain identifier (dot11FTMobilityDomainID, MDID)
+# MDID is used to indicate a group of APs (within an ESS, i.e., sharing the
+# same SSID) between which a STA can use Fast BSS Transition.
+# 2-octet identifier as a hex string.
+#mobility_domain=a1b2
+
+# PMK-R0 Key Holder identifier (dot11FTR0KeyHolderID)
+# 1 to 48 octet identifier.
+# This is configured with nas_identifier (see RADIUS client section above).
+
+# Default lifetime of the PMK-RO in minutes; range 1..65535
+# (dot11FTR0KeyLifetime)
+#r0_key_lifetime=10000
+
+# PMK-R1 Key Holder identifier (dot11FTR1KeyHolderID)
+# 6-octet identifier as a hex string.
+# Defaults to BSSID.
+#r1_key_holder=000102030405
+
+# Reassociation deadline in time units (TUs / 1.024 ms; range 1000..65535)
+# (dot11FTReassociationDeadline)
+#reassociation_deadline=1000
+
+# List of R0KHs in the same Mobility Domain
+# format: <MAC address> <NAS Identifier> <128-bit key as hex string>
+# This list is used to map R0KH-ID (NAS Identifier) to a destination MAC
+# address when requesting PMK-R1 key from the R0KH that the STA used during the
+# Initial Mobility Domain Association.
+#r0kh=02:01:02:03:04:05 r0kh-1.example.com 000102030405060708090a0b0c0d0e0f
+#r0kh=02:01:02:03:04:06 r0kh-2.example.com 00112233445566778899aabbccddeeff
+# And so on.. One line per R0KH.
+
+# List of R1KHs in the same Mobility Domain
+# format: <MAC address> <R1KH-ID> <128-bit key as hex string>
+# This list is used to map R1KH-ID to a destination MAC address when sending
+# PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD
+# that can request PMK-R1 keys.
+#r1kh=02:01:02:03:04:05 02:11:22:33:44:55 000102030405060708090a0b0c0d0e0f
+#r1kh=02:01:02:03:04:06 02:11:22:33:44:66 00112233445566778899aabbccddeeff
+# And so on.. One line per R1KH.
+
+# Whether PMK-R1 push is enabled at R0KH
+# 0 = do not push PMK-R1 to all configured R1KHs (default)
+# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived
+#pmk_r1_push=1
+
+# Whether to enable FT-over-DS
+# 0 = FT-over-DS disabled
+# 1 = FT-over-DS enabled (default)
+#ft_over_ds=1
+
+##### Neighbor table ##########################################################
+# Maximum number of entries kept in AP table (either for neigbor table or for
+# detecting Overlapping Legacy BSS Condition). The oldest entry will be
+# removed when adding a new entry that would make the list grow over this
+# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is
+# enabled, so this field should not be set to 0 when using IEEE 802.11g.
+# default: 255
+#ap_table_max_size=255
+
+# Number of seconds of no frames received after which entries may be deleted
+# from the AP table. Since passive scanning is not usually performed frequently
+# this should not be set to very small value. In addition, there is no
+# guarantee that every scan cycle will receive beacon frames from the
+# neighboring APs.
+# default: 60
+#ap_table_expiration_time=3600
+
+# Maximum number of stations to track on the operating channel
+# This can be used to detect dualband capable stations before they have
+# associated, e.g., to provide guidance on which colocated BSS to use.
+# Default: 0 (disabled)
+#track_sta_max_num=100
+
+# Maximum age of a station tracking entry in seconds
+# Default: 180
+#track_sta_max_age=180
+
+# Do not reply to group-addressed Probe Request from a station that was seen on
+# another radio.
+# Default: Disabled
+#
+# This can be used with enabled track_sta_max_num configuration on another
+# interface controlled by the same hostapd process to restrict Probe Request
+# frame handling from replying to group-addressed Probe Request frames from a
+# station that has been detected to be capable of operating on another band,
+# e.g., to try to reduce likelihood of the station selecting a 2.4 GHz BSS when
+# the AP operates both a 2.4 GHz and 5 GHz BSS concurrently.
+#
+# Note: Enabling this can cause connectivity issues and increase latency for
+# discovering the AP.
+#no_probe_resp_if_seen_on=wlan1
+
+# Reject authentication from a station that was seen on another radio.
+# Default: Disabled
+#
+# This can be used with enabled track_sta_max_num configuration on another
+# interface controlled by the same hostapd process to reject authentication
+# attempts from a station that has been detected to be capable of operating on
+# another band, e.g., to try to reduce likelihood of the station selecting a
+# 2.4 GHz BSS when the AP operates both a 2.4 GHz and 5 GHz BSS concurrently.
+#
+# Note: Enabling this can cause connectivity issues and increase latency for
+# connecting with the AP.
+#no_auth_if_seen_on=wlan1
+
+##### Wi-Fi Protected Setup (WPS) #############################################
+
+# WPS state
+# 0 = WPS disabled (default)
+# 1 = WPS enabled, not configured
+# 2 = WPS enabled, configured
+#wps_state=2
+
+# Whether to manage this interface independently from other WPS interfaces
+# By default, a single hostapd process applies WPS operations to all configured
+# interfaces. This parameter can be used to disable that behavior for a subset
+# of interfaces. If this is set to non-zero for an interface, WPS commands
+# issued on that interface do not apply to other interfaces and WPS operations
+# performed on other interfaces do not affect this interface.
+#wps_independent=0
+
+# AP can be configured into a locked state where new WPS Registrar are not
+# accepted, but previously authorized Registrars (including the internal one)
+# can continue to add new Enrollees.
+#ap_setup_locked=1
+
+# Universally Unique IDentifier (UUID; see RFC 4122) of the device
+# This value is used as the UUID for the internal WPS Registrar. If the AP
+# is also using UPnP, this value should be set to the device's UPnP UUID.
+# If not configured, UUID will be generated based on the local MAC address.
+#uuid=12345678-9abc-def0-1234-56789abcdef0
+
+# Note: If wpa_psk_file is set, WPS is used to generate random, per-device PSKs
+# that will be appended to the wpa_psk_file. If wpa_psk_file is not set, the
+# default PSK (wpa_psk/wpa_passphrase) will be delivered to Enrollees. Use of
+# per-device PSKs is recommended as the more secure option (i.e., make sure to
+# set wpa_psk_file when using WPS with WPA-PSK).
+
+# When an Enrollee requests access to the network with PIN method, the Enrollee
+# PIN will need to be entered for the Registrar. PIN request notifications are
+# sent to hostapd ctrl_iface monitor. In addition, they can be written to a
+# text file that could be used, e.g., to populate the AP administration UI with
+# pending PIN requests. If the following variable is set, the PIN requests will
+# be written to the configured file.
+#wps_pin_requests=/var/run/hostapd_wps_pin_requests
+
+# Device Name
+# User-friendly description of device; up to 32 octets encoded in UTF-8
+#device_name=Wireless AP
+
+# Manufacturer
+# The manufacturer of the device (up to 64 ASCII characters)
+#manufacturer=Company
+
+# Model Name
+# Model of the device (up to 32 ASCII characters)
+#model_name=WAP
+
+# Model Number
+# Additional device description (up to 32 ASCII characters)
+#model_number=123
+
+# Serial Number
+# Serial number of the device (up to 32 characters)
+#serial_number=12345
+
+# Primary Device Type
+# Used format: <categ>-<OUI>-<subcateg>
+# categ = Category as an integer value
+# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for
+#       default WPS OUI
+# subcateg = OUI-specific Sub Category as an integer value
+# Examples:
+#   1-0050F204-1 (Computer / PC)
+#   1-0050F204-2 (Computer / Server)
+#   5-0050F204-1 (Storage / NAS)
+#   6-0050F204-1 (Network Infrastructure / AP)
+#device_type=6-0050F204-1
+
+# OS Version
+# 4-octet operating system version number (hex string)
+#os_version=01020300
+
+# Config Methods
+# List of the supported configuration methods
+# Available methods: usba ethernet label display ext_nfc_token int_nfc_token
+#	nfc_interface push_button keypad virtual_display physical_display
+#	virtual_push_button physical_push_button
+#config_methods=label virtual_display virtual_push_button keypad
+
+# WPS capability discovery workaround for PBC with Windows 7
+# Windows 7 uses incorrect way of figuring out AP's WPS capabilities by acting
+# as a Registrar and using M1 from the AP. The config methods attribute in that
+# message is supposed to indicate only the configuration method supported by
+# the AP in Enrollee role, i.e., to add an external Registrar. For that case,
+# PBC shall not be used and as such, the PushButton config method is removed
+# from M1 by default. If pbc_in_m1=1 is included in the configuration file,
+# the PushButton config method is left in M1 (if included in config_methods
+# parameter) to allow Windows 7 to use PBC instead of PIN (e.g., from a label
+# in the AP).
+#pbc_in_m1=1
+
+# Static access point PIN for initial configuration and adding Registrars
+# If not set, hostapd will not allow external WPS Registrars to control the
+# access point. The AP PIN can also be set at runtime with hostapd_cli
+# wps_ap_pin command. Use of temporary (enabled by user action) and random
+# AP PIN is much more secure than configuring a static AP PIN here. As such,
+# use of the ap_pin parameter is not recommended if the AP device has means for
+# displaying a random PIN.
+#ap_pin=12345670
+
+# Skip building of automatic WPS credential
+# This can be used to allow the automatically generated Credential attribute to
+# be replaced with pre-configured Credential(s).
+#skip_cred_build=1
+
+# Additional Credential attribute(s)
+# This option can be used to add pre-configured Credential attributes into M8
+# message when acting as a Registrar. If skip_cred_build=1, this data will also
+# be able to override the Credential attribute that would have otherwise been
+# automatically generated based on network configuration. This configuration
+# option points to an external file that much contain the WPS Credential
+# attribute(s) as binary data.
+#extra_cred=hostapd.cred
+
+# Credential processing
+#   0 = process received credentials internally (default)
+#   1 = do not process received credentials; just pass them over ctrl_iface to
+#	external program(s)
+#   2 = process received credentials internally and pass them over ctrl_iface
+#	to external program(s)
+# Note: With wps_cred_processing=1, skip_cred_build should be set to 1 and
+# extra_cred be used to provide the Credential data for Enrollees.
+#
+# wps_cred_processing=1 will disabled automatic updates of hostapd.conf file
+# both for Credential processing and for marking AP Setup Locked based on
+# validation failures of AP PIN. An external program is responsible on updating
+# the configuration appropriately in this case.
+#wps_cred_processing=0
+
+# AP Settings Attributes for M7
+# By default, hostapd generates the AP Settings Attributes for M7 based on the
+# current configuration. It is possible to override this by providing a file
+# with pre-configured attributes. This is similar to extra_cred file format,
+# but the AP Settings attributes are not encapsulated in a Credential
+# attribute.
+#ap_settings=hostapd.ap_settings
+
+# WPS UPnP interface
+# If set, support for external Registrars is enabled.
+#upnp_iface=br0
+
+# Friendly Name (required for UPnP)
+# Short description for end use. Should be less than 64 characters.
+#friendly_name=WPS Access Point
+
+# Manufacturer URL (optional for UPnP)
+#manufacturer_url=http://www.example.com/
+
+# Model Description (recommended for UPnP)
+# Long description for end user. Should be less than 128 characters.
+#model_description=Wireless Access Point
+
+# Model URL (optional for UPnP)
+#model_url=http://www.example.com/model/
+
+# Universal Product Code (optional for UPnP)
+# 12-digit, all-numeric code that identifies the consumer package.
+#upc=123456789012
+
+# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band, ad = 60 GHz)
+# This value should be set according to RF band(s) supported by the AP if
+# hw_mode is not set. For dual band dual concurrent devices, this needs to be
+# set to ag to allow both RF bands to be advertized.
+#wps_rf_bands=ag
+
+# NFC password token for WPS
+# These parameters can be used to configure a fixed NFC password token for the
+# AP. This can be generated, e.g., with nfc_pw_token from wpa_supplicant. When
+# these parameters are used, the AP is assumed to be deployed with a NFC tag
+# that includes the matching NFC password token (e.g., written based on the
+# NDEF record from nfc_pw_token).
+#
+#wps_nfc_dev_pw_id: Device Password ID (16..65535)
+#wps_nfc_dh_pubkey: Hexdump of DH Public Key
+#wps_nfc_dh_privkey: Hexdump of DH Private Key
+#wps_nfc_dev_pw: Hexdump of Device Password
+
+##### Wi-Fi Direct (P2P) ######################################################
+
+# Enable P2P Device management
+#manage_p2p=1
+
+# Allow cross connection
+#allow_cross_connection=1
+
+#### TDLS (IEEE 802.11z-2010) #################################################
+
+# Prohibit use of TDLS in this BSS
+#tdls_prohibit=1
+
+# Prohibit use of TDLS Channel Switching in this BSS
+#tdls_prohibit_chan_switch=1
+
+##### IEEE 802.11v-2011 #######################################################
+
+# Time advertisement
+# 0 = disabled (default)
+# 2 = UTC time at which the TSF timer is 0
+#time_advertisement=2
+
+# Local time zone as specified in 8.3 of IEEE Std 1003.1-2004:
+# stdoffset[dst[offset][,start[/time],end[/time]]]
+#time_zone=EST5
+
+# WNM-Sleep Mode (extended sleep mode for stations)
+# 0 = disabled (default)
+# 1 = enabled (allow stations to use WNM-Sleep Mode)
+#wnm_sleep_mode=1
+
+# BSS Transition Management
+# 0 = disabled (default)
+# 1 = enabled
+#bss_transition=1
+
+# Proxy ARP
+# 0 = disabled (default)
+# 1 = enabled
+#proxy_arp=1
+
+# IPv6 Neighbor Advertisement multicast-to-unicast conversion
+# This can be used with Proxy ARP to allow multicast NAs to be forwarded to
+# associated STAs using link layer unicast delivery.
+# 0 = disabled (default)
+# 1 = enabled
+#na_mcast_to_ucast=0
+
+##### IEEE 802.11u-2011 #######################################################
+
+# Enable Interworking service
+#interworking=1
+
+# Access Network Type
+# 0 = Private network
+# 1 = Private network with guest access
+# 2 = Chargeable public network
+# 3 = Free public network
+# 4 = Personal device network
+# 5 = Emergency services only network
+# 14 = Test or experimental
+# 15 = Wildcard
+#access_network_type=0
+
+# Whether the network provides connectivity to the Internet
+# 0 = Unspecified
+# 1 = Network provides connectivity to the Internet
+#internet=1
+
+# Additional Step Required for Access
+# Note: This is only used with open network, i.e., ASRA shall ne set to 0 if
+# RSN is used.
+#asra=0
+
+# Emergency services reachable
+#esr=0
+
+# Unauthenticated emergency service accessible
+#uesa=0
+
+# Venue Info (optional)
+# The available values are defined in IEEE Std 802.11u-2011, 7.3.1.34.
+# Example values (group,type):
+# 0,0 = Unspecified
+# 1,7 = Convention Center
+# 1,13 = Coffee Shop
+# 2,0 = Unspecified Business
+# 7,1  Private Residence
+#venue_group=7
+#venue_type=1
+
+# Homogeneous ESS identifier (optional; dot11HESSID)
+# If set, this shall be identifical to one of the BSSIDs in the homogeneous
+# ESS and this shall be set to the same value across all BSSs in homogeneous
+# ESS.
+#hessid=02:03:04:05:06:07
+
+# Roaming Consortium List
+# Arbitrary number of Roaming Consortium OIs can be configured with each line
+# adding a new OI to the list. The first three entries are available through
+# Beacon and Probe Response frames. Any additional entry will be available only
+# through ANQP queries. Each OI is between 3 and 15 octets and is configured as
+# a hexstring.
+#roaming_consortium=021122
+#roaming_consortium=2233445566
+
+# Venue Name information
+# This parameter can be used to configure one or more Venue Name Duples for
+# Venue Name ANQP information. Each entry has a two or three character language
+# code (ISO-639) separated by colon from the venue name string.
+# Note that venue_group and venue_type have to be set for Venue Name
+# information to be complete.
+#venue_name=eng:Example venue
+#venue_name=fin:Esimerkkipaikka
+# Alternative format for language:value strings:
+# (double quoted string, printf-escaped string)
+#venue_name=P"eng:Example\nvenue"
+
+# Network Authentication Type
+# This parameter indicates what type of network authentication is used in the
+# network.
+# format: <network auth type indicator (1-octet hex str)> [redirect URL]
+# Network Authentication Type Indicator values:
+# 00 = Acceptance of terms and conditions
+# 01 = On-line enrollment supported
+# 02 = http/https redirection
+# 03 = DNS redirection
+#network_auth_type=00
+#network_auth_type=02http://www.example.com/redirect/me/here/
+
+# IP Address Type Availability
+# format: <1-octet encoded value as hex str>
+# (ipv4_type & 0x3f) << 2 | (ipv6_type & 0x3)
+# ipv4_type:
+# 0 = Address type not available
+# 1 = Public IPv4 address available
+# 2 = Port-restricted IPv4 address available
+# 3 = Single NATed private IPv4 address available
+# 4 = Double NATed private IPv4 address available
+# 5 = Port-restricted IPv4 address and single NATed IPv4 address available
+# 6 = Port-restricted IPv4 address and double NATed IPv4 address available
+# 7 = Availability of the address type is not known
+# ipv6_type:
+# 0 = Address type not available
+# 1 = Address type available
+# 2 = Availability of the address type not known
+#ipaddr_type_availability=14
+
+# Domain Name
+# format: <variable-octet str>[,<variable-octet str>]
+#domain_name=example.com,another.example.com,yet-another.example.com
+
+# 3GPP Cellular Network information
+# format: <MCC1,MNC1>[;<MCC2,MNC2>][;...]
+#anqp_3gpp_cell_net=244,91;310,026;234,56
+
+# NAI Realm information
+# One or more realm can be advertised. Each nai_realm line adds a new realm to
+# the set. These parameters provide information for stations using Interworking
+# network selection to allow automatic connection to a network based on
+# credentials.
+# format: <encoding>,<NAI Realm(s)>[,<EAP Method 1>][,<EAP Method 2>][,...]
+# encoding:
+#	0 = Realm formatted in accordance with IETF RFC 4282
+#	1 = UTF-8 formatted character string that is not formatted in
+#	    accordance with IETF RFC 4282
+# NAI Realm(s): Semi-colon delimited NAI Realm(s)
+# EAP Method: <EAP Method>[:<[AuthParam1:Val1]>][<[AuthParam2:Val2]>][...]
+# EAP Method types, see:
+# http://www.iana.org/assignments/eap-numbers/eap-numbers.xhtml#eap-numbers-4
+# AuthParam (Table 8-188 in IEEE Std 802.11-2012):
+# ID 2 = Non-EAP Inner Authentication Type
+#	1 = PAP, 2 = CHAP, 3 = MSCHAP, 4 = MSCHAPV2
+# ID 3 = Inner authentication EAP Method Type
+# ID 5 = Credential Type
+#	1 = SIM, 2 = USIM, 3 = NFC Secure Element, 4 = Hardware Token,
+#	5 = Softoken, 6 = Certificate, 7 = username/password, 9 = Anonymous,
+#	10 = Vendor Specific
+#nai_realm=0,example.com;example.net
+# EAP methods EAP-TLS with certificate and EAP-TTLS/MSCHAPv2 with
+# username/password
+#nai_realm=0,example.org,13[5:6],21[2:4][5:7]
+
+# Arbitrary ANQP-element configuration
+# Additional ANQP-elements with arbitrary values can be defined by specifying
+# their contents in raw format as a hexdump of the payload. Note that these
+# values will override ANQP-element contents that may have been specified in the
+# more higher layer configuration parameters listed above.
+# format: anqp_elem=<InfoID>:<hexdump of payload>
+# For example, AP Geospatial Location ANQP-element with unknown location:
+#anqp_elem=265:0000
+# For example, AP Civic Location ANQP-element with unknown location:
+#anqp_elem=266:000000
+
+# GAS Address 3 behavior
+# 0 = P2P specification (Address3 = AP BSSID) workaround enabled by default
+#     based on GAS request Address3
+# 1 = IEEE 802.11 standard compliant regardless of GAS request Address3
+# 2 = Force non-compliant behavior (Address3 = AP BSSID for all cases)
+#gas_address3=0
+
+# QoS Map Set configuration
+#
+# Comma delimited QoS Map Set in decimal values
+# (see IEEE Std 802.11-2012, 8.4.2.97)
+#
+# format:
+# [<DSCP Exceptions[DSCP,UP]>,]<UP 0 range[low,high]>,...<UP 7 range[low,high]>
+#
+# There can be up to 21 optional DSCP Exceptions which are pairs of DSCP Value
+# (0..63 or 255) and User Priority (0..7). This is followed by eight DSCP Range
+# descriptions with DSCP Low Value and DSCP High Value pairs (0..63 or 255) for
+# each UP starting from 0. If both low and high value are set to 255, the
+# corresponding UP is not used.
+#
+# default: not set
+#qos_map_set=53,2,22,6,8,15,0,7,255,255,16,31,32,39,255,255,40,47,255,255
+
+##### Hotspot 2.0 #############################################################
+
+# Enable Hotspot 2.0 support
+#hs20=1
+
+# Disable Downstream Group-Addressed Forwarding (DGAF)
+# This can be used to configure a network where no group-addressed frames are
+# allowed. The AP will not forward any group-address frames to the stations and
+# random GTKs are issued for each station to prevent associated stations from
+# forging such frames to other stations in the BSS.
+#disable_dgaf=1
+
+# OSU Server-Only Authenticated L2 Encryption Network
+#osen=1
+
+# ANQP Domain ID (0..65535)
+# An identifier for a set of APs in an ESS that share the same common ANQP
+# information. 0 = Some of the ANQP information is unique to this AP (default).
+#anqp_domain_id=1234
+
+# Deauthentication request timeout
+# If the RADIUS server indicates that the station is not allowed to connect to
+# the BSS/ESS, the AP can allow the station some time to download a
+# notification page (URL included in the message). This parameter sets that
+# timeout in seconds.
+#hs20_deauth_req_timeout=60
+
+# Operator Friendly Name
+# This parameter can be used to configure one or more Operator Friendly Name
+# Duples. Each entry has a two or three character language code (ISO-639)
+# separated by colon from the operator friendly name string.
+#hs20_oper_friendly_name=eng:Example operator
+#hs20_oper_friendly_name=fin:Esimerkkioperaattori
+
+# Connection Capability
+# This can be used to advertise what type of IP traffic can be sent through the
+# hotspot (e.g., due to firewall allowing/blocking protocols/ports).
+# format: <IP Protocol>:<Port Number>:<Status>
+# IP Protocol: 1 = ICMP, 6 = TCP, 17 = UDP
+# Port Number: 0..65535
+# Status: 0 = Closed, 1 = Open, 2 = Unknown
+# Each hs20_conn_capab line is added to the list of advertised tuples.
+#hs20_conn_capab=1:0:2
+#hs20_conn_capab=6:22:1
+#hs20_conn_capab=17:5060:0
+
+# WAN Metrics
+# format: <WAN Info>:<DL Speed>:<UL Speed>:<DL Load>:<UL Load>:<LMD>
+# WAN Info: B0-B1: Link Status, B2: Symmetric Link, B3: At Capabity
+#    (encoded as two hex digits)
+#    Link Status: 1 = Link up, 2 = Link down, 3 = Link in test state
+# Downlink Speed: Estimate of WAN backhaul link current downlink speed in kbps;
+#	1..4294967295; 0 = unknown
+# Uplink Speed: Estimate of WAN backhaul link current uplink speed in kbps
+#	1..4294967295; 0 = unknown
+# Downlink Load: Current load of downlink WAN connection (scaled to 255 = 100%)
+# Uplink Load: Current load of uplink WAN connection (scaled to 255 = 100%)
+# Load Measurement Duration: Duration for measuring downlink/uplink load in
+# tenths of a second (1..65535); 0 if load cannot be determined
+#hs20_wan_metrics=01:8000:1000:80:240:3000
+
+# Operating Class Indication
+# List of operating classes the BSSes in this ESS use. The Global operating
+# classes in Table E-4 of IEEE Std 802.11-2012 Annex E define the values that
+# can be used in this.
+# format: hexdump of operating class octets
+# for example, operating classes 81 (2.4 GHz channels 1-13) and 115 (5 GHz
+# channels 36-48):
+#hs20_operating_class=5173
+
+# OSU icons
+# <Icon Width>:<Icon Height>:<Language code>:<Icon Type>:<Name>:<file path>
+#hs20_icon=32:32:eng:image/png:icon32:/tmp/icon32.png
+#hs20_icon=64:64:eng:image/png:icon64:/tmp/icon64.png
+
+# OSU SSID (see ssid2 for format description)
+# This is the SSID used for all OSU connections to all the listed OSU Providers.
+#osu_ssid="example"
+
+# OSU Providers
+# One or more sets of following parameter. Each OSU provider is started by the
+# mandatory osu_server_uri item. The other parameters add information for the
+# last added OSU provider.
+#
+#osu_server_uri=https://example.com/osu/
+#osu_friendly_name=eng:Example operator
+#osu_friendly_name=fin:Esimerkkipalveluntarjoaja
+#osu_nai=anonymous@example.com
+#osu_method_list=1 0
+#osu_icon=icon32
+#osu_icon=icon64
+#osu_service_desc=eng:Example services
+#osu_service_desc=fin:Esimerkkipalveluja
+#
+#osu_server_uri=...
+
+##### Fast Session Transfer (FST) support #####################################
+#
+# The options in this section are only available when the build configuration
+# option CONFIG_FST is set while compiling hostapd. They allow this interface
+# to be a part of FST setup.
+#
+# FST is the transfer of a session from a channel to another channel, in the
+# same or different frequency bands.
+#
+# For detals, see IEEE Std 802.11ad-2012.
+
+# Identifier of an FST Group the interface belongs to.
+#fst_group_id=bond0
+
+# Interface priority within the FST Group.
+# Announcing a higher priority for an interface means declaring it more
+# preferable for FST switch.
+# fst_priority is in 1..255 range with 1 being the lowest priority.
+#fst_priority=100
+
+# Default LLT value for this interface in milliseconds. The value used in case
+# no value provided during session setup. Default is 50 ms.
+# fst_llt is in 1..4294967 range (due to spec limitation, see 10.32.2.2
+# Transitioning between states).
+#fst_llt=100
+
+##### Radio measurements / location ###########################################
+
+# The content of a LCI measurement subelement
+#lci=<Hexdump of binary data of the LCI report>
+
+# The content of a location civic measurement subelement
+#civic=<Hexdump of binary data of the location civic report>
+
+# Enable neighbor report via radio measurements
+#rrm_neighbor_report=1
+
+# Publish fine timing measurement (FTM) responder functionality
+# This parameter only controls publishing via Extended Capabilities element.
+# Actual functionality is managed outside hostapd.
+#ftm_responder=0
+
+# Publish fine timing measurement (FTM) initiator functionality
+# This parameter only controls publishing via Extended Capabilities element.
+# Actual functionality is managed outside hostapd.
+#ftm_initiator=0
+
+##### TESTING OPTIONS #########################################################
+#
+# The options in this section are only available when the build configuration
+# option CONFIG_TESTING_OPTIONS is set while compiling hostapd. They allow
+# testing some scenarios that are otherwise difficult to reproduce.
+#
+# Ignore probe requests sent to hostapd with the given probability, must be a
+# floating point number in the range [0, 1).
+#ignore_probe_probability=0.0
+#
+# Ignore authentication frames with the given probability
+#ignore_auth_probability=0.0
+#
+# Ignore association requests with the given probability
+#ignore_assoc_probability=0.0
+#
+# Ignore reassociation requests with the given probability
+#ignore_reassoc_probability=0.0
+#
+# Corrupt Key MIC in GTK rekey EAPOL-Key frames with the given probability
+#corrupt_gtk_rekey_mic_probability=0.0
+#
+# Include only ECSA IE without CSA IE where possible
+# (channel switch operating class is needed)
+#ecsa_ie_only=0
+
+##### Multiple BSSID support ##################################################
+#
+# Above configuration is using the default interface (wlan#, or multi-SSID VLAN
+# interfaces). Other BSSIDs can be added by using separator 'bss' with
+# default interface name to be allocated for the data packets of the new BSS.
+#
+# hostapd will generate BSSID mask based on the BSSIDs that are
+# configured. hostapd will verify that dev_addr & MASK == dev_addr. If this is
+# not the case, the MAC address of the radio must be changed before starting
+# hostapd (ifconfig wlan0 hw ether <MAC addr>). If a BSSID is configured for
+# every secondary BSS, this limitation is not applied at hostapd and other
+# masks may be used if the driver supports them (e.g., swap the locally
+# administered bit)
+#
+# BSSIDs are assigned in order to each BSS, unless an explicit BSSID is
+# specified using the 'bssid' parameter.
+# If an explicit BSSID is specified, it must be chosen such that it:
+# - results in a valid MASK that covers it and the dev_addr
+# - is not the same as the MAC address of the radio
+# - is not the same as any other explicitly specified BSSID
+#
+# Alternatively, the 'use_driver_iface_addr' parameter can be used to request
+# hostapd to use the driver auto-generated interface address (e.g., to use the
+# exact MAC addresses allocated to the device).
+#
+# Not all drivers support multiple BSSes. The exact mechanism for determining
+# the driver capabilities is driver specific. With the current (i.e., a recent
+# kernel) drivers using nl80211, this information can be checked with "iw list"
+# (search for "valid interface combinations").
+#
+# Please note that hostapd uses some of the values configured for the first BSS
+# as the defaults for the following BSSes. However, it is recommended that all
+# BSSes include explicit configuration of all relevant configuration items.
+#
+#bss=wlan0_0
+#ssid=test2
+# most of the above items can be used here (apart from radio interface specific
+# items, like channel)
+
+#bss=wlan0_1
+#bssid=00:13:10:95:fe:0b
+# ...

+ 5 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.deny

@@ -0,0 +1,5 @@
+# List of MAC addresses that are not allowed to authenticate (IEEE 802.11)
+# with the AP.
+00:20:30:40:50:60
+00:ab:cd:ef:12:34
+00:00:30:40:50:60

+ 103 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.eap_user

@@ -0,0 +1,103 @@
+# hostapd user database for integrated EAP server
+
+# Each line must contain an identity, EAP method(s), and an optional password
+# separated with whitespace (space or tab). The identity and password must be
+# double quoted ("user"). Password can alternatively be stored as
+# NtPasswordHash (16-byte MD4 hash of the unicode presentation of the password
+# in unicode) if it is used for MSCHAP or MSCHAPv2 authentication. This means
+# that the plaintext password does not need to be included in the user file.
+# Password hash is stored as hash:<16-octets of hex data> without quotation
+# marks.
+
+# [2] flag in the end of the line can be used to mark users for tunneled phase
+# 2 authentication (e.g., within EAP-PEAP). In these cases, an anonymous
+# identity can be used in the unencrypted phase 1 and the real user identity
+# is transmitted only within the encrypted tunnel in phase 2. If non-anonymous
+# access is needed, two user entries is needed, one for phase 1 and another
+# with the same username for phase 2.
+#
+# EAP-TLS, EAP-PEAP, EAP-TTLS, EAP-FAST, EAP-SIM, and EAP-AKA do not use
+# password option.
+# EAP-MD5, EAP-MSCHAPV2, EAP-GTC, EAP-PAX, EAP-PSK, and EAP-SAKE require a
+# password.
+# EAP-PEAP, EAP-TTLS, and EAP-FAST require Phase 2 configuration.
+#
+# * can be used as a wildcard to match any user identity. The main purposes for
+# this are to set anonymous phase 1 identity for EAP-PEAP and EAP-TTLS and to
+# avoid having to configure every certificate for EAP-TLS authentication. The
+# first matching entry is selected, so * should be used as the last phase 1
+# user entry.
+#
+# "prefix"* can be used to match the given prefix and anything after this. The
+# main purpose for this is to be able to avoid EAP method negotiation when the
+# method is using known prefix in identities (e.g., EAP-SIM and EAP-AKA). This
+# is only allowed for phase 1 identities.
+#
+# Multiple methods can be configured to make the authenticator try them one by
+# one until the peer accepts one. The method names are separated with a
+# comma (,).
+#
+# [ver=0] and [ver=1] flags after EAP type PEAP can be used to force PEAP
+# version based on the Phase 1 identity. Without this flag, the EAP
+# authenticator advertises the highest supported version and select the version
+# based on the first PEAP packet from the supplicant.
+#
+# EAP-TTLS supports both EAP and non-EAP authentication inside the tunnel.
+# Tunneled EAP methods are configured with standard EAP method name and [2]
+# flag. Non-EAP methods can be enabled by following method names: TTLS-PAP,
+# TTLS-CHAP, TTLS-MSCHAP, TTLS-MSCHAPV2. TTLS-PAP and TTLS-CHAP require a
+# plaintext password while TTLS-MSCHAP and TTLS-MSCHAPV2 can use NT password
+# hash.
+#
+# Arbitrary RADIUS attributes can be added into Access-Accept packets similarly
+# to the way radius_auth_req_attr is used for Access-Request packet in
+# hostapd.conf. For EAP server, this is configured separately for each user
+# entry with radius_accept_attr=<value> line(s) following the main user entry
+# line.
+
+# Phase 1 users
+"user"		MD5	"password"
+"test user"	MD5	"secret"
+"example user"	TLS
+"DOMAIN\user"	MSCHAPV2	"password"
+"gtc user"	GTC	"password"
+"pax user"	PAX	"unknown"
+"pax.user@example.com"	PAX	0123456789abcdef0123456789abcdef
+"psk user"	PSK	"unknown"
+"psk.user@example.com"	PSK	0123456789abcdef0123456789abcdef
+"sake.user@example.com"	SAKE	0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
+"ttls"		TTLS
+"not anonymous"	PEAP
+# Default to EAP-SIM and EAP-AKA based on fixed identity prefixes
+"0"*		AKA,TTLS,TLS,PEAP,SIM
+"1"*		SIM,TTLS,TLS,PEAP,AKA
+"2"*		AKA,TTLS,TLS,PEAP,SIM
+"3"*		SIM,TTLS,TLS,PEAP,AKA
+"4"*		AKA,TTLS,TLS,PEAP,SIM
+"5"*		SIM,TTLS,TLS,PEAP,AKA
+"6"*		AKA'
+"7"*		AKA'
+"8"*		AKA'
+
+# Wildcard for all other identities
+*		PEAP,TTLS,TLS,SIM,AKA
+
+# Phase 2 (tunnelled within EAP-PEAP or EAP-TTLS) users
+"t-md5"		MD5	"password"	[2]
+"DOMAIN\t-mschapv2"	MSCHAPV2	"password"	[2]
+"t-gtc"		GTC	"password"	[2]
+"not anonymous"	MSCHAPV2	"password"	[2]
+"user"		MD5,GTC,MSCHAPV2	"password"	[2]
+"test user"	MSCHAPV2	hash:000102030405060708090a0b0c0d0e0f	[2]
+"ttls-user"	TTLS-PAP,TTLS-CHAP,TTLS-MSCHAP,TTLS-MSCHAPV2	"password"	[2]
+
+# Default to EAP-SIM and EAP-AKA based on fixed identity prefixes in phase 2
+"0"*		AKA	[2]
+"1"*		SIM	[2]
+"2"*		AKA	[2]
+"3"*		SIM	[2]
+"4"*		AKA	[2]
+"5"*		SIM	[2]
+"6"*		AKA'	[2]
+"7"*		AKA'	[2]
+"8"*		AKA'	[2]

+ 26 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.eap_user_sqlite

@@ -0,0 +1,26 @@
+CREATE TABLE users(
+	identity TEXT PRIMARY KEY,
+	methods TEXT,
+	password TEXT,
+	remediation TEXT,
+	phase2 INTEGER
+);
+
+CREATE TABLE wildcards(
+	identity TEXT PRIMARY KEY,
+	methods TEXT
+);
+
+INSERT INTO users(identity,methods,password,phase2) VALUES ('user','TTLS-MSCHAPV2','password',1);
+INSERT INTO users(identity,methods,password,phase2) VALUES ('DOMAIN\mschapv2 user','TTLS-MSCHAPV2','password',1);
+
+INSERT INTO wildcards(identity,methods) VALUES ('','TTLS,TLS');
+INSERT INTO wildcards(identity,methods) VALUES ('0','AKA');
+
+CREATE TABLE authlog(
+	timestamp TEXT,
+	session TEXT,
+	nas_ip TEXT,
+	username TEXT,
+	note TEXT
+);

+ 4 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.radius_clients

@@ -0,0 +1,4 @@
+# RADIUS client configuration for the RADIUS server
+10.1.2.3	secret passphrase
+192.168.1.0/24	another very secret passphrase
+0.0.0.0/0	radius

+ 9 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.sim_db

@@ -0,0 +1,9 @@
+# Example GSM authentication triplet file for EAP-SIM authenticator
+# IMSI:Kc:SRES:RAND
+# IMSI: ASCII string (numbers)
+# Kc: hex, 8 octets
+# SRES: hex, 4 octets
+# RAND: hex, 16 octets
+234567898765432:A0A1A2A3A4A5A6A7:D1D2D3D4:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+234567898765432:B0B1B2B3B4B5B6B7:E1E2E3E4:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+234567898765432:C0C1C2C3C4C5C6C7:F1F2F3F4:CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

+ 9 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.vlan

@@ -0,0 +1,9 @@
+# VLAN ID to network interface mapping
+1	vlan1
+2	vlan2
+3	vlan3
+100	guest
+# Optional wildcard entry matching all VLAN IDs. The first # in the interface
+# name will be replaced with the VLAN ID. The network interfaces are created
+# (and removed) dynamically based on the use.
+*	vlan#

+ 9 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd.wpa_psk

@@ -0,0 +1,9 @@
+# List of WPA PSKs. Each line, except for empty lines and lines starting
+# with #, must contain a MAC address and PSK separated with a space.
+# Special MAC address 00:00:00:00:00:00 can be used to configure PSKs that
+# anyone can use. PSK can be configured as an ASCII passphrase of 8..63
+# characters or as a 256-bit hex PSK (64 hex digits).
+00:00:00:00:00:00 secret passphrase
+00:11:22:33:44:55 another passphrase
+00:22:33:44:55:66 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
+00:00:00:00:00:00 another passphrase for all STAs

BIN
EVSE/GPL/hostapd-2.6/hostapd/hostapd_cli


+ 89 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd_cli.1

@@ -0,0 +1,89 @@
+.TH HOSTAPD_CLI 1 "April  7, 2005" hostapd_cli "hostapd command-line interface"
+.SH NAME
+hostapd_cli \- hostapd command-line interface
+.SH SYNOPSIS
+.B hostapd_cli
+[\-p<path>] [\-i<ifname>] [\-a<path>] [\-hvB] [command..]
+.SH DESCRIPTION
+This manual page documents briefly the
+.B hostapd_cli
+utility.
+.PP
+.B hostapd_cli
+is a command-line interface for the
+.B hostapd
+daemon.
+
+.B hostapd
+is a user space daemon for access point and authentication servers.
+It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and RADIUS authentication server.
+For more information about
+.B hostapd
+refer to the
+.BR hostapd (8)
+man page.
+.SH OPTIONS
+A summary of options is included below.
+For a complete description, run
+.BR hostapd_cli
+from the command line.
+.TP
+.B \-p<path>
+Path to find control sockets.
+
+Default: /var/run/hostapd
+.TP
+.B \-i<ifname>
+Interface to listen on.
+
+Default: first interface found in socket path.
+.TP
+.B \-a<path>
+Run in daemon mode executing the action file based on events from hostapd.
+.TP
+.B \-B
+Run a daemon in the background.
+.TP
+.B \-h
+Show usage.
+.TP
+.B \-v
+Show hostapd_cli version.
+.SH COMMANDS
+A summary of commands is included below.
+For a complete description, run
+.BR hostapd_cli
+from the command line.
+.TP
+.B mib
+Get MIB variables (dot1x, dot11, radius).
+.TP
+.B sta <addr>
+Get MIB variables for one station.
+.TP
+.B all_sta
+Get MIB variables for all stations.
+.TP
+.B help
+Get usage help.
+.TP
+.B interface [ifname] 
+Show interfaces/select interface.
+.TP
+.B level <debug level>
+Change debug level.
+.TP
+.B license
+Show full
+.B hostapd_cli
+license.
+.TP
+.B quit
+Exit hostapd_cli.
+.SH SEE ALSO
+.BR hostapd (8).
+.SH AUTHOR
+hostapd_cli was written by Jouni Malinen <j@w1.fi>. 
+.PP
+This manual page was written by Faidon Liambotis <faidon@cube.gr>,
+for the Debian project (but may be used by others).

+ 1807 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd_cli.c

@@ -0,0 +1,1807 @@
+/*
+ * hostapd - command line interface for hostapd daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+#include <dirent.h>
+
+#include "common/wpa_ctrl.h"
+#include "common/ieee802_11_defs.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/edit.h"
+#include "common/version.h"
+#include "common/cli.h"
+
+#ifndef CONFIG_NO_CTRL_IFACE
+
+static const char *const hostapd_cli_version =
+"hostapd_cli v" VERSION_STR "\n"
+"Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi> and contributors";
+
+static struct wpa_ctrl *ctrl_conn;
+static int hostapd_cli_quit = 0;
+static int hostapd_cli_attached = 0;
+
+#ifndef CONFIG_CTRL_IFACE_DIR
+#define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
+#endif /* CONFIG_CTRL_IFACE_DIR */
+static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
+static const char *client_socket_dir = NULL;
+
+static char *ctrl_ifname = NULL;
+static const char *pid_file = NULL;
+static const char *action_file = NULL;
+static int ping_interval = 5;
+static int interactive = 0;
+static int event_handler_registered = 0;
+
+static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */
+
+static void print_help(FILE *stream, const char *cmd);
+static char ** list_cmd_list(void);
+static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx);
+
+
+static void usage(void)
+{
+	fprintf(stderr, "%s\n", hostapd_cli_version);
+	fprintf(stderr,
+		"\n"
+		"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
+		"[-a<path>] \\\n"
+		"                   [-P<pid file>] [-G<ping interval>] [command..]\n"
+		"\n"
+		"Options:\n"
+		"   -h           help (show this usage text)\n"
+		"   -v           shown version information\n"
+		"   -p<path>     path to find control sockets (default: "
+		"/var/run/hostapd)\n"
+		"   -s<dir_path> dir path to open client sockets (default: "
+		CONFIG_CTRL_IFACE_DIR ")\n"
+		"   -a<file>     run in daemon mode executing the action file "
+		"based on events\n"
+		"                from hostapd\n"
+		"   -B           run a daemon in the background\n"
+		"   -i<ifname>   Interface to listen on (default: first "
+		"interface found in the\n"
+		"                socket path)\n\n");
+	print_help(stderr, NULL);
+}
+
+
+static void register_event_handler(struct wpa_ctrl *ctrl)
+{
+	if (!ctrl_conn)
+		return;
+	if (interactive) {
+		event_handler_registered =
+			!eloop_register_read_sock(wpa_ctrl_get_fd(ctrl),
+						  hostapd_cli_receive,
+						  NULL, NULL);
+	}
+}
+
+
+static void unregister_event_handler(struct wpa_ctrl *ctrl)
+{
+	if (!ctrl_conn)
+		return;
+	if (interactive && event_handler_registered) {
+		eloop_unregister_read_sock(wpa_ctrl_get_fd(ctrl));
+		event_handler_registered = 0;
+	}
+}
+
+
+static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
+{
+#ifndef CONFIG_CTRL_IFACE_UDP
+	char *cfile;
+	int flen;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
+
+	if (ifname == NULL)
+		return NULL;
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+	ctrl_conn = wpa_ctrl_open(ifname);
+	return ctrl_conn;
+#else /* CONFIG_CTRL_IFACE_UDP */
+	flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
+	cfile = malloc(flen);
+	if (cfile == NULL)
+		return NULL;
+	snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
+
+	if (client_socket_dir && client_socket_dir[0] &&
+	    access(client_socket_dir, F_OK) < 0) {
+		perror(client_socket_dir);
+		free(cfile);
+		return NULL;
+	}
+
+	ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
+	free(cfile);
+	return ctrl_conn;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+}
+
+
+static void hostapd_cli_close_connection(void)
+{
+	if (ctrl_conn == NULL)
+		return;
+
+	unregister_event_handler(ctrl_conn);
+	if (hostapd_cli_attached) {
+		wpa_ctrl_detach(ctrl_conn);
+		hostapd_cli_attached = 0;
+	}
+	wpa_ctrl_close(ctrl_conn);
+	ctrl_conn = NULL;
+}
+
+
+static void hostapd_cli_msg_cb(char *msg, size_t len)
+{
+	printf("%s\n", msg);
+}
+
+
+static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
+{
+	char buf[4096];
+	size_t len;
+	int ret;
+
+	if (ctrl_conn == NULL) {
+		printf("Not connected to hostapd - command dropped.\n");
+		return -1;
+	}
+	len = sizeof(buf) - 1;
+	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
+			       hostapd_cli_msg_cb);
+	if (ret == -2) {
+		printf("'%s' command timed out.\n", cmd);
+		return -2;
+	} else if (ret < 0) {
+		printf("'%s' command failed.\n", cmd);
+		return -1;
+	}
+	if (print) {
+		buf[len] = '\0';
+		printf("%s", buf);
+	}
+	return 0;
+}
+
+
+static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
+{
+	return _wpa_ctrl_command(ctrl, cmd, 1);
+}
+
+
+static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd,
+			   int min_args, int argc, char *argv[])
+{
+	char buf[4096];
+
+	if (argc < min_args) {
+		printf("Invalid %s command - at least %d argument%s required.\n",
+		       cmd, min_args, min_args > 1 ? "s are" : " is");
+		return -1;
+	}
+	if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
+		return -1;
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "PING");
+}
+
+
+static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "RELOG");
+}
+
+
+static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
+		return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
+	return wpa_ctrl_command(ctrl, "STATUS");
+}
+
+
+static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	if (argc > 0) {
+		char buf[100];
+		os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
+		return wpa_ctrl_command(ctrl, buf);
+	}
+	return wpa_ctrl_command(ctrl, "MIB");
+}
+
+
+static int hostapd_cli_exec(const char *program, const char *arg1,
+			    const char *arg2)
+{
+	char *arg;
+	size_t len;
+	int res;
+
+	len = os_strlen(arg1) + os_strlen(arg2) + 2;
+	arg = os_malloc(len);
+	if (arg == NULL)
+		return -1;
+	os_snprintf(arg, len, "%s %s", arg1, arg2);
+	res = os_exec(program, arg, 1);
+	os_free(arg);
+
+	return res;
+}
+
+
+static void hostapd_cli_action_process(char *msg, size_t len)
+{
+	const char *pos;
+
+	pos = msg;
+	if (*pos == '<') {
+		pos = os_strchr(pos, '>');
+		if (pos)
+			pos++;
+		else
+			pos = msg;
+	}
+
+	hostapd_cli_exec(action_file, ctrl_ifname, pos);
+}
+
+
+static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char buf[64];
+	if (argc < 1) {
+		printf("Invalid 'sta' command - at least one argument, STA "
+		       "address, is required.\n");
+		return -1;
+	}
+	if (argc > 1)
+		snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
+	else
+		snprintf(buf, sizeof(buf), "STA %s", argv[0]);
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	char buf[64];
+	if (argc != 1) {
+		printf("Invalid 'new_sta' command - exactly one argument, STA "
+		       "address, is required.\n");
+		return -1;
+	}
+	snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
+					  char *argv[])
+{
+	char buf[64];
+	if (argc < 1) {
+		printf("Invalid 'deauthenticate' command - exactly one "
+		       "argument, STA address, is required.\n");
+		return -1;
+	}
+	if (argc > 1)
+		os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
+			    argv[0], argv[1]);
+	else
+		os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static char ** hostapd_complete_deauthenticate(const char *str, int pos)
+{
+	int arg = get_cmd_arg_num(str, pos);
+	char **res = NULL;
+
+	switch (arg) {
+	case 1:
+		res = cli_txt_list_array(&stations);
+		break;
+	}
+
+	return res;
+}
+
+
+static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
+					char *argv[])
+{
+	char buf[64];
+	if (argc < 1) {
+		printf("Invalid 'disassociate' command - exactly one "
+		       "argument, STA address, is required.\n");
+		return -1;
+	}
+	if (argc > 1)
+		os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
+			    argv[0], argv[1]);
+	else
+		os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static char ** hostapd_complete_disassociate(const char *str, int pos)
+{
+	int arg = get_cmd_arg_num(str, pos);
+	char **res = NULL;
+
+	switch (arg) {
+	case 1:
+		res = cli_txt_list_array(&stations);
+		break;
+	}
+
+	return res;
+}
+
+
+#ifdef CONFIG_TAXONOMY
+static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
+				     char *argv[])
+{
+	char buf[64];
+
+	if (argc != 1) {
+		printf("Invalid 'signature' command - exactly one argument, STA address, is required.\n");
+		return -1;
+	}
+	os_snprintf(buf, sizeof(buf), "SIGNATURE %s", argv[0]);
+	return wpa_ctrl_command(ctrl, buf);
+}
+#endif /* CONFIG_TAXONOMY */
+
+
+#ifdef CONFIG_IEEE80211W
+static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
+				    char *argv[])
+{
+	char buf[64];
+	if (argc != 1) {
+		printf("Invalid 'sa_query' command - exactly one argument, "
+		       "STA address, is required.\n");
+		return -1;
+	}
+	snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
+	return wpa_ctrl_command(ctrl, buf);
+}
+#endif /* CONFIG_IEEE80211W */
+
+
+#ifdef CONFIG_WPS
+static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	char buf[256];
+	if (argc < 2) {
+		printf("Invalid 'wps_pin' command - at least two arguments, "
+		       "UUID and PIN, are required.\n");
+		return -1;
+	}
+	if (argc > 3)
+		snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
+			 argv[0], argv[1], argv[2], argv[3]);
+	else if (argc > 2)
+		snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
+			 argv[0], argv[1], argv[2]);
+	else
+		snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
+					 char *argv[])
+{
+	char cmd[256];
+	int res;
+
+	if (argc != 1 && argc != 2) {
+		printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
+		       "- PIN to be verified\n");
+		return -1;
+	}
+
+	if (argc == 2)
+		res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
+				  argv[0], argv[1]);
+	else
+		res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
+				  argv[0]);
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long WPS_CHECK_PIN command.\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "WPS_PBC");
+}
+
+
+static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "WPS_CANCEL");
+}
+
+
+#ifdef CONFIG_WPS_NFC
+static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
+					    char *argv[])
+{
+	int ret;
+	char *buf;
+	size_t buflen;
+
+	if (argc != 1) {
+		printf("Invalid 'wps_nfc_tag_read' command - one argument "
+		       "is required.\n");
+		return -1;
+	}
+
+	buflen = 18 + os_strlen(argv[0]);
+	buf = os_malloc(buflen);
+	if (buf == NULL)
+		return -1;
+	os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
+
+	ret = wpa_ctrl_command(ctrl, buf);
+	os_free(buf);
+
+	return ret;
+}
+
+
+static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
+						int argc, char *argv[])
+{
+	char cmd[64];
+	int res;
+
+	if (argc != 1) {
+		printf("Invalid 'wps_nfc_config_token' command - one argument "
+		       "is required.\n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
+			  argv[0]);
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
+					 int argc, char *argv[])
+{
+	char cmd[64];
+	int res;
+
+	if (argc != 1) {
+		printf("Invalid 'wps_nfc_token' command - one argument is "
+		       "required.\n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long WPS_NFC_TOKEN command.\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
+						int argc, char *argv[])
+{
+	char cmd[64];
+	int res;
+
+	if (argc != 2) {
+		printf("Invalid 'nfc_get_handover_sel' command - two arguments "
+		       "are required.\n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
+			  argv[0], argv[1]);
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long NFC_GET_HANDOVER_SEL command.\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+#endif /* CONFIG_WPS_NFC */
+
+
+static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	char buf[64];
+	if (argc < 1) {
+		printf("Invalid 'wps_ap_pin' command - at least one argument "
+		       "is required.\n");
+		return -1;
+	}
+	if (argc > 2)
+		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
+			 argv[0], argv[1], argv[2]);
+	else if (argc > 1)
+		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
+			 argv[0], argv[1]);
+	else
+		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
+					  char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
+}
+
+
+static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	char buf[256];
+	char ssid_hex[2 * SSID_MAX_LEN + 1];
+	char key_hex[2 * 64 + 1];
+	int i;
+
+	if (argc < 1) {
+		printf("Invalid 'wps_config' command - at least two arguments "
+		       "are required.\n");
+		return -1;
+	}
+
+	ssid_hex[0] = '\0';
+	for (i = 0; i < SSID_MAX_LEN; i++) {
+		if (argv[0][i] == '\0')
+			break;
+		os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
+	}
+
+	key_hex[0] = '\0';
+	if (argc > 3) {
+		for (i = 0; i < 64; i++) {
+			if (argv[3][i] == '\0')
+				break;
+			os_snprintf(&key_hex[i * 2], 3, "%02x",
+				    argv[3][i]);
+		}
+	}
+
+	if (argc > 3)
+		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
+			 ssid_hex, argv[1], argv[2], key_hex);
+	else if (argc > 2)
+		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
+			 ssid_hex, argv[1], argv[2]);
+	else
+		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
+			 ssid_hex, argv[1]);
+	return wpa_ctrl_command(ctrl, buf);
+}
+#endif /* CONFIG_WPS */
+
+
+static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
+					     char *argv[])
+{
+	char buf[300];
+	int res;
+
+	if (argc < 2) {
+		printf("Invalid 'disassoc_imminent' command - two arguments "
+		       "(STA addr and Disassociation Timer) are needed\n");
+		return -1;
+	}
+
+	res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
+			  argv[0], argv[1]);
+	if (os_snprintf_error(sizeof(buf), res))
+		return -1;
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
+					char *argv[])
+{
+	char buf[300];
+	int res;
+
+	if (argc < 3) {
+		printf("Invalid 'ess_disassoc' command - three arguments (STA "
+		       "addr, disassoc timer, and URL) are needed\n");
+		return -1;
+	}
+
+	res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
+			  argv[0], argv[1], argv[2]);
+	if (os_snprintf_error(sizeof(buf), res))
+		return -1;
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	char buf[2000], *tmp;
+	int res, i, total;
+
+	if (argc < 1) {
+		printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
+		return -1;
+	}
+
+	res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
+	if (os_snprintf_error(sizeof(buf), res))
+		return -1;
+
+	total = res;
+	for (i = 1; i < argc; i++) {
+		tmp = &buf[total];
+		res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
+		if (os_snprintf_error(sizeof(buf) - total, res))
+			return -1;
+		total += res;
+	}
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "GET_CONFIG");
+}
+
+
+static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
+				char *addr, size_t addr_len)
+{
+	char buf[4096], *pos;
+	size_t len;
+	int ret;
+
+	if (ctrl_conn == NULL) {
+		printf("Not connected to hostapd - command dropped.\n");
+		return -1;
+	}
+	len = sizeof(buf) - 1;
+	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
+			       hostapd_cli_msg_cb);
+	if (ret == -2) {
+		printf("'%s' command timed out.\n", cmd);
+		return -2;
+	} else if (ret < 0) {
+		printf("'%s' command failed.\n", cmd);
+		return -1;
+	}
+
+	buf[len] = '\0';
+	if (memcmp(buf, "FAIL", 4) == 0)
+		return -1;
+	printf("%s", buf);
+
+	pos = buf;
+	while (*pos != '\0' && *pos != '\n')
+		pos++;
+	*pos = '\0';
+	os_strlcpy(addr, buf, addr_len);
+	return 0;
+}
+
+
+static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	char addr[32], cmd[64];
+
+	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
+		return 0;
+	do {
+		snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
+	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
+
+	return -1;
+}
+
+
+static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	print_help(stdout, argc > 0 ? argv[0] : NULL);
+	return 0;
+}
+
+
+static char ** hostapd_cli_complete_help(const char *str, int pos)
+{
+	int arg = get_cmd_arg_num(str, pos);
+	char **res = NULL;
+
+	switch (arg) {
+	case 1:
+		res = list_cmd_list();
+		break;
+	}
+
+	return res;
+}
+
+
+static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	printf("%s\n\n%s\n", hostapd_cli_version, cli_full_license);
+	return 0;
+}
+
+
+static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
+					   int argc, char *argv[])
+{
+	char buf[200];
+	int res;
+
+	if (argc != 1) {
+		printf("Invalid 'set_qos_map_set' command - "
+		       "one argument (comma delimited QoS map set) "
+		       "is needed\n");
+		return -1;
+	}
+
+	res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
+	if (os_snprintf_error(sizeof(buf), res))
+		return -1;
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
+					     int argc, char *argv[])
+{
+	char buf[50];
+	int res;
+
+	if (argc != 1) {
+		printf("Invalid 'send_qos_map_conf' command - "
+		       "one argument (STA addr) is needed\n");
+		return -1;
+	}
+
+	res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
+	if (os_snprintf_error(sizeof(buf), res))
+		return -1;
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
+					  char *argv[])
+{
+	char buf[300];
+	int res;
+
+	if (argc < 2) {
+		printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
+		       "addr and URL) are needed\n");
+		return -1;
+	}
+
+	res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
+			  argv[0], argv[1]);
+	if (os_snprintf_error(sizeof(buf), res))
+		return -1;
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
+					   char *argv[])
+{
+	char buf[300];
+	int res;
+
+	if (argc < 3) {
+		printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
+		return -1;
+	}
+
+	if (argc > 3)
+		res = os_snprintf(buf, sizeof(buf),
+				  "HS20_DEAUTH_REQ %s %s %s %s",
+				  argv[0], argv[1], argv[2], argv[3]);
+	else
+		res = os_snprintf(buf, sizeof(buf),
+				  "HS20_DEAUTH_REQ %s %s %s",
+				  argv[0], argv[1], argv[2]);
+	if (os_snprintf_error(sizeof(buf), res))
+		return -1;
+	return wpa_ctrl_command(ctrl, buf);
+}
+
+
+static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	hostapd_cli_quit = 1;
+	if (interactive)
+		eloop_terminate();
+	return 0;
+}
+
+
+static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char cmd[256];
+	if (argc != 1) {
+		printf("Invalid LEVEL command: needs one argument (debug "
+		       "level)\n");
+		return 0;
+	}
+	snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static void hostapd_cli_get_interfaces(struct wpa_ctrl *ctrl,
+				       struct dl_list *interfaces)
+{
+	struct dirent *dent;
+	DIR *dir;
+
+	if (!ctrl || !interfaces)
+		return;
+	dir = opendir(ctrl_iface_dir);
+	if (dir == NULL)
+		return;
+
+	while ((dent = readdir(dir))) {
+		if (strcmp(dent->d_name, ".") == 0 ||
+		    strcmp(dent->d_name, "..") == 0)
+			continue;
+		cli_txt_list_add(interfaces, dent->d_name);
+	}
+	closedir(dir);
+}
+
+
+static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
+{
+	struct dirent *dent;
+	DIR *dir;
+
+	dir = opendir(ctrl_iface_dir);
+	if (dir == NULL) {
+		printf("Control interface directory '%s' could not be "
+		       "openned.\n", ctrl_iface_dir);
+		return;
+	}
+
+	printf("Available interfaces:\n");
+	while ((dent = readdir(dir))) {
+		if (strcmp(dent->d_name, ".") == 0 ||
+		    strcmp(dent->d_name, "..") == 0)
+			continue;
+		printf("%s\n", dent->d_name);
+	}
+	closedir(dir);
+}
+
+
+static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
+				     char *argv[])
+{
+	if (argc < 1) {
+		hostapd_cli_list_interfaces(ctrl);
+		return 0;
+	}
+
+	hostapd_cli_close_connection();
+	os_free(ctrl_ifname);
+	ctrl_ifname = os_strdup(argv[0]);
+	if (ctrl_ifname == NULL)
+		return -1;
+
+	if (hostapd_cli_open_connection(ctrl_ifname)) {
+		printf("Connected to interface '%s.\n", ctrl_ifname);
+		if (wpa_ctrl_attach(ctrl_conn) == 0) {
+			hostapd_cli_attached = 1;
+			register_event_handler(ctrl_conn);
+		} else {
+			printf("Warning: Failed to attach to "
+			       "hostapd.\n");
+		}
+	} else {
+		printf("Could not connect to interface '%s' - re-trying\n",
+			ctrl_ifname);
+	}
+	return 0;
+}
+
+
+static char ** hostapd_complete_interface(const char *str, int pos)
+{
+	int arg = get_cmd_arg_num(str, pos);
+	char **res = NULL;
+	DEFINE_DL_LIST(interfaces);
+
+	switch (arg) {
+	case 1:
+		hostapd_cli_get_interfaces(ctrl_conn, &interfaces);
+		res = cli_txt_list_array(&interfaces);
+		cli_txt_list_flush(&interfaces);
+		break;
+	}
+
+	return res;
+}
+
+
+static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char cmd[256];
+	int res;
+
+	if (argc != 2) {
+		printf("Invalid SET command: needs two arguments (variable "
+		       "name and value)\n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long SET command.\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char cmd[256];
+	int res;
+
+	if (argc != 1) {
+		printf("Invalid GET command: needs one argument (variable "
+		       "name)\n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long GET command.\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+#ifdef CONFIG_FST
+static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char cmd[256];
+	int res;
+	int i;
+	int total;
+
+	if (argc <= 0) {
+		printf("FST command: parameters are required.\n");
+		return -1;
+	}
+
+	total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
+
+	for (i = 0; i < argc; i++) {
+		res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
+				  argv[i]);
+		if (os_snprintf_error(sizeof(cmd) - total, res)) {
+			printf("Too long fst command.\n");
+			return -1;
+		}
+		total += res;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+#endif /* CONFIG_FST */
+
+
+static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
+				       int argc, char *argv[])
+{
+	char cmd[256];
+	int res;
+	int i;
+	char *tmp;
+	int total;
+
+	if (argc < 2) {
+		printf("Invalid chan_switch command: needs at least two "
+		       "arguments (count and freq)\n"
+		       "usage: <cs_count> <freq> [sec_channel_offset=] "
+		       "[center_freq1=] [center_freq2=] [bandwidth=] "
+		       "[blocktx] [ht|vht]\n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
+			  argv[0], argv[1]);
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long CHAN_SWITCH command.\n");
+		return -1;
+	}
+
+	total = res;
+	for (i = 2; i < argc; i++) {
+		tmp = cmd + total;
+		res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
+		if (os_snprintf_error(sizeof(cmd) - total, res)) {
+			printf("Too long CHAN_SWITCH command.\n");
+			return -1;
+		}
+		total += res;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "ENABLE");
+}
+
+
+static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "RELOAD");
+}
+
+
+static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
+				      char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "DISABLE");
+}
+
+
+static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char cmd[256];
+	int res;
+
+	if (argc < 2 || argc > 3) {
+		printf("Invalid vendor command\n"
+		       "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
+			  argc == 3 ? argv[2] : "");
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long VENDOR command.\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
+				     char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "ERP_FLUSH");
+}
+
+
+static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
+				     char *argv[])
+{
+	char cmd[256];
+	int res;
+
+	res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
+			  argc >= 1 ? " " : "",
+			  argc >= 1 ? argv[0] : "",
+			  argc == 2 ? " " : "",
+			  argc == 2 ? argv[1] : "");
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long option\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	if (argc == 0)
+		return -1;
+	return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
+}
+
+
+static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "PMKSA");
+}
+
+
+static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
+				       char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
+}
+
+
+static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
+					char *argv[])
+{
+	char cmd[2048];
+	int res;
+
+	if (argc < 3 || argc > 5) {
+		printf("Invalid set_neighbor command: needs 3-5 arguments\n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
+			  argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
+			  argc == 5 ? argv[4] : "");
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long SET_NEIGHBOR command.\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
+					   char *argv[])
+{
+	char cmd[400];
+	int res;
+
+	if (argc != 2) {
+		printf("Invalid remove_neighbor command: needs 2 arguments\n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
+			  argv[0], argv[1]);
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long REMOVE_NEIGHBOR command.\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	char cmd[256];
+	int res;
+
+	if (argc != 1) {
+		printf("Invalid req_lci command - requires destination address\n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
+	if (os_snprintf_error(sizeof(cmd), res)) {
+		printf("Too long REQ_LCI command.\n");
+		return -1;
+	}
+	return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
+				     char *argv[])
+{
+	if (argc < 4) {
+		printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
+		return -1;
+	}
+
+	return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
+}
+
+
+static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
+					char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
+}
+
+
+struct hostapd_cli_cmd {
+	const char *cmd;
+	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
+	char ** (*completion)(const char *str, int pos);
+	const char *usage;
+};
+
+static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+	{ "ping", hostapd_cli_cmd_ping, NULL,
+	  "= pings hostapd" },
+	{ "mib", hostapd_cli_cmd_mib, NULL,
+	  "= get MIB variables (dot1x, dot11, radius)" },
+	{ "relog", hostapd_cli_cmd_relog, NULL, NULL },
+	{ "status", hostapd_cli_cmd_status, NULL, NULL },
+	{ "sta", hostapd_cli_cmd_sta, NULL,
+	  "<addr> = get MIB variables for one station" },
+	{ "all_sta", hostapd_cli_cmd_all_sta, NULL,
+	   "= get MIB variables for all stations" },
+	{ "new_sta", hostapd_cli_cmd_new_sta, NULL,
+	  "<addr> = add a new station" },
+	{ "deauthenticate", hostapd_cli_cmd_deauthenticate,
+	  hostapd_complete_deauthenticate,
+	  "<addr> = deauthenticate a station" },
+	{ "disassociate", hostapd_cli_cmd_disassociate,
+	  hostapd_complete_disassociate,
+	  "<addr> = disassociate a station" },
+#ifdef CONFIG_TAXONOMY
+	{ "signature", hostapd_cli_cmd_signature, NULL,
+	  "<addr> = get taxonomy signature for a station" },
+#endif /* CONFIG_TAXONOMY */
+#ifdef CONFIG_IEEE80211W
+	{ "sa_query", hostapd_cli_cmd_sa_query, NULL,
+	  "<addr> = send SA Query to a station" },
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_WPS
+	{ "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
+	  "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
+	{ "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
+	  "<PIN> = verify PIN checksum" },
+	{ "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
+	  "= indicate button pushed to initiate PBC" },
+	{ "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
+	  "= cancel the pending WPS operation" },
+#ifdef CONFIG_WPS_NFC
+	{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
+	  "<hexdump> = report read NFC tag with WPS data" },
+	{ "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
+	  "<WPS/NDEF> = build NFC configuration token" },
+	{ "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
+	  "<WPS/NDEF/enable/disable> = manager NFC password token" },
+	{ "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
+	  NULL },
+#endif /* CONFIG_WPS_NFC */
+	{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
+	  "<cmd> [params..] = enable/disable AP PIN" },
+	{ "wps_config", hostapd_cli_cmd_wps_config, NULL,
+	  "<SSID> <auth> <encr> <key> = configure AP" },
+	{ "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
+	  "= show current WPS status" },
+#endif /* CONFIG_WPS */
+	{ "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, NULL },
+	{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, NULL },
+	{ "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, NULL },
+	{ "get_config", hostapd_cli_cmd_get_config, NULL,
+	  "= show current configuration" },
+	{ "help", hostapd_cli_cmd_help, hostapd_cli_complete_help,
+	  "= show this usage help" },
+	{ "interface", hostapd_cli_cmd_interface, hostapd_complete_interface,
+	  "[ifname] = show interfaces/select interface" },
+#ifdef CONFIG_FST
+	{ "fst", hostapd_cli_cmd_fst, NULL, NULL },
+#endif /* CONFIG_FST */
+	{ "raw", hostapd_cli_cmd_raw, NULL, NULL },
+	{ "level", hostapd_cli_cmd_level, NULL,
+	  "<debug level> = change debug level" },
+	{ "license", hostapd_cli_cmd_license, NULL,
+	  "= show full hostapd_cli license" },
+	{ "quit", hostapd_cli_cmd_quit, NULL,
+	  "= exit hostapd_cli" },
+	{ "set", hostapd_cli_cmd_set, NULL, NULL },
+	{ "get", hostapd_cli_cmd_get, NULL, NULL },
+	{ "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, NULL },
+	{ "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, NULL, NULL },
+	{ "chan_switch", hostapd_cli_cmd_chan_switch, NULL, NULL },
+	{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, NULL },
+	{ "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, NULL },
+	{ "vendor", hostapd_cli_cmd_vendor, NULL, NULL },
+	{ "enable", hostapd_cli_cmd_enable, NULL, NULL },
+	{ "reload", hostapd_cli_cmd_reload, NULL, NULL },
+	{ "disable", hostapd_cli_cmd_disable, NULL, NULL },
+	{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL, NULL },
+	{ "log_level", hostapd_cli_cmd_log_level, NULL, NULL },
+	{ "pmksa", hostapd_cli_cmd_pmksa, NULL, NULL },
+	{ "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, NULL },
+	{ "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, NULL },
+	{ "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, NULL },
+	{ "req_lci", hostapd_cli_cmd_req_lci, NULL, NULL },
+	{ "req_range", hostapd_cli_cmd_req_range, NULL, NULL },
+	{ "driver_flags", hostapd_cli_cmd_driver_flags, NULL, NULL },
+	{ NULL, NULL, NULL, NULL }
+};
+
+
+/*
+ * Prints command usage, lines are padded with the specified string.
+ */
+static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd,
+			   const char *pad)
+{
+	char c;
+	size_t n;
+
+	if (cmd->usage == NULL)
+		return;
+	fprintf(stream, "%s%s ", pad, cmd->cmd);
+	for (n = 0; (c = cmd->usage[n]); n++) {
+		fprintf(stream, "%c", c);
+		if (c == '\n')
+			fprintf(stream, "%s", pad);
+	}
+	fprintf(stream, "\n");
+}
+
+
+static void print_help(FILE *stream, const char *cmd)
+{
+	int n;
+
+	fprintf(stream, "commands:\n");
+	for (n = 0; hostapd_cli_commands[n].cmd; n++) {
+		if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd))
+			print_cmd_help(stream, &hostapd_cli_commands[n], "  ");
+	}
+}
+
+
+static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	const struct hostapd_cli_cmd *cmd, *match = NULL;
+	int count;
+
+	count = 0;
+	cmd = hostapd_cli_commands;
+	while (cmd->cmd) {
+		if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
+			match = cmd;
+			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
+				/* we have an exact match */
+				count = 1;
+				break;
+			}
+			count++;
+		}
+		cmd++;
+	}
+
+	if (count > 1) {
+		printf("Ambiguous command '%s'; possible commands:", argv[0]);
+		cmd = hostapd_cli_commands;
+		while (cmd->cmd) {
+			if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
+			    0) {
+				printf(" %s", cmd->cmd);
+			}
+			cmd++;
+		}
+		printf("\n");
+	} else if (count == 0) {
+		printf("Unknown command '%s'\n", argv[0]);
+	} else {
+		match->handler(ctrl, argc - 1, &argv[1]);
+	}
+}
+
+
+static void cli_event(const char *str)
+{
+	const char *start, *s;
+
+	start = os_strchr(str, '>');
+	if (start == NULL)
+		return;
+
+	start++;
+
+	if (str_starts(start, AP_STA_CONNECTED)) {
+		s = os_strchr(start, ' ');
+		if (s == NULL)
+			return;
+		cli_txt_list_add(&stations, s + 1);
+		return;
+	}
+
+	if (str_starts(start, AP_STA_DISCONNECTED)) {
+		s = os_strchr(start, ' ');
+		if (s == NULL)
+			return;
+		cli_txt_list_del_addr(&stations, s + 1);
+		return;
+	}
+}
+
+
+static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
+				     int action_monitor)
+{
+	int first = 1;
+	if (ctrl_conn == NULL)
+		return;
+	while (wpa_ctrl_pending(ctrl)) {
+		char buf[256];
+		size_t len = sizeof(buf) - 1;
+		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
+			buf[len] = '\0';
+			if (action_monitor)
+				hostapd_cli_action_process(buf, len);
+			else {
+				cli_event(buf);
+				if (in_read && first)
+					printf("\n");
+				first = 0;
+				printf("%s\n", buf);
+			}
+		} else {
+			printf("Could not read pending message.\n");
+			break;
+		}
+	}
+}
+
+
+static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	hostapd_cli_recv_pending(ctrl_conn, 0, 0);
+}
+
+
+static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
+{
+	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
+		printf("Connection to hostapd lost - trying to reconnect\n");
+		hostapd_cli_close_connection();
+	}
+	if (!ctrl_conn) {
+		ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
+		if (ctrl_conn) {
+			printf("Connection to hostapd re-established\n");
+			if (wpa_ctrl_attach(ctrl_conn) == 0) {
+				hostapd_cli_attached = 1;
+				register_event_handler(ctrl_conn);
+			} else {
+				printf("Warning: Failed to attach to "
+				       "hostapd.\n");
+			}
+		}
+	}
+	if (ctrl_conn)
+		hostapd_cli_recv_pending(ctrl_conn, 1, 0);
+	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
+}
+
+
+static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
+{
+	eloop_terminate();
+}
+
+
+static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
+{
+	char *argv[max_args];
+	int argc;
+	argc = tokenize_cmd(cmd, argv);
+	if (argc)
+		wpa_request(ctrl_conn, argc, argv);
+}
+
+
+static void hostapd_cli_edit_eof_cb(void *ctx)
+{
+	eloop_terminate();
+}
+
+
+static char ** list_cmd_list(void)
+{
+	char **res;
+	int i, count;
+
+	count = ARRAY_SIZE(hostapd_cli_commands);
+	res = os_calloc(count + 1, sizeof(char *));
+	if (res == NULL)
+		return NULL;
+
+	for (i = 0; hostapd_cli_commands[i].cmd; i++) {
+		res[i] = os_strdup(hostapd_cli_commands[i].cmd);
+		if (res[i] == NULL)
+			break;
+	}
+
+	return res;
+}
+
+
+static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
+				      int pos)
+{
+	int i;
+
+	for (i = 0; hostapd_cli_commands[i].cmd; i++) {
+		if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
+			continue;
+		if (hostapd_cli_commands[i].completion)
+			return hostapd_cli_commands[i].completion(str, pos);
+		if (!hostapd_cli_commands[i].usage)
+			return NULL;
+		edit_clear_line();
+		printf("\r%s\n", hostapd_cli_commands[i].usage);
+		edit_redraw();
+		break;
+	}
+
+	return NULL;
+}
+
+
+static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
+					      int pos)
+{
+	char **res;
+	const char *end;
+	char *cmd;
+
+	end = os_strchr(str, ' ');
+	if (end == NULL || str + pos < end)
+		return list_cmd_list();
+
+	cmd = os_malloc(pos + 1);
+	if (cmd == NULL)
+		return NULL;
+	os_memcpy(cmd, str, pos);
+	cmd[end - str] = '\0';
+	res = hostapd_cli_cmd_completion(cmd, str, pos);
+	os_free(cmd);
+	return res;
+}
+
+
+static void hostapd_cli_interactive(void)
+{
+	printf("\nInteractive mode\n\n");
+
+	eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
+	edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
+		  hostapd_cli_edit_completion_cb, NULL, NULL, NULL);
+	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
+
+	eloop_run();
+
+	cli_txt_list_flush(&stations);
+	edit_deinit(NULL, NULL);
+	eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
+}
+
+
+static void hostapd_cli_cleanup(void)
+{
+	hostapd_cli_close_connection();
+	if (pid_file)
+		os_daemonize_terminate(pid_file);
+
+	os_program_deinit();
+}
+
+
+static void hostapd_cli_action(struct wpa_ctrl *ctrl)
+{
+	fd_set rfds;
+	int fd, res;
+	struct timeval tv;
+	char buf[256];
+	size_t len;
+
+	fd = wpa_ctrl_get_fd(ctrl);
+
+	while (!hostapd_cli_quit) {
+		FD_ZERO(&rfds);
+		FD_SET(fd, &rfds);
+		tv.tv_sec = ping_interval;
+		tv.tv_usec = 0;
+		res = select(fd + 1, &rfds, NULL, NULL, &tv);
+		if (res < 0 && errno != EINTR) {
+			perror("select");
+			break;
+		}
+
+		if (FD_ISSET(fd, &rfds))
+			hostapd_cli_recv_pending(ctrl, 0, 1);
+		else {
+			len = sizeof(buf) - 1;
+			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
+					     hostapd_cli_action_process) < 0 ||
+			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
+				printf("hostapd did not reply to PING "
+				       "command - exiting\n");
+				break;
+			}
+		}
+	}
+}
+
+
+int main(int argc, char *argv[])
+{
+	int warning_displayed = 0;
+	int c;
+	int daemonize = 0;
+
+	if (os_program_init())
+		return -1;
+
+	for (;;) {
+		c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
+		if (c < 0)
+			break;
+		switch (c) {
+		case 'a':
+			action_file = optarg;
+			break;
+		case 'B':
+			daemonize = 1;
+			break;
+		case 'G':
+			ping_interval = atoi(optarg);
+			break;
+		case 'h':
+			usage();
+			return 0;
+		case 'v':
+			printf("%s\n", hostapd_cli_version);
+			return 0;
+		case 'i':
+			os_free(ctrl_ifname);
+			ctrl_ifname = os_strdup(optarg);
+			break;
+		case 'p':
+			ctrl_iface_dir = optarg;
+			break;
+		case 'P':
+			pid_file = optarg;
+			break;
+		case 's':
+			client_socket_dir = optarg;
+			break;
+		default:
+			usage();
+			return -1;
+		}
+	}
+
+	interactive = (argc == optind) && (action_file == NULL);
+
+	if (interactive) {
+		printf("%s\n\n%s\n\n", hostapd_cli_version, cli_license);
+	}
+
+	if (eloop_init())
+		return -1;
+
+	for (;;) {
+		if (ctrl_ifname == NULL) {
+			struct dirent *dent;
+			DIR *dir = opendir(ctrl_iface_dir);
+			if (dir) {
+				while ((dent = readdir(dir))) {
+					if (os_strcmp(dent->d_name, ".") == 0
+					    ||
+					    os_strcmp(dent->d_name, "..") == 0)
+						continue;
+					printf("Selected interface '%s'\n",
+					       dent->d_name);
+					ctrl_ifname = os_strdup(dent->d_name);
+					break;
+				}
+				closedir(dir);
+			}
+		}
+		ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
+		if (ctrl_conn) {
+			if (warning_displayed)
+				printf("Connection established.\n");
+			break;
+		}
+
+		if (!interactive) {
+			perror("Failed to connect to hostapd - "
+			       "wpa_ctrl_open");
+			return -1;
+		}
+
+		if (!warning_displayed) {
+			printf("Could not connect to hostapd - re-trying\n");
+			warning_displayed = 1;
+		}
+		os_sleep(1, 0);
+		continue;
+	}
+
+	if (interactive || action_file) {
+		if (wpa_ctrl_attach(ctrl_conn) == 0) {
+			hostapd_cli_attached = 1;
+			register_event_handler(ctrl_conn);
+		} else {
+			printf("Warning: Failed to attach to hostapd.\n");
+			if (action_file)
+				return -1;
+		}
+	}
+
+	if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
+		return -1;
+
+	if (interactive)
+		hostapd_cli_interactive();
+	else if (action_file)
+		hostapd_cli_action(ctrl_conn);
+	else
+		wpa_request(ctrl_conn, argc - optind, &argv[optind]);
+
+	unregister_event_handler(ctrl_conn);
+	os_free(ctrl_ifname);
+	eloop_destroy();
+	hostapd_cli_cleanup();
+	return 0;
+}
+
+#else /* CONFIG_NO_CTRL_IFACE */
+
+int main(int argc, char *argv[])
+{
+	return -1;
+}
+
+#endif /* CONFIG_NO_CTRL_IFACE */

+ 14 - 0
EVSE/GPL/hostapd-2.6/hostapd/hostapd_cli.d

@@ -0,0 +1,14 @@
+hostapd_cli.o: hostapd_cli.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_ctrl.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/eloop.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/edit.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/version.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/cli.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h

+ 9 - 0
EVSE/GPL/hostapd-2.6/hostapd/logwatch/README

@@ -0,0 +1,9 @@
+Logwatch is a utility for analyzing system logs and provide a human
+readable summary. This directory has a configuration file and a log
+analyzer script for parsing hostapd system log entries for logwatch.
+These files can be installed by copying them to following locations:
+
+/etc/log.d/conf/services/hostapd.conf
+/etc/log.d/scripts/services/hostapd
+
+More information about logwatch is available from http://www.logwatch.org/

+ 65 - 0
EVSE/GPL/hostapd-2.6/hostapd/logwatch/hostapd

@@ -0,0 +1,65 @@
+#!/usr/bin/perl -w
+#
+# Logwatch script for hostapd
+#
+# Copyright 2005 Henrik Brix Andersen <brix@gentoo.org>
+# Distributed under the terms of the GNU General Public License v2
+# Alternatively, this file may be distributed under the terms of the BSD License
+
+use strict;
+
+my $debug = $ENV{'LOGWATCH_DEBUG'} || 0;
+my $detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
+my $debugcounter = 1;
+
+my %hostapd;
+my @unmatched;
+
+if ($debug >= 5) {
+	print STDERR "\n\nDEBUG: Inside HOSTAPD Filter\n\n";
+}
+
+while (defined(my $line = <STDIN>)) {
+	if ($debug >= 5) {
+		print STDERR "DEBUG($debugcounter): $line";
+		$debugcounter++;
+	}
+    chomp($line);
+
+	if (my ($iface,$mac,$layer,$details) = ($line =~ /(.*?): STA (.*?) (.*?): (.*?)$/i)) {
+		unless ($detail == 10) {
+			# collapse association events
+			$details =~ s/^(associated) .*$/$1/i;
+		}
+		$hostapd{$iface}->{$mac}->{$layer}->{$details}++;
+	} else {
+		push @unmatched, "$line\n";
+	}
+}
+
+if (keys %hostapd) {
+	foreach my $iface (sort keys %hostapd) {
+		print "Interface $iface:\n";
+		foreach my $mac (sort keys %{$hostapd{$iface}}) {
+			print "  Client MAC Address $mac:\n";
+			foreach my $layer (sort keys %{$hostapd{$iface}->{$mac}}) {
+				print "    $layer:\n";
+				foreach my $details (sort keys %{$hostapd{$iface}->{$mac}->{$layer}}) {
+					print "      $details";
+					my $count = $hostapd{$iface}->{$mac}->{$layer}->{$details};
+					if ($count > 1) {
+						print ": " . $count . " Times";
+					}
+					print "\n";
+				}
+			}
+		}
+	}
+}
+
+if ($#unmatched >= 0) {
+    print "\n**Unmatched Entries**\n";
+    print @unmatched;
+}
+
+exit(0);

+ 10 - 0
EVSE/GPL/hostapd-2.6/hostapd/logwatch/hostapd.conf

@@ -0,0 +1,10 @@
+# Logwatch configuration for hostapd
+#
+# Copyright 2005 Henrik Brix Andersen <brix@gentoo.org>
+# Distributed under the terms of the GNU General Public License v2
+# Alternatively, this file may be distributed under the terms of the BSD License
+
+Title = "hostapd"
+LogFile = messages
+*OnlyService = hostapd
+*RemoveHeaders

+ 900 - 0
EVSE/GPL/hostapd-2.6/hostapd/main.c

@@ -0,0 +1,900 @@
+/*
+ * hostapd / main()
+ * Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#ifndef CONFIG_NATIVE_WINDOWS
+#include <syslog.h>
+#include <grp.h>
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/uuid.h"
+#include "crypto/random.h"
+#include "crypto/tls.h"
+#include "common/version.h"
+#include "drivers/driver.h"
+#include "eap_server/eap.h"
+#include "eap_server/tncs.h"
+#include "ap/hostapd.h"
+#include "ap/ap_config.h"
+#include "ap/ap_drv_ops.h"
+#include "fst/fst.h"
+#include "config_file.h"
+#include "eap_register.h"
+#include "ctrl_iface.h"
+
+
+struct hapd_global {
+	void **drv_priv;
+	size_t drv_count;
+};
+
+static struct hapd_global global;
+
+
+#ifndef CONFIG_NO_HOSTAPD_LOGGER
+static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
+			      int level, const char *txt, size_t len)
+{
+	struct hostapd_data *hapd = ctx;
+	char *format, *module_str;
+	int maxlen;
+	int conf_syslog_level, conf_stdout_level;
+	unsigned int conf_syslog, conf_stdout;
+
+	maxlen = len + 100;
+	format = os_malloc(maxlen);
+	if (!format)
+		return;
+
+	if (hapd && hapd->conf) {
+		conf_syslog_level = hapd->conf->logger_syslog_level;
+		conf_stdout_level = hapd->conf->logger_stdout_level;
+		conf_syslog = hapd->conf->logger_syslog;
+		conf_stdout = hapd->conf->logger_stdout;
+	} else {
+		conf_syslog_level = conf_stdout_level = 0;
+		conf_syslog = conf_stdout = (unsigned int) -1;
+	}
+
+	switch (module) {
+	case HOSTAPD_MODULE_IEEE80211:
+		module_str = "IEEE 802.11";
+		break;
+	case HOSTAPD_MODULE_IEEE8021X:
+		module_str = "IEEE 802.1X";
+		break;
+	case HOSTAPD_MODULE_RADIUS:
+		module_str = "RADIUS";
+		break;
+	case HOSTAPD_MODULE_WPA:
+		module_str = "WPA";
+		break;
+	case HOSTAPD_MODULE_DRIVER:
+		module_str = "DRIVER";
+		break;
+	case HOSTAPD_MODULE_IAPP:
+		module_str = "IAPP";
+		break;
+	case HOSTAPD_MODULE_MLME:
+		module_str = "MLME";
+		break;
+	default:
+		module_str = NULL;
+		break;
+	}
+
+	if (hapd && hapd->conf && addr)
+		os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s",
+			    hapd->conf->iface, MAC2STR(addr),
+			    module_str ? " " : "", module_str ? module_str : "",
+			    txt);
+	else if (hapd && hapd->conf)
+		os_snprintf(format, maxlen, "%s:%s%s %s",
+			    hapd->conf->iface, module_str ? " " : "",
+			    module_str ? module_str : "", txt);
+	else if (addr)
+		os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
+			    MAC2STR(addr), module_str ? " " : "",
+			    module_str ? module_str : "", txt);
+	else
+		os_snprintf(format, maxlen, "%s%s%s",
+			    module_str ? module_str : "",
+			    module_str ? ": " : "", txt);
+
+	if ((conf_stdout & module) && level >= conf_stdout_level) {
+		wpa_debug_print_timestamp();
+		wpa_printf(MSG_INFO, "%s", format);
+	}
+
+#ifndef CONFIG_NATIVE_WINDOWS
+	if ((conf_syslog & module) && level >= conf_syslog_level) {
+		int priority;
+		switch (level) {
+		case HOSTAPD_LEVEL_DEBUG_VERBOSE:
+		case HOSTAPD_LEVEL_DEBUG:
+			priority = LOG_DEBUG;
+			break;
+		case HOSTAPD_LEVEL_INFO:
+			priority = LOG_INFO;
+			break;
+		case HOSTAPD_LEVEL_NOTICE:
+			priority = LOG_NOTICE;
+			break;
+		case HOSTAPD_LEVEL_WARNING:
+			priority = LOG_WARNING;
+			break;
+		default:
+			priority = LOG_INFO;
+			break;
+		}
+		syslog(priority, "%s", format);
+	}
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+	os_free(format);
+}
+#endif /* CONFIG_NO_HOSTAPD_LOGGER */
+
+
+/**
+ * hostapd_driver_init - Preparate driver interface
+ */
+static int hostapd_driver_init(struct hostapd_iface *iface)
+{
+	struct wpa_init_params params;
+	size_t i;
+	struct hostapd_data *hapd = iface->bss[0];
+	struct hostapd_bss_config *conf = hapd->conf;
+	u8 *b = conf->bssid;
+	struct wpa_driver_capa capa;
+
+	if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) {
+		wpa_printf(MSG_ERROR, "No hostapd driver wrapper available");
+		return -1;
+	}
+
+	/* Initialize the driver interface */
+	if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5]))
+		b = NULL;
+
+	os_memset(&params, 0, sizeof(params));
+	for (i = 0; wpa_drivers[i]; i++) {
+		if (wpa_drivers[i] != hapd->driver)
+			continue;
+
+		if (global.drv_priv[i] == NULL &&
+		    wpa_drivers[i]->global_init) {
+			global.drv_priv[i] =
+				wpa_drivers[i]->global_init(iface->interfaces);
+			if (global.drv_priv[i] == NULL) {
+				wpa_printf(MSG_ERROR, "Failed to initialize "
+					   "driver '%s'",
+					   wpa_drivers[i]->name);
+				return -1;
+			}
+		}
+
+		params.global_priv = global.drv_priv[i];
+		break;
+	}
+	params.bssid = b;
+	params.ifname = hapd->conf->iface;
+	params.driver_params = hapd->iconf->driver_params;
+	params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
+
+	params.num_bridge = hapd->iface->num_bss;
+	params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *));
+	if (params.bridge == NULL)
+		return -1;
+	for (i = 0; i < hapd->iface->num_bss; i++) {
+		struct hostapd_data *bss = hapd->iface->bss[i];
+		if (bss->conf->bridge[0])
+			params.bridge[i] = bss->conf->bridge;
+	}
+
+	params.own_addr = hapd->own_addr;
+
+	hapd->drv_priv = hapd->driver->hapd_init(hapd, &params);
+	os_free(params.bridge);
+	if (hapd->drv_priv == NULL) {
+		wpa_printf(MSG_ERROR, "%s driver initialization failed.",
+			   hapd->driver->name);
+		hapd->driver = NULL;
+		return -1;
+	}
+
+	if (hapd->driver->get_capa &&
+	    hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
+		struct wowlan_triggers *triggs;
+
+		iface->drv_flags = capa.flags;
+		iface->smps_modes = capa.smps_modes;
+		iface->probe_resp_offloads = capa.probe_resp_offloads;
+		/*
+		 * Use default extended capa values from per-radio information
+		 */
+		iface->extended_capa = capa.extended_capa;
+		iface->extended_capa_mask = capa.extended_capa_mask;
+		iface->extended_capa_len = capa.extended_capa_len;
+		iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs;
+
+		/*
+		 * Override extended capa with per-interface type (AP), if
+		 * available from the driver.
+		 */
+		hostapd_get_ext_capa(iface);
+
+		triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa);
+		if (triggs && hapd->driver->set_wowlan) {
+			if (hapd->driver->set_wowlan(hapd->drv_priv, triggs))
+				wpa_printf(MSG_ERROR, "set_wowlan failed");
+		}
+		os_free(triggs);
+	}
+
+	return 0;
+}
+
+
+/**
+ * hostapd_interface_init - Read configuration file and init BSS data
+ *
+ * This function is used to parse configuration file for a full interface (one
+ * or more BSSes sharing the same radio) and allocate memory for the BSS
+ * interfaces. No actiual driver operations are started.
+ */
+static struct hostapd_iface *
+hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name,
+		       const char *config_fname, int debug)
+{
+	struct hostapd_iface *iface;
+	int k;
+
+	wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
+	iface = hostapd_init(interfaces, config_fname);
+	if (!iface)
+		return NULL;
+
+	if (if_name) {
+		os_strlcpy(iface->conf->bss[0]->iface, if_name,
+			   sizeof(iface->conf->bss[0]->iface));
+	}
+
+	iface->interfaces = interfaces;
+
+	for (k = 0; k < debug; k++) {
+		if (iface->bss[0]->conf->logger_stdout_level > 0)
+			iface->bss[0]->conf->logger_stdout_level--;
+	}
+
+	if (iface->conf->bss[0]->iface[0] == '\0' &&
+	    !hostapd_drv_none(iface->bss[0])) {
+		wpa_printf(MSG_ERROR,
+			   "Interface name not specified in %s, nor by '-i' parameter",
+			   config_fname);
+		hostapd_interface_deinit_free(iface);
+		return NULL;
+	}
+
+	return iface;
+}
+
+
+/**
+ * handle_term - SIGINT and SIGTERM handler to terminate hostapd process
+ */
+static void handle_term(int sig, void *signal_ctx)
+{
+	wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig);
+	eloop_terminate();
+}
+
+
+#ifndef CONFIG_NATIVE_WINDOWS
+
+static int handle_reload_iface(struct hostapd_iface *iface, void *ctx)
+{
+	if (hostapd_reload_config(iface) < 0) {
+		wpa_printf(MSG_WARNING, "Failed to read new configuration "
+			   "file - continuing with old.");
+	}
+	return 0;
+}
+
+
+/**
+ * handle_reload - SIGHUP handler to reload configuration
+ */
+static void handle_reload(int sig, void *signal_ctx)
+{
+	struct hapd_interfaces *interfaces = signal_ctx;
+	wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration",
+		   sig);
+	hostapd_for_each_interface(interfaces, handle_reload_iface, NULL);
+}
+
+
+static void handle_dump_state(int sig, void *signal_ctx)
+{
+	/* Not used anymore - ignore signal */
+}
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+
+static int hostapd_global_init(struct hapd_interfaces *interfaces,
+			       const char *entropy_file)
+{
+	int i;
+
+	os_memset(&global, 0, sizeof(global));
+
+	hostapd_logger_register_cb(hostapd_logger_cb);
+
+	if (eap_server_register_methods()) {
+		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
+		return -1;
+	}
+
+	if (eloop_init()) {
+		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
+		return -1;
+	}
+	interfaces->eloop_initialized = 1;
+
+	random_init(entropy_file);
+
+#ifndef CONFIG_NATIVE_WINDOWS
+	eloop_register_signal(SIGHUP, handle_reload, interfaces);
+	eloop_register_signal(SIGUSR1, handle_dump_state, interfaces);
+#endif /* CONFIG_NATIVE_WINDOWS */
+	eloop_register_signal_terminate(handle_term, interfaces);
+
+#ifndef CONFIG_NATIVE_WINDOWS
+	openlog("hostapd", 0, LOG_DAEMON);
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+	for (i = 0; wpa_drivers[i]; i++)
+		global.drv_count++;
+	if (global.drv_count == 0) {
+		wpa_printf(MSG_ERROR, "No drivers enabled");
+		return -1;
+	}
+	global.drv_priv = os_calloc(global.drv_count, sizeof(void *));
+	if (global.drv_priv == NULL)
+		return -1;
+
+	return 0;
+}
+
+
+static void hostapd_global_deinit(const char *pid_file, int eloop_initialized)
+{
+	int i;
+
+	for (i = 0; wpa_drivers[i] && global.drv_priv; i++) {
+		if (!global.drv_priv[i])
+			continue;
+		wpa_drivers[i]->global_deinit(global.drv_priv[i]);
+	}
+	os_free(global.drv_priv);
+	global.drv_priv = NULL;
+
+#ifdef EAP_SERVER_TNC
+	tncs_global_deinit();
+#endif /* EAP_SERVER_TNC */
+
+	random_deinit();
+
+	if (eloop_initialized)
+		eloop_destroy();
+
+#ifndef CONFIG_NATIVE_WINDOWS
+	closelog();
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+	eap_server_unregister_methods();
+
+	os_daemonize_terminate(pid_file);
+}
+
+
+static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
+			      const char *pid_file)
+{
+#ifdef EAP_SERVER_TNC
+	int tnc = 0;
+	size_t i, k;
+
+	for (i = 0; !tnc && i < ifaces->count; i++) {
+		for (k = 0; k < ifaces->iface[i]->num_bss; k++) {
+			if (ifaces->iface[i]->bss[0]->conf->tnc) {
+				tnc++;
+				break;
+			}
+		}
+	}
+
+	if (tnc && tncs_global_init() < 0) {
+		wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
+		return -1;
+	}
+#endif /* EAP_SERVER_TNC */
+
+	if (daemonize) {
+		if (os_daemonize(pid_file)) {
+			wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno));
+			return -1;
+		}
+		if (eloop_sock_requeue()) {
+			wpa_printf(MSG_ERROR, "eloop_sock_requeue: %s",
+				   strerror(errno));
+			return -1;
+		}
+	}
+
+	eloop_run();
+
+	return 0;
+}
+
+
+static void show_version(void)
+{
+	fprintf(stderr,
+		"hostapd v" VERSION_STR "\n"
+		"User space daemon for IEEE 802.11 AP management,\n"
+		"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
+		"Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> "
+		"and contributors\n");
+}
+
+
+static void usage(void)
+{
+	show_version();
+	fprintf(stderr,
+		"\n"
+		"usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
+		"\\\n"
+		"         [-g <global ctrl_iface>] [-G <group>]\\\n"
+		"         [-i <comma-separated list of interface names>]\\\n"
+		"         <configuration file(s)>\n"
+		"\n"
+		"options:\n"
+		"   -h   show this usage\n"
+		"   -d   show more debug messages (-dd for even more)\n"
+		"   -B   run daemon in the background\n"
+		"   -e   entropy file\n"
+		"   -g   global control interface path\n"
+		"   -G   group for control interfaces\n"
+		"   -P   PID file\n"
+		"   -K   include key data in debug messages\n"
+#ifdef CONFIG_DEBUG_FILE
+		"   -f   log output to debug file instead of stdout\n"
+#endif /* CONFIG_DEBUG_FILE */
+#ifdef CONFIG_DEBUG_LINUX_TRACING
+		"   -T = record to Linux tracing in addition to logging\n"
+		"        (records all messages regardless of debug verbosity)\n"
+#endif /* CONFIG_DEBUG_LINUX_TRACING */
+		"   -i   list of interface names to use\n"
+		"   -S   start all the interfaces synchronously\n"
+		"   -t   include timestamps in some debug messages\n"
+		"   -v   show hostapd version\n");
+
+	exit(1);
+}
+
+
+static const char * hostapd_msg_ifname_cb(void *ctx)
+{
+	struct hostapd_data *hapd = ctx;
+	if (hapd && hapd->conf)
+		return hapd->conf->iface;
+	return NULL;
+}
+
+
+static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
+					 const char *path)
+{
+#ifndef CONFIG_CTRL_IFACE_UDP
+	char *pos;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
+
+	os_free(interfaces->global_iface_path);
+	interfaces->global_iface_path = os_strdup(path);
+	if (interfaces->global_iface_path == NULL)
+		return -1;
+
+#ifndef CONFIG_CTRL_IFACE_UDP
+	pos = os_strrchr(interfaces->global_iface_path, '/');
+	if (pos == NULL) {
+		wpa_printf(MSG_ERROR, "No '/' in the global control interface "
+			   "file");
+		os_free(interfaces->global_iface_path);
+		interfaces->global_iface_path = NULL;
+		return -1;
+	}
+
+	*pos = '\0';
+	interfaces->global_iface_name = pos + 1;
+#endif /* !CONFIG_CTRL_IFACE_UDP */
+
+	return 0;
+}
+
+
+static int hostapd_get_ctrl_iface_group(struct hapd_interfaces *interfaces,
+					const char *group)
+{
+#ifndef CONFIG_NATIVE_WINDOWS
+	struct group *grp;
+	grp = getgrnam(group);
+	if (grp == NULL) {
+		wpa_printf(MSG_ERROR, "Unknown group '%s'", group);
+		return -1;
+	}
+	interfaces->ctrl_iface_group = grp->gr_gid;
+#endif /* CONFIG_NATIVE_WINDOWS */
+	return 0;
+}
+
+
+static int hostapd_get_interface_names(char ***if_names,
+				       size_t *if_names_size,
+				       char *optarg)
+{
+	char *if_name, *tmp, **nnames;
+	size_t i;
+
+	if (!optarg)
+		return -1;
+	if_name = strtok_r(optarg, ",", &tmp);
+
+	while (if_name) {
+		nnames = os_realloc_array(*if_names, 1 + *if_names_size,
+					  sizeof(char *));
+		if (!nnames)
+			goto fail;
+		*if_names = nnames;
+
+		(*if_names)[*if_names_size] = os_strdup(if_name);
+		if (!(*if_names)[*if_names_size])
+			goto fail;
+		(*if_names_size)++;
+		if_name = strtok_r(NULL, ",", &tmp);
+	}
+
+	return 0;
+
+fail:
+	for (i = 0; i < *if_names_size; i++)
+		os_free((*if_names)[i]);
+	os_free(*if_names);
+	*if_names = NULL;
+	*if_names_size = 0;
+	return -1;
+}
+
+
+#ifdef CONFIG_WPS
+static int gen_uuid(const char *txt_addr)
+{
+	u8 addr[ETH_ALEN];
+	u8 uuid[UUID_LEN];
+	char buf[100];
+
+	if (hwaddr_aton(txt_addr, addr) < 0)
+		return -1;
+
+	uuid_gen_mac_addr(addr, uuid);
+	if (uuid_bin2str(uuid, buf, sizeof(buf)) < 0)
+		return -1;
+
+	printf("%s\n", buf);
+
+	return 0;
+}
+#endif /* CONFIG_WPS */
+
+
+#ifndef HOSTAPD_CLEANUP_INTERVAL
+#define HOSTAPD_CLEANUP_INTERVAL 10
+#endif /* HOSTAPD_CLEANUP_INTERVAL */
+
+static int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx)
+{
+	hostapd_periodic_iface(iface);
+	return 0;
+}
+
+
+/* Periodic cleanup tasks */
+static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
+{
+	struct hapd_interfaces *interfaces = eloop_ctx;
+
+	eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
+			       hostapd_periodic, interfaces, NULL);
+	hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL);
+}
+
+
+int main(int argc, char *argv[])
+{
+	struct hapd_interfaces interfaces;
+	int ret = 1;
+	size_t i, j;
+	int c, debug = 0, daemonize = 0;
+	char *pid_file = NULL;
+	const char *log_file = NULL;
+	const char *entropy_file = NULL;
+	char **bss_config = NULL, **tmp_bss;
+	size_t num_bss_configs = 0;
+#ifdef CONFIG_DEBUG_LINUX_TRACING
+	int enable_trace_dbg = 0;
+#endif /* CONFIG_DEBUG_LINUX_TRACING */
+	int start_ifaces_in_sync = 0;
+	char **if_names = NULL;
+	size_t if_names_size = 0;
+
+	if (os_program_init())
+		return -1;
+
+	os_memset(&interfaces, 0, sizeof(interfaces));
+	interfaces.reload_config = hostapd_reload_config;
+	interfaces.config_read_cb = hostapd_config_read;
+	interfaces.for_each_interface = hostapd_for_each_interface;
+	interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
+	interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
+	interfaces.driver_init = hostapd_driver_init;
+	interfaces.global_iface_path = NULL;
+	interfaces.global_iface_name = NULL;
+	interfaces.global_ctrl_sock = -1;
+	dl_list_init(&interfaces.global_ctrl_dst);
+
+	for (;;) {
+		c = getopt(argc, argv, "b:Bde:f:hi:KP:STtu:vg:G:");
+		if (c < 0)
+			break;
+		switch (c) {
+		case 'h':
+			usage();
+			break;
+		case 'd':
+			debug++;
+			if (wpa_debug_level > 0)
+				wpa_debug_level--;
+			break;
+		case 'B':
+			daemonize++;
+			break;
+		case 'e':
+			entropy_file = optarg;
+			break;
+		case 'f':
+			log_file = optarg;
+			break;
+		case 'K':
+			wpa_debug_show_keys++;
+			break;
+		case 'P':
+			os_free(pid_file);
+			pid_file = os_rel2abs_path(optarg);
+			break;
+		case 't':
+			wpa_debug_timestamp++;
+			break;
+#ifdef CONFIG_DEBUG_LINUX_TRACING
+		case 'T':
+			enable_trace_dbg = 1;
+			break;
+#endif /* CONFIG_DEBUG_LINUX_TRACING */
+		case 'v':
+			show_version();
+			exit(1);
+			break;
+		case 'g':
+			if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
+				return -1;
+			break;
+		case 'G':
+			if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
+				return -1;
+			break;
+		case 'b':
+			tmp_bss = os_realloc_array(bss_config,
+						   num_bss_configs + 1,
+						   sizeof(char *));
+			if (tmp_bss == NULL)
+				goto out;
+			bss_config = tmp_bss;
+			bss_config[num_bss_configs++] = optarg;
+			break;
+		case 'S':
+			start_ifaces_in_sync = 1;
+			break;
+#ifdef CONFIG_WPS
+		case 'u':
+			return gen_uuid(optarg);
+#endif /* CONFIG_WPS */
+		case 'i':
+			if (hostapd_get_interface_names(&if_names,
+							&if_names_size, optarg))
+				goto out;
+			break;
+		default:
+			usage();
+			break;
+		}
+	}
+
+	if (optind == argc && interfaces.global_iface_path == NULL &&
+	    num_bss_configs == 0)
+		usage();
+
+	wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
+
+	if (log_file)
+		wpa_debug_open_file(log_file);
+	else
+		wpa_debug_setup_stdout();
+#ifdef CONFIG_DEBUG_LINUX_TRACING
+	if (enable_trace_dbg) {
+		int tret = wpa_debug_open_linux_tracing();
+		if (tret) {
+			wpa_printf(MSG_ERROR, "Failed to enable trace logging");
+			return -1;
+		}
+	}
+#endif /* CONFIG_DEBUG_LINUX_TRACING */
+
+	interfaces.count = argc - optind;
+	if (interfaces.count || num_bss_configs) {
+		interfaces.iface = os_calloc(interfaces.count + num_bss_configs,
+					     sizeof(struct hostapd_iface *));
+		if (interfaces.iface == NULL) {
+			wpa_printf(MSG_ERROR, "malloc failed");
+			return -1;
+		}
+	}
+
+	if (hostapd_global_init(&interfaces, entropy_file)) {
+		wpa_printf(MSG_ERROR, "Failed to initialize global context");
+		return -1;
+	}
+
+	eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
+			       hostapd_periodic, &interfaces, NULL);
+
+	if (fst_global_init()) {
+		wpa_printf(MSG_ERROR,
+			   "Failed to initialize global FST context");
+		goto out;
+	}
+
+#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
+	if (!fst_global_add_ctrl(fst_ctrl_cli))
+		wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
+#endif /* CONFIG_FST && CONFIG_CTRL_IFACE */
+
+	/* Allocate and parse configuration for full interface files */
+	for (i = 0; i < interfaces.count; i++) {
+		char *if_name = NULL;
+
+		if (i < if_names_size)
+			if_name = if_names[i];
+
+		interfaces.iface[i] = hostapd_interface_init(&interfaces,
+							     if_name,
+							     argv[optind + i],
+							     debug);
+		if (!interfaces.iface[i]) {
+			wpa_printf(MSG_ERROR, "Failed to initialize interface");
+			goto out;
+		}
+		if (start_ifaces_in_sync)
+			interfaces.iface[i]->need_to_start_in_sync = 1;
+	}
+
+	/* Allocate and parse configuration for per-BSS files */
+	for (i = 0; i < num_bss_configs; i++) {
+		struct hostapd_iface *iface;
+		char *fname;
+
+		wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]);
+		fname = os_strchr(bss_config[i], ':');
+		if (fname == NULL) {
+			wpa_printf(MSG_ERROR,
+				   "Invalid BSS config identifier '%s'",
+				   bss_config[i]);
+			goto out;
+		}
+		*fname++ = '\0';
+		iface = hostapd_interface_init_bss(&interfaces, bss_config[i],
+						   fname, debug);
+		if (iface == NULL)
+			goto out;
+		for (j = 0; j < interfaces.count; j++) {
+			if (interfaces.iface[j] == iface)
+				break;
+		}
+		if (j == interfaces.count) {
+			struct hostapd_iface **tmp;
+			tmp = os_realloc_array(interfaces.iface,
+					       interfaces.count + 1,
+					       sizeof(struct hostapd_iface *));
+			if (tmp == NULL) {
+				hostapd_interface_deinit_free(iface);
+				goto out;
+			}
+			interfaces.iface = tmp;
+			interfaces.iface[interfaces.count++] = iface;
+		}
+	}
+
+	/*
+	 * Enable configured interfaces. Depending on channel configuration,
+	 * this may complete full initialization before returning or use a
+	 * callback mechanism to complete setup in case of operations like HT
+	 * co-ex scans, ACS, or DFS are needed to determine channel parameters.
+	 * In such case, the interface will be enabled from eloop context within
+	 * hostapd_global_run().
+	 */
+	interfaces.terminate_on_error = interfaces.count;
+	for (i = 0; i < interfaces.count; i++) {
+		if (hostapd_driver_init(interfaces.iface[i]) ||
+		    hostapd_setup_interface(interfaces.iface[i]))
+			goto out;
+	}
+
+	hostapd_global_ctrl_iface_init(&interfaces);
+
+	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
+		wpa_printf(MSG_ERROR, "Failed to start eloop");
+		goto out;
+	}
+
+	ret = 0;
+
+ out:
+	hostapd_global_ctrl_iface_deinit(&interfaces);
+	/* Deinitialize all interfaces */
+	for (i = 0; i < interfaces.count; i++) {
+		if (!interfaces.iface[i])
+			continue;
+		interfaces.iface[i]->driver_ap_teardown =
+			!!(interfaces.iface[i]->drv_flags &
+			   WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
+		hostapd_interface_deinit_free(interfaces.iface[i]);
+	}
+	os_free(interfaces.iface);
+
+	if (interfaces.eloop_initialized)
+		eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
+	hostapd_global_deinit(pid_file, interfaces.eloop_initialized);
+	os_free(pid_file);
+
+	if (log_file)
+		wpa_debug_close_file();
+	wpa_debug_close_linux_tracing();
+
+	os_free(bss_config);
+
+	for (i = 0; i < if_names_size; i++)
+		os_free(if_names[i]);
+	os_free(if_names);
+
+	fst_global_deinit();
+
+	os_program_deinit();
+
+	return ret;
+}

+ 34 - 0
EVSE/GPL/hostapd-2.6/hostapd/main.d

@@ -0,0 +1,34 @@
+main.o: main.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/eloop.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/uuid.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/crypto/random.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/crypto/tls.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/version.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_common/eap_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap_methods.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/tncs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/hostapd.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/vlan.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/ap/ap_drv_ops.h \
+ config_file.h eap_register.h ctrl_iface.h

+ 47 - 0
EVSE/GPL/hostapd-2.6/hostapd/nt_password_hash.c

@@ -0,0 +1,47 @@
+/*
+ * hostapd - Plaintext password to NtPasswordHash
+ * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto/ms_funcs.h"
+
+
+int main(int argc, char *argv[])
+{
+	unsigned char password_hash[16];
+	size_t i;
+	char *password, buf[64], *pos;
+
+	if (argc > 1)
+		password = argv[1];
+	else {
+		if (fgets(buf, sizeof(buf), stdin) == NULL) {
+			printf("Failed to read password\n");
+			return 1;
+		}
+		buf[sizeof(buf) - 1] = '\0';
+		pos = buf;
+		while (*pos != '\0') {
+			if (*pos == '\r' || *pos == '\n') {
+				*pos = '\0';
+				break;
+			}
+			pos++;
+		}
+		password = buf;
+	}
+
+	if (nt_password_hash((u8 *) password, strlen(password), password_hash))
+		return -1;
+	for (i = 0; i < sizeof(password_hash); i++)
+		printf("%02x", password_hash[i]);
+	printf("\n");
+
+	return 0;
+}

+ 40 - 0
EVSE/GPL/hostapd-2.6/hostapd/wired.conf

@@ -0,0 +1,40 @@
+##### hostapd configuration file ##############################################
+# Empty lines and lines starting with # are ignored
+
+# Example configuration file for wired authenticator. See hostapd.conf for
+# more details.
+
+interface=eth0
+driver=wired
+logger_stdout=-1
+logger_stdout_level=1
+debug=2
+dump_file=/tmp/hostapd.dump
+
+ieee8021x=1
+eap_reauth_period=3600
+
+use_pae_group_addr=1
+
+
+##### RADIUS configuration ####################################################
+# for IEEE 802.1X with external Authentication Server, IEEE 802.11
+# authentication with external ACL for MAC addresses, and accounting
+
+# The own IP address of the access point (used as NAS-IP-Address)
+own_ip_addr=127.0.0.1
+
+# Optional NAS-Identifier string for RADIUS messages. When used, this should be
+# a unique to the NAS within the scope of the RADIUS server. For example, a
+# fully qualified domain name can be used here.
+nas_identifier=ap.example.com
+
+# RADIUS authentication server
+auth_server_addr=127.0.0.1
+auth_server_port=1812
+auth_server_shared_secret=radius
+
+# RADIUS accounting server
+acct_server_addr=127.0.0.1
+acct_server_port=1813
+acct_server_shared_secret=radius

+ 342 - 0
EVSE/GPL/hostapd-2.6/hostapd/wps-ap-nfc.py

@@ -0,0 +1,342 @@
+#!/usr/bin/python
+#
+# Example nfcpy to hostapd wrapper for WPS NFC operations
+# Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
+#
+# This software may be distributed under the terms of the BSD license.
+# See README for more details.
+
+import os
+import sys
+import time
+import argparse
+
+import nfc
+import nfc.ndef
+import nfc.llcp
+import nfc.handover
+
+import logging
+
+import wpaspy
+
+wpas_ctrl = '/var/run/hostapd'
+continue_loop = True
+summary_file = None
+success_file = None
+
+def summary(txt):
+    print txt
+    if summary_file:
+        with open(summary_file, 'a') as f:
+            f.write(txt + "\n")
+
+def success_report(txt):
+    summary(txt)
+    if success_file:
+        with open(success_file, 'a') as f:
+            f.write(txt + "\n")
+
+def wpas_connect():
+    ifaces = []
+    if os.path.isdir(wpas_ctrl):
+        try:
+            ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
+        except OSError, error:
+            print "Could not find hostapd: ", error
+            return None
+
+    if len(ifaces) < 1:
+        print "No hostapd control interface found"
+        return None
+
+    for ctrl in ifaces:
+        try:
+            wpas = wpaspy.Ctrl(ctrl)
+            return wpas
+        except Exception, e:
+            pass
+    return None
+
+
+def wpas_tag_read(message):
+    wpas = wpas_connect()
+    if (wpas == None):
+        return False
+    if "FAIL" in wpas.request("WPS_NFC_TAG_READ " + str(message).encode("hex")):
+        return False
+    return True
+
+
+def wpas_get_config_token():
+    wpas = wpas_connect()
+    if (wpas == None):
+        return None
+    ret = wpas.request("WPS_NFC_CONFIG_TOKEN NDEF")
+    if "FAIL" in ret:
+        return None
+    return ret.rstrip().decode("hex")
+
+
+def wpas_get_password_token():
+    wpas = wpas_connect()
+    if (wpas == None):
+        return None
+    ret = wpas.request("WPS_NFC_TOKEN NDEF")
+    if "FAIL" in ret:
+        return None
+    return ret.rstrip().decode("hex")
+
+
+def wpas_get_handover_sel():
+    wpas = wpas_connect()
+    if (wpas == None):
+        return None
+    ret = wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR")
+    if "FAIL" in ret:
+        return None
+    return ret.rstrip().decode("hex")
+
+
+def wpas_report_handover(req, sel):
+    wpas = wpas_connect()
+    if (wpas == None):
+        return None
+    return wpas.request("NFC_REPORT_HANDOVER RESP WPS " +
+                        str(req).encode("hex") + " " +
+                        str(sel).encode("hex"))
+
+
+class HandoverServer(nfc.handover.HandoverServer):
+    def __init__(self, llc):
+        super(HandoverServer, self).__init__(llc)
+        self.ho_server_processing = False
+        self.success = False
+
+    # override to avoid parser error in request/response.pretty() in nfcpy
+    # due to new WSC handover format
+    def _process_request(self, request):
+        summary("received handover request {}".format(request.type))
+        response = nfc.ndef.Message("\xd1\x02\x01Hs\x12")
+        if not request.type == 'urn:nfc:wkt:Hr':
+            summary("not a handover request")
+        else:
+            try:
+                request = nfc.ndef.HandoverRequestMessage(request)
+            except nfc.ndef.DecodeError as e:
+                summary("error decoding 'Hr' message: {}".format(e))
+            else:
+                response = self.process_request(request)
+        summary("send handover response {}".format(response.type))
+        return response
+
+    def process_request(self, request):
+        summary("HandoverServer - request received")
+        try:
+            print "Parsed handover request: " + request.pretty()
+        except Exception, e:
+            print e
+        print str(request).encode("hex")
+
+        sel = nfc.ndef.HandoverSelectMessage(version="1.2")
+
+        for carrier in request.carriers:
+            print "Remote carrier type: " + carrier.type
+            if carrier.type == "application/vnd.wfa.wsc":
+                summary("WPS carrier type match - add WPS carrier record")
+                data = wpas_get_handover_sel()
+                if data is None:
+                    summary("Could not get handover select carrier record from hostapd")
+                    continue
+                print "Handover select carrier record from hostapd:"
+                print data.encode("hex")
+                if "OK" in wpas_report_handover(carrier.record, data):
+                    success_report("Handover reported successfully")
+                else:
+                    summary("Handover report rejected")
+
+                message = nfc.ndef.Message(data);
+                sel.add_carrier(message[0], "active", message[1:])
+
+        print "Handover select:"
+        try:
+            print sel.pretty()
+        except Exception, e:
+            print e
+        print str(sel).encode("hex")
+
+        summary("Sending handover select")
+        self.success = True
+        return sel
+
+
+def wps_tag_read(tag):
+    success = False
+    if len(tag.ndef.message):
+        for record in tag.ndef.message:
+            print "record type " + record.type
+            if record.type == "application/vnd.wfa.wsc":
+                summary("WPS tag - send to hostapd")
+                success = wpas_tag_read(tag.ndef.message)
+                break
+    else:
+        summary("Empty tag")
+
+    if success:
+        success_report("Tag read succeeded")
+
+    return success
+
+
+def rdwr_connected_write(tag):
+    summary("Tag found - writing - " + str(tag))
+    global write_data
+    tag.ndef.message = str(write_data)
+    success_report("Tag write succeeded")
+    print "Done - remove tag"
+    global only_one
+    if only_one:
+        global continue_loop
+        continue_loop = False
+    global write_wait_remove
+    while write_wait_remove and tag.is_present:
+        time.sleep(0.1)
+
+def wps_write_config_tag(clf, wait_remove=True):
+    summary("Write WPS config token")
+    global write_data, write_wait_remove
+    write_wait_remove = wait_remove
+    write_data = wpas_get_config_token()
+    if write_data == None:
+        summary("Could not get WPS config token from hostapd")
+        return
+
+    print "Touch an NFC tag"
+    clf.connect(rdwr={'on-connect': rdwr_connected_write})
+
+
+def wps_write_password_tag(clf, wait_remove=True):
+    summary("Write WPS password token")
+    global write_data, write_wait_remove
+    write_wait_remove = wait_remove
+    write_data = wpas_get_password_token()
+    if write_data == None:
+        summary("Could not get WPS password token from hostapd")
+        return
+
+    print "Touch an NFC tag"
+    clf.connect(rdwr={'on-connect': rdwr_connected_write})
+
+
+def rdwr_connected(tag):
+    global only_one, no_wait
+    summary("Tag connected: " + str(tag))
+
+    if tag.ndef:
+        print "NDEF tag: " + tag.type
+        try:
+            print tag.ndef.message.pretty()
+        except Exception, e:
+            print e
+        success = wps_tag_read(tag)
+        if only_one and success:
+            global continue_loop
+            continue_loop = False
+    else:
+        summary("Not an NDEF tag - remove tag")
+        return True
+
+    return not no_wait
+
+
+def llcp_startup(clf, llc):
+    print "Start LLCP server"
+    global srv
+    srv = HandoverServer(llc)
+    return llc
+
+def llcp_connected(llc):
+    print "P2P LLCP connected"
+    global wait_connection
+    wait_connection = False
+    global srv
+    srv.start()
+    return True
+
+
+def main():
+    clf = nfc.ContactlessFrontend()
+
+    parser = argparse.ArgumentParser(description='nfcpy to hostapd integration for WPS NFC operations')
+    parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO,
+                        action='store_const', dest='loglevel',
+                        help='verbose debug output')
+    parser.add_argument('-q', const=logging.WARNING, action='store_const',
+                        dest='loglevel', help='be quiet')
+    parser.add_argument('--only-one', '-1', action='store_true',
+                        help='run only one operation and exit')
+    parser.add_argument('--no-wait', action='store_true',
+                        help='do not wait for tag to be removed before exiting')
+    parser.add_argument('--summary',
+                        help='summary file for writing status updates')
+    parser.add_argument('--success',
+                        help='success file for writing success update')
+    parser.add_argument('command', choices=['write-config',
+                                            'write-password'],
+                        nargs='?')
+    args = parser.parse_args()
+
+    global only_one
+    only_one = args.only_one
+
+    global no_wait
+    no_wait = args.no_wait
+
+    if args.summary:
+        global summary_file
+        summary_file = args.summary
+
+    if args.success:
+        global success_file
+        success_file = args.success
+
+    logging.basicConfig(level=args.loglevel)
+
+    try:
+        if not clf.open("usb"):
+            print "Could not open connection with an NFC device"
+            raise SystemExit
+
+        if args.command == "write-config":
+            wps_write_config_tag(clf, wait_remove=not args.no_wait)
+            raise SystemExit
+
+        if args.command == "write-password":
+            wps_write_password_tag(clf, wait_remove=not args.no_wait)
+            raise SystemExit
+
+        global continue_loop
+        while continue_loop:
+            print "Waiting for a tag or peer to be touched"
+            wait_connection = True
+            try:
+                if not clf.connect(rdwr={'on-connect': rdwr_connected},
+                                   llcp={'on-startup': llcp_startup,
+                                         'on-connect': llcp_connected}):
+                    break
+            except Exception, e:
+                print "clf.connect failed"
+
+            global srv
+            if only_one and srv and srv.success:
+                raise SystemExit
+
+    except KeyboardInterrupt:
+        raise SystemExit
+    finally:
+        clf.close()
+
+    raise SystemExit
+
+if __name__ == '__main__':
+    main()

BIN
EVSE/GPL/hostapd-2.6/release/usr/local/bin/hostapd


BIN
EVSE/GPL/hostapd-2.6/release/usr/local/bin/hostapd_cli


+ 12 - 0
EVSE/GPL/hostapd-2.6/src/Makefile

@@ -0,0 +1,12 @@
+SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p pae radius rsn_supp tls utils wps
+SUBDIRS += fst
+
+all:
+	for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done
+
+clean:
+	for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done
+	rm -f *~
+
+install:
+	for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done

+ 67 - 0
EVSE/GPL/hostapd-2.6/src/ap/Makefile

@@ -0,0 +1,67 @@
+all: libap.a
+
+clean:
+	rm -f *~ *.o *.d *.gcno *.gcda *.gcov libap.a
+
+install:
+	@echo Nothing to be made.
+
+include ../lib.rules
+
+CFLAGS += -DHOSTAPD
+CFLAGS += -DNEED_AP_MLME
+CFLAGS += -DCONFIG_HS20
+CFLAGS += -DCONFIG_INTERWORKING
+CFLAGS += -DCONFIG_IEEE80211R
+CFLAGS += -DCONFIG_IEEE80211W
+CFLAGS += -DCONFIG_WPS
+CFLAGS += -DCONFIG_PROXYARP
+CFLAGS += -DCONFIG_IAPP
+
+LIB_OBJS= \
+	accounting.o \
+	ap_config.o \
+	ap_drv_ops.o \
+	ap_list.o \
+	ap_mlme.o \
+	authsrv.o \
+	beacon.o \
+	bss_load.o \
+	ctrl_iface_ap.o \
+	dfs.o \
+	dhcp_snoop.o \
+	drv_callbacks.o \
+	eap_user_db.o \
+	gas_serv.o \
+	hostapd.o \
+	hs20.o \
+	hw_features.o \
+	iapp.o \
+	ieee802_11_auth.o \
+	ieee802_11.o \
+	ieee802_11_ht.o \
+	ieee802_11_shared.o \
+	ieee802_11_vht.o \
+	ieee802_1x.o \
+	ndisc_snoop.o \
+	p2p_hostapd.o \
+	peerkey_auth.o \
+	pmksa_cache_auth.o \
+	preauth_auth.o \
+	sta_info.o \
+	tkip_countermeasures.o \
+	utils.o \
+	vlan_init.o \
+	wmm.o \
+	wnm_ap.o \
+	wpa_auth.o \
+	wpa_auth_ft.o \
+	wpa_auth_glue.o \
+	wpa_auth_ie.o \
+	wps_hostapd.o \
+	x_snoop.o
+
+libap.a: $(LIB_OBJS)
+	$(AR) crT $@ $?
+
+-include $(OBJS:%.o=%.d)

+ 544 - 0
EVSE/GPL/hostapd-2.6/src/ap/accounting.c

@@ -0,0 +1,544 @@
+/*
+ * hostapd / RADIUS Accounting
+ * Copyright (c) 2002-2009, 2012-2015, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "eapol_auth/eapol_auth_sm_i.h"
+#include "radius/radius.h"
+#include "radius/radius_client.h"
+#include "hostapd.h"
+#include "ieee802_1x.h"
+#include "ap_config.h"
+#include "sta_info.h"
+#include "ap_drv_ops.h"
+#include "accounting.h"
+
+
+/* Default interval in seconds for polling TX/RX octets from the driver if
+ * STA is not using interim accounting. This detects wrap arounds for
+ * input/output octets and updates Acct-{Input,Output}-Gigawords. */
+#define ACCT_DEFAULT_UPDATE_INTERVAL 300
+
+static void accounting_sta_interim(struct hostapd_data *hapd,
+				   struct sta_info *sta);
+
+
+static struct radius_msg * accounting_msg(struct hostapd_data *hapd,
+					  struct sta_info *sta,
+					  int status_type)
+{
+	struct radius_msg *msg;
+	char buf[128];
+	u8 *val;
+	size_t len;
+	int i;
+	struct wpabuf *b;
+	struct os_time now;
+
+	msg = radius_msg_new(RADIUS_CODE_ACCOUNTING_REQUEST,
+			     radius_client_get_id(hapd->radius));
+	if (msg == NULL) {
+		wpa_printf(MSG_INFO, "Could not create new RADIUS packet");
+		return NULL;
+	}
+
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_STATUS_TYPE,
+				       status_type)) {
+		wpa_printf(MSG_INFO, "Could not add Acct-Status-Type");
+		goto fail;
+	}
+
+	if (sta) {
+		if (!hostapd_config_get_radius_attr(
+			    hapd->conf->radius_acct_req_attr,
+			    RADIUS_ATTR_ACCT_AUTHENTIC) &&
+		    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_AUTHENTIC,
+					       hapd->conf->ieee802_1x ?
+					       RADIUS_ACCT_AUTHENTIC_RADIUS :
+					       RADIUS_ACCT_AUTHENTIC_LOCAL)) {
+			wpa_printf(MSG_INFO, "Could not add Acct-Authentic");
+			goto fail;
+		}
+
+		/* Use 802.1X identity if available */
+		val = ieee802_1x_get_identity(sta->eapol_sm, &len);
+
+		/* Use RADIUS ACL identity if 802.1X provides no identity */
+		if (!val && sta->identity) {
+			val = (u8 *) sta->identity;
+			len = os_strlen(sta->identity);
+		}
+
+		/* Use STA MAC if neither 802.1X nor RADIUS ACL provided
+		 * identity */
+		if (!val) {
+			os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT,
+				    MAC2STR(sta->addr));
+			val = (u8 *) buf;
+			len = os_strlen(buf);
+		}
+
+		if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, val,
+					 len)) {
+			wpa_printf(MSG_INFO, "Could not add User-Name");
+			goto fail;
+		}
+	}
+
+	if (add_common_radius_attr(hapd, hapd->conf->radius_acct_req_attr, sta,
+				   msg) < 0)
+		goto fail;
+
+	if (sta) {
+		for (i = 0; ; i++) {
+			val = ieee802_1x_get_radius_class(sta->eapol_sm, &len,
+							  i);
+			if (val == NULL)
+				break;
+
+			if (!radius_msg_add_attr(msg, RADIUS_ATTR_CLASS,
+						 val, len)) {
+				wpa_printf(MSG_INFO, "Could not add Class");
+				goto fail;
+			}
+		}
+
+		b = ieee802_1x_get_radius_cui(sta->eapol_sm);
+		if (b &&
+		    !radius_msg_add_attr(msg,
+					 RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
+					 wpabuf_head(b), wpabuf_len(b))) {
+			wpa_printf(MSG_ERROR, "Could not add CUI");
+			goto fail;
+		}
+
+		if (!b && sta->radius_cui &&
+		    !radius_msg_add_attr(msg,
+					 RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
+					 (u8 *) sta->radius_cui,
+					 os_strlen(sta->radius_cui))) {
+			wpa_printf(MSG_ERROR, "Could not add CUI from ACL");
+			goto fail;
+		}
+
+		if (sta->ipaddr &&
+		    !radius_msg_add_attr_int32(msg,
+					       RADIUS_ATTR_FRAMED_IP_ADDRESS,
+					       be_to_host32(sta->ipaddr))) {
+			wpa_printf(MSG_ERROR,
+				   "Could not add Framed-IP-Address");
+			goto fail;
+		}
+	}
+
+	os_get_time(&now);
+	if (now.sec > 1000000000 &&
+	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_EVENT_TIMESTAMP,
+				       now.sec)) {
+		wpa_printf(MSG_INFO, "Could not add Event-Timestamp");
+		goto fail;
+	}
+
+	/*
+	 * Add Acct-Delay-Time with zero value for the first transmission. This
+	 * will be updated within radius_client.c when retransmitting the frame.
+	 */
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_DELAY_TIME, 0)) {
+		wpa_printf(MSG_INFO, "Could not add Acct-Delay-Time");
+		goto fail;
+	}
+
+	return msg;
+
+ fail:
+	radius_msg_free(msg);
+	return NULL;
+}
+
+
+static int accounting_sta_update_stats(struct hostapd_data *hapd,
+				       struct sta_info *sta,
+				       struct hostap_sta_driver_data *data)
+{
+	if (hostapd_drv_read_sta_data(hapd, data, sta->addr))
+		return -1;
+
+	if (!data->bytes_64bit) {
+		/* Extend 32-bit counters from the driver to 64-bit counters */
+		if (sta->last_rx_bytes_lo > data->rx_bytes)
+			sta->last_rx_bytes_hi++;
+		sta->last_rx_bytes_lo = data->rx_bytes;
+
+		if (sta->last_tx_bytes_lo > data->tx_bytes)
+			sta->last_tx_bytes_hi++;
+		sta->last_tx_bytes_lo = data->tx_bytes;
+	}
+
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
+		       HOSTAPD_LEVEL_DEBUG,
+		       "updated TX/RX stats: rx_bytes=%llu [%u:%u] tx_bytes=%llu [%u:%u] bytes_64bit=%d",
+		       data->rx_bytes, sta->last_rx_bytes_hi,
+		       sta->last_rx_bytes_lo,
+		       data->tx_bytes, sta->last_tx_bytes_hi,
+		       sta->last_tx_bytes_lo,
+		       data->bytes_64bit);
+
+	return 0;
+}
+
+
+static void accounting_interim_update(void *eloop_ctx, void *timeout_ctx)
+{
+	struct hostapd_data *hapd = eloop_ctx;
+	struct sta_info *sta = timeout_ctx;
+	int interval;
+
+	if (sta->acct_interim_interval) {
+		accounting_sta_interim(hapd, sta);
+		interval = sta->acct_interim_interval;
+	} else {
+		struct hostap_sta_driver_data data;
+		accounting_sta_update_stats(hapd, sta, &data);
+		interval = ACCT_DEFAULT_UPDATE_INTERVAL;
+	}
+
+	eloop_register_timeout(interval, 0, accounting_interim_update,
+			       hapd, sta);
+}
+
+
+/**
+ * accounting_sta_start - Start STA accounting
+ * @hapd: hostapd BSS data
+ * @sta: The station
+ */
+void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	struct radius_msg *msg;
+	int interval;
+
+	if (sta->acct_session_started)
+		return;
+
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
+		       HOSTAPD_LEVEL_INFO,
+		       "starting accounting session %016llX",
+		       (unsigned long long) sta->acct_session_id);
+
+	os_get_reltime(&sta->acct_session_start);
+	sta->last_rx_bytes_hi = 0;
+	sta->last_rx_bytes_lo = 0;
+	sta->last_tx_bytes_hi = 0;
+	sta->last_tx_bytes_lo = 0;
+	hostapd_drv_sta_clear_stats(hapd, sta->addr);
+
+	if (!hapd->conf->radius->acct_server)
+		return;
+
+	if (sta->acct_interim_interval)
+		interval = sta->acct_interim_interval;
+	else
+		interval = ACCT_DEFAULT_UPDATE_INTERVAL;
+	eloop_register_timeout(interval, 0, accounting_interim_update,
+			       hapd, sta);
+
+	msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START);
+	if (msg &&
+	    radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr) < 0)
+		radius_msg_free(msg);
+
+	sta->acct_session_started = 1;
+}
+
+
+static void accounting_sta_report(struct hostapd_data *hapd,
+				  struct sta_info *sta, int stop)
+{
+	struct radius_msg *msg;
+	int cause = sta->acct_terminate_cause;
+	struct hostap_sta_driver_data data;
+	struct os_reltime now_r, diff;
+	u64 bytes;
+
+	if (!hapd->conf->radius->acct_server)
+		return;
+
+	msg = accounting_msg(hapd, sta,
+			     stop ? RADIUS_ACCT_STATUS_TYPE_STOP :
+			     RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE);
+	if (!msg) {
+		wpa_printf(MSG_INFO, "Could not create RADIUS Accounting message");
+		return;
+	}
+
+	os_get_reltime(&now_r);
+	os_reltime_sub(&now_r, &sta->acct_session_start, &diff);
+	if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME,
+				       diff.sec)) {
+		wpa_printf(MSG_INFO, "Could not add Acct-Session-Time");
+		goto fail;
+	}
+
+	if (accounting_sta_update_stats(hapd, sta, &data) == 0) {
+		if (!radius_msg_add_attr_int32(msg,
+					       RADIUS_ATTR_ACCT_INPUT_PACKETS,
+					       data.rx_packets)) {
+			wpa_printf(MSG_INFO, "Could not add Acct-Input-Packets");
+			goto fail;
+		}
+		if (!radius_msg_add_attr_int32(msg,
+					       RADIUS_ATTR_ACCT_OUTPUT_PACKETS,
+					       data.tx_packets)) {
+			wpa_printf(MSG_INFO, "Could not add Acct-Output-Packets");
+			goto fail;
+		}
+		if (data.bytes_64bit)
+			bytes = data.rx_bytes;
+		else
+			bytes = ((u64) sta->last_rx_bytes_hi << 32) |
+				sta->last_rx_bytes_lo;
+		if (!radius_msg_add_attr_int32(msg,
+					       RADIUS_ATTR_ACCT_INPUT_OCTETS,
+					       (u32) bytes)) {
+			wpa_printf(MSG_INFO, "Could not add Acct-Input-Octets");
+			goto fail;
+		}
+		if (!radius_msg_add_attr_int32(msg,
+					       RADIUS_ATTR_ACCT_INPUT_GIGAWORDS,
+					       (u32) (bytes >> 32))) {
+			wpa_printf(MSG_INFO, "Could not add Acct-Input-Gigawords");
+			goto fail;
+		}
+		if (data.bytes_64bit)
+			bytes = data.tx_bytes;
+		else
+			bytes = ((u64) sta->last_tx_bytes_hi << 32) |
+				sta->last_tx_bytes_lo;
+		if (!radius_msg_add_attr_int32(msg,
+					       RADIUS_ATTR_ACCT_OUTPUT_OCTETS,
+					       (u32) bytes)) {
+			wpa_printf(MSG_INFO, "Could not add Acct-Output-Octets");
+			goto fail;
+		}
+		if (!radius_msg_add_attr_int32(msg,
+					       RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS,
+					       (u32) (bytes >> 32))) {
+			wpa_printf(MSG_INFO, "Could not add Acct-Output-Gigawords");
+			goto fail;
+		}
+	}
+
+	if (eloop_terminated())
+		cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT;
+
+	if (stop && cause &&
+	    !radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_TERMINATE_CAUSE,
+				       cause)) {
+		wpa_printf(MSG_INFO, "Could not add Acct-Terminate-Cause");
+		goto fail;
+	}
+
+	if (radius_client_send(hapd->radius, msg,
+			       stop ? RADIUS_ACCT : RADIUS_ACCT_INTERIM,
+			       sta->addr) < 0)
+		goto fail;
+	return;
+
+ fail:
+	radius_msg_free(msg);
+}
+
+
+/**
+ * accounting_sta_interim - Send a interim STA accounting report
+ * @hapd: hostapd BSS data
+ * @sta: The station
+ */
+static void accounting_sta_interim(struct hostapd_data *hapd,
+				   struct sta_info *sta)
+{
+	if (sta->acct_session_started)
+		accounting_sta_report(hapd, sta, 0);
+}
+
+
+/**
+ * accounting_sta_stop - Stop STA accounting
+ * @hapd: hostapd BSS data
+ * @sta: The station
+ */
+void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	if (sta->acct_session_started) {
+		accounting_sta_report(hapd, sta, 1);
+		eloop_cancel_timeout(accounting_interim_update, hapd, sta);
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
+			       HOSTAPD_LEVEL_INFO,
+			       "stopped accounting session %016llX",
+			       (unsigned long long) sta->acct_session_id);
+		sta->acct_session_started = 0;
+	}
+}
+
+
+int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	return radius_gen_session_id((u8 *) &sta->acct_session_id,
+				     sizeof(sta->acct_session_id));
+}
+
+
+/**
+ * accounting_receive - Process the RADIUS frames from Accounting Server
+ * @msg: RADIUS response message
+ * @req: RADIUS request message
+ * @shared_secret: RADIUS shared secret
+ * @shared_secret_len: Length of shared_secret in octets
+ * @data: Context data (struct hostapd_data *)
+ * Returns: Processing status
+ */
+static RadiusRxResult
+accounting_receive(struct radius_msg *msg, struct radius_msg *req,
+		   const u8 *shared_secret, size_t shared_secret_len,
+		   void *data)
+{
+	if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_RESPONSE) {
+		wpa_printf(MSG_INFO, "Unknown RADIUS message code");
+		return RADIUS_RX_UNKNOWN;
+	}
+
+	if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) {
+		wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have correct Authenticator - dropped");
+		return RADIUS_RX_INVALID_AUTHENTICATOR;
+	}
+
+	return RADIUS_RX_PROCESSED;
+}
+
+
+static void accounting_report_state(struct hostapd_data *hapd, int on)
+{
+	struct radius_msg *msg;
+
+	if (!hapd->conf->radius->acct_server || hapd->radius == NULL)
+		return;
+
+	/* Inform RADIUS server that accounting will start/stop so that the
+	 * server can close old accounting sessions. */
+	msg = accounting_msg(hapd, NULL,
+			     on ? RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON :
+			     RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF);
+	if (!msg)
+		return;
+
+	if (hapd->acct_session_id) {
+		char buf[20];
+
+		os_snprintf(buf, sizeof(buf), "%016llX",
+			    (unsigned long long) hapd->acct_session_id);
+		if (!radius_msg_add_attr(msg, RADIUS_ATTR_ACCT_SESSION_ID,
+					 (u8 *) buf, os_strlen(buf)))
+			wpa_printf(MSG_ERROR, "Could not add Acct-Session-Id");
+	}
+
+	if (radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL) < 0)
+		radius_msg_free(msg);
+}
+
+
+static void accounting_interim_error_cb(const u8 *addr, void *ctx)
+{
+	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta;
+	unsigned int i, wait_time;
+	int res;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta)
+		return;
+	sta->acct_interim_errors++;
+	if (sta->acct_interim_errors > 10 /* RADIUS_CLIENT_MAX_RETRIES */) {
+		wpa_printf(MSG_DEBUG,
+			   "Interim RADIUS accounting update failed for " MACSTR
+			   " - too many errors, abandon this interim accounting update",
+			   MAC2STR(addr));
+		sta->acct_interim_errors = 0;
+		/* Next update will be tried after normal update interval */
+		return;
+	}
+
+	/*
+	 * Use a shorter update interval as an improved retransmission mechanism
+	 * for failed interim accounting updates. This allows the statistics to
+	 * be updated for each retransmission.
+	 *
+	 * RADIUS client code has already waited RADIUS_CLIENT_FIRST_WAIT.
+	 * Schedule the first retry attempt immediately and every following one
+	 * with exponential backoff.
+	 */
+	if (sta->acct_interim_errors == 1) {
+		wait_time = 0;
+	} else {
+		wait_time = 3; /* RADIUS_CLIENT_FIRST_WAIT */
+		for (i = 1; i < sta->acct_interim_errors; i++)
+			wait_time *= 2;
+	}
+	res = eloop_deplete_timeout(wait_time, 0, accounting_interim_update,
+				    hapd, sta);
+	if (res == 1)
+		wpa_printf(MSG_DEBUG,
+			   "Interim RADIUS accounting update failed for " MACSTR
+			   " (error count: %u) - schedule next update in %u seconds",
+			   MAC2STR(addr), sta->acct_interim_errors, wait_time);
+	else if (res == 0)
+		wpa_printf(MSG_DEBUG,
+			   "Interim RADIUS accounting update failed for " MACSTR
+			   " (error count: %u)", MAC2STR(addr),
+			   sta->acct_interim_errors);
+	else
+		wpa_printf(MSG_DEBUG,
+			   "Interim RADIUS accounting update failed for " MACSTR
+			   " (error count: %u) - no timer found", MAC2STR(addr),
+			   sta->acct_interim_errors);
+}
+
+
+/**
+ * accounting_init: Initialize accounting
+ * @hapd: hostapd BSS data
+ * Returns: 0 on success, -1 on failure
+ */
+int accounting_init(struct hostapd_data *hapd)
+{
+	if (radius_gen_session_id((u8 *) &hapd->acct_session_id,
+				  sizeof(hapd->acct_session_id)) < 0)
+		return -1;
+
+	if (radius_client_register(hapd->radius, RADIUS_ACCT,
+				   accounting_receive, hapd))
+		return -1;
+	radius_client_set_interim_error_cb(hapd->radius,
+					   accounting_interim_error_cb, hapd);
+
+	accounting_report_state(hapd, 1);
+
+	return 0;
+}
+
+
+/**
+ * accounting_deinit: Deinitialize accounting
+ * @hapd: hostapd BSS data
+ */
+void accounting_deinit(struct hostapd_data *hapd)
+{
+	accounting_report_state(hapd, 0);
+}

+ 29 - 0
EVSE/GPL/hostapd-2.6/src/ap/accounting.d

@@ -0,0 +1,29 @@
+../src/ap/accounting.o: ../src/ap/accounting.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/eloop.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eapol_auth/eapol_auth_sm.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eapol_auth/eapol_auth_sm_i.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius_client.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ ../src/ap/hostapd.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/vlan.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ ../src/ap/ieee802_1x.h ../src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/ap_drv_ops.h ../src/ap/accounting.h

+ 45 - 0
EVSE/GPL/hostapd-2.6/src/ap/accounting.h

@@ -0,0 +1,45 @@
+/*
+ * hostapd / RADIUS Accounting
+ * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef ACCOUNTING_H
+#define ACCOUNTING_H
+
+#ifdef CONFIG_NO_ACCOUNTING
+static inline int accounting_sta_get_id(struct hostapd_data *hapd,
+					struct sta_info *sta)
+{
+	return 0;
+}
+
+static inline void accounting_sta_start(struct hostapd_data *hapd,
+					struct sta_info *sta)
+{
+}
+
+static inline void accounting_sta_stop(struct hostapd_data *hapd,
+				       struct sta_info *sta)
+{
+}
+
+static inline int accounting_init(struct hostapd_data *hapd)
+{
+	return 0;
+}
+
+static inline void accounting_deinit(struct hostapd_data *hapd)
+{
+}
+#else /* CONFIG_NO_ACCOUNTING */
+int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta);
+void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta);
+void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta);
+int accounting_init(struct hostapd_data *hapd);
+void accounting_deinit(struct hostapd_data *hapd);
+#endif /* CONFIG_NO_ACCOUNTING */
+
+#endif /* ACCOUNTING_H */

+ 948 - 0
EVSE/GPL/hostapd-2.6/src/ap/acs.c

@@ -0,0 +1,948 @@
+/*
+ * ACS - Automatic Channel Selection module
+ * Copyright (c) 2011, Atheros Communications
+ * Copyright (c) 2013, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#include <math.h>
+
+#include "utils/common.h"
+#include "utils/list.h"
+#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
+#include "drivers/driver.h"
+#include "hostapd.h"
+#include "ap_drv_ops.h"
+#include "ap_config.h"
+#include "hw_features.h"
+#include "acs.h"
+
+/*
+ * Automatic Channel Selection
+ * ===========================
+ *
+ * More info at
+ * ------------
+ * http://wireless.kernel.org/en/users/Documentation/acs
+ *
+ * How to use
+ * ----------
+ * - make sure you have CONFIG_ACS=y in hostapd's .config
+ * - use channel=0 or channel=acs to enable ACS
+ *
+ * How does it work
+ * ----------------
+ * 1. passive scans are used to collect survey data
+ *    (it is assumed that scan trigger collection of survey data in driver)
+ * 2. interference factor is calculated for each channel
+ * 3. ideal channel is picked depending on channel width by using adjacent
+ *    channel interference factors
+ *
+ * Known limitations
+ * -----------------
+ * - Current implementation depends heavily on the amount of time willing to
+ *   spend gathering survey data during hostapd startup. Short traffic bursts
+ *   may be missed and a suboptimal channel may be picked.
+ * - Ideal channel may end up overlapping a channel with 40 MHz intolerant BSS
+ *
+ * Todo / Ideas
+ * ------------
+ * - implement other interference computation methods
+ *   - BSS/RSSI based
+ *   - spectral scan based
+ *   (should be possibly to hook this up with current ACS scans)
+ * - add wpa_supplicant support (for P2P)
+ * - collect a histogram of interference over time allowing more educated
+ *   guess about an ideal channel (perhaps CSA could be used to migrate AP to a
+ *   new "better" channel while running)
+ * - include neighboring BSS scan to avoid conflicts with 40 MHz intolerant BSSs
+ *   when choosing the ideal channel
+ *
+ * Survey interference factor implementation details
+ * -------------------------------------------------
+ * Generic interference_factor in struct hostapd_channel_data is used.
+ *
+ * The survey interference factor is defined as the ratio of the
+ * observed busy time over the time we spent on the channel,
+ * this value is then amplified by the observed noise floor on
+ * the channel in comparison to the lowest noise floor observed
+ * on the entire band.
+ *
+ * This corresponds to:
+ * ---
+ * (busy time - tx time) / (active time - tx time) * 2^(chan_nf + band_min_nf)
+ * ---
+ *
+ * The coefficient of 2 reflects the way power in "far-field"
+ * radiation decreases as the square of distance from the antenna [1].
+ * What this does is it decreases the observed busy time ratio if the
+ * noise observed was low but increases it if the noise was high,
+ * proportionally to the way "far field" radiation changes over
+ * distance.
+ *
+ * If channel busy time is not available the fallback is to use channel RX time.
+ *
+ * Since noise floor is in dBm it is necessary to convert it into Watts so that
+ * combined channel interference (e.g., HT40, which uses two channels) can be
+ * calculated easily.
+ * ---
+ * (busy time - tx time) / (active time - tx time) *
+ *    2^(10^(chan_nf/10) + 10^(band_min_nf/10))
+ * ---
+ *
+ * However to account for cases where busy/rx time is 0 (channel load is then
+ * 0%) channel noise floor signal power is combined into the equation so a
+ * channel with lower noise floor is preferred. The equation becomes:
+ * ---
+ * 10^(chan_nf/5) + (busy time - tx time) / (active time - tx time) *
+ *    2^(10^(chan_nf/10) + 10^(band_min_nf/10))
+ * ---
+ *
+ * All this "interference factor" is purely subjective and only time
+ * will tell how usable this is. By using the minimum noise floor we
+ * remove any possible issues due to card calibration. The computation
+ * of the interference factor then is dependent on what the card itself
+ * picks up as the minimum noise, not an actual real possible card
+ * noise value.
+ *
+ * Total interference computation details
+ * --------------------------------------
+ * The above channel interference factor is calculated with no respect to
+ * target operational bandwidth.
+ *
+ * To find an ideal channel the above data is combined by taking into account
+ * the target operational bandwidth and selected band. E.g., on 2.4 GHz channels
+ * overlap with 20 MHz bandwidth, but there is no overlap for 20 MHz bandwidth
+ * on 5 GHz.
+ *
+ * Each valid and possible channel spec (i.e., channel + width) is taken and its
+ * interference factor is computed by summing up interferences of each channel
+ * it overlaps. The one with least total interference is picked up.
+ *
+ * Note: This implies base channel interference factor must be non-negative
+ * allowing easy summing up.
+ *
+ * Example ACS analysis printout
+ * -----------------------------
+ *
+ * ACS: Trying survey-based ACS
+ * ACS: Survey analysis for channel 1 (2412 MHz)
+ * ACS:  1: min_nf=-113 interference_factor=0.0802469 nf=-113 time=162 busy=0 rx=13
+ * ACS:  2: min_nf=-113 interference_factor=0.0745342 nf=-113 time=161 busy=0 rx=12
+ * ACS:  3: min_nf=-113 interference_factor=0.0679012 nf=-113 time=162 busy=0 rx=11
+ * ACS:  4: min_nf=-113 interference_factor=0.0310559 nf=-113 time=161 busy=0 rx=5
+ * ACS:  5: min_nf=-113 interference_factor=0.0248447 nf=-113 time=161 busy=0 rx=4
+ * ACS:  * interference factor average: 0.0557166
+ * ACS: Survey analysis for channel 2 (2417 MHz)
+ * ACS:  1: min_nf=-113 interference_factor=0.0185185 nf=-113 time=162 busy=0 rx=3
+ * ACS:  2: min_nf=-113 interference_factor=0.0246914 nf=-113 time=162 busy=0 rx=4
+ * ACS:  3: min_nf=-113 interference_factor=0.037037 nf=-113 time=162 busy=0 rx=6
+ * ACS:  4: min_nf=-113 interference_factor=0.149068 nf=-113 time=161 busy=0 rx=24
+ * ACS:  5: min_nf=-113 interference_factor=0.0248447 nf=-113 time=161 busy=0 rx=4
+ * ACS:  * interference factor average: 0.050832
+ * ACS: Survey analysis for channel 3 (2422 MHz)
+ * ACS:  1: min_nf=-113 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0
+ * ACS:  2: min_nf=-113 interference_factor=0.0185185 nf=-113 time=162 busy=0 rx=3
+ * ACS:  3: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3
+ * ACS:  4: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3
+ * ACS:  5: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3
+ * ACS:  * interference factor average: 0.0148838
+ * ACS: Survey analysis for channel 4 (2427 MHz)
+ * ACS:  1: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
+ * ACS:  2: min_nf=-114 interference_factor=0.0555556 nf=-114 time=162 busy=0 rx=9
+ * ACS:  3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0
+ * ACS:  4: min_nf=-114 interference_factor=0.0186335 nf=-114 time=161 busy=0 rx=3
+ * ACS:  5: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
+ * ACS:  * interference factor average: 0.0160801
+ * ACS: Survey analysis for channel 5 (2432 MHz)
+ * ACS:  1: min_nf=-114 interference_factor=0.409938 nf=-113 time=161 busy=0 rx=66
+ * ACS:  2: min_nf=-114 interference_factor=0.0432099 nf=-113 time=162 busy=0 rx=7
+ * ACS:  3: min_nf=-114 interference_factor=0.0124224 nf=-113 time=161 busy=0 rx=2
+ * ACS:  4: min_nf=-114 interference_factor=0.677019 nf=-113 time=161 busy=0 rx=109
+ * ACS:  5: min_nf=-114 interference_factor=0.0186335 nf=-114 time=161 busy=0 rx=3
+ * ACS:  * interference factor average: 0.232244
+ * ACS: Survey analysis for channel 6 (2437 MHz)
+ * ACS:  1: min_nf=-113 interference_factor=0.552795 nf=-113 time=161 busy=0 rx=89
+ * ACS:  2: min_nf=-113 interference_factor=0.0807453 nf=-112 time=161 busy=0 rx=13
+ * ACS:  3: min_nf=-113 interference_factor=0.0310559 nf=-113 time=161 busy=0 rx=5
+ * ACS:  4: min_nf=-113 interference_factor=0.434783 nf=-112 time=161 busy=0 rx=70
+ * ACS:  5: min_nf=-113 interference_factor=0.0621118 nf=-113 time=161 busy=0 rx=10
+ * ACS:  * interference factor average: 0.232298
+ * ACS: Survey analysis for channel 7 (2442 MHz)
+ * ACS:  1: min_nf=-113 interference_factor=0.440994 nf=-112 time=161 busy=0 rx=71
+ * ACS:  2: min_nf=-113 interference_factor=0.385093 nf=-113 time=161 busy=0 rx=62
+ * ACS:  3: min_nf=-113 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6
+ * ACS:  4: min_nf=-113 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6
+ * ACS:  5: min_nf=-113 interference_factor=0.0745342 nf=-113 time=161 busy=0 rx=12
+ * ACS:  * interference factor average: 0.195031
+ * ACS: Survey analysis for channel 8 (2447 MHz)
+ * ACS:  1: min_nf=-114 interference_factor=0.0496894 nf=-112 time=161 busy=0 rx=8
+ * ACS:  2: min_nf=-114 interference_factor=0.0496894 nf=-114 time=161 busy=0 rx=8
+ * ACS:  3: min_nf=-114 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6
+ * ACS:  4: min_nf=-114 interference_factor=0.12963 nf=-113 time=162 busy=0 rx=21
+ * ACS:  5: min_nf=-114 interference_factor=0.166667 nf=-114 time=162 busy=0 rx=27
+ * ACS:  * interference factor average: 0.0865885
+ * ACS: Survey analysis for channel 9 (2452 MHz)
+ * ACS:  1: min_nf=-114 interference_factor=0.0124224 nf=-114 time=161 busy=0 rx=2
+ * ACS:  2: min_nf=-114 interference_factor=0.0310559 nf=-114 time=161 busy=0 rx=5
+ * ACS:  3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0
+ * ACS:  4: min_nf=-114 interference_factor=0.00617284 nf=-114 time=162 busy=0 rx=1
+ * ACS:  5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
+ * ACS:  * interference factor average: 0.00993022
+ * ACS: Survey analysis for channel 10 (2457 MHz)
+ * ACS:  1: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
+ * ACS:  2: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
+ * ACS:  3: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
+ * ACS:  4: min_nf=-114 interference_factor=0.0493827 nf=-114 time=162 busy=0 rx=8
+ * ACS:  5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
+ * ACS:  * interference factor average: 0.0136033
+ * ACS: Survey analysis for channel 11 (2462 MHz)
+ * ACS:  1: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0
+ * ACS:  2: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=161 busy=0 rx=0
+ * ACS:  3: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=161 busy=0 rx=0
+ * ACS:  4: min_nf=-114 interference_factor=0.0432099 nf=-114 time=162 busy=0 rx=7
+ * ACS:  5: min_nf=-114 interference_factor=0.0925926 nf=-114 time=162 busy=0 rx=15
+ * ACS:  * interference factor average: 0.0271605
+ * ACS: Survey analysis for channel 12 (2467 MHz)
+ * ACS:  1: min_nf=-114 interference_factor=0.0621118 nf=-113 time=161 busy=0 rx=10
+ * ACS:  2: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
+ * ACS:  3: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0
+ * ACS:  4: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0
+ * ACS:  5: min_nf=-114 interference_factor=0.00617284 nf=-113 time=162 busy=0 rx=1
+ * ACS:  * interference factor average: 0.0148992
+ * ACS: Survey analysis for channel 13 (2472 MHz)
+ * ACS:  1: min_nf=-114 interference_factor=0.0745342 nf=-114 time=161 busy=0 rx=12
+ * ACS:  2: min_nf=-114 interference_factor=0.0555556 nf=-114 time=162 busy=0 rx=9
+ * ACS:  3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
+ * ACS:  4: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
+ * ACS:  5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
+ * ACS:  * interference factor average: 0.0260179
+ * ACS: Survey analysis for selected bandwidth 20MHz
+ * ACS:  * channel 1: total interference = 0.121432
+ * ACS:  * channel 2: total interference = 0.137512
+ * ACS:  * channel 3: total interference = 0.369757
+ * ACS:  * channel 4: total interference = 0.546338
+ * ACS:  * channel 5: total interference = 0.690538
+ * ACS:  * channel 6: total interference = 0.762242
+ * ACS:  * channel 7: total interference = 0.756092
+ * ACS:  * channel 8: total interference = 0.537451
+ * ACS:  * channel 9: total interference = 0.332313
+ * ACS:  * channel 10: total interference = 0.152182
+ * ACS:  * channel 11: total interference = 0.0916111
+ * ACS:  * channel 12: total interference = 0.0816809
+ * ACS:  * channel 13: total interference = 0.0680776
+ * ACS: Ideal channel is 13 (2472 MHz) with total interference factor of 0.0680776
+ *
+ * [1] http://en.wikipedia.org/wiki/Near_and_far_field
+ */
+
+
+static int acs_request_scan(struct hostapd_iface *iface);
+static int acs_survey_is_sufficient(struct freq_survey *survey);
+
+
+static void acs_clean_chan_surveys(struct hostapd_channel_data *chan)
+{
+	struct freq_survey *survey, *tmp;
+
+	if (dl_list_empty(&chan->survey_list))
+		return;
+
+	dl_list_for_each_safe(survey, tmp, &chan->survey_list,
+			      struct freq_survey, list) {
+		dl_list_del(&survey->list);
+		os_free(survey);
+	}
+}
+
+
+static void acs_cleanup(struct hostapd_iface *iface)
+{
+	int i;
+	struct hostapd_channel_data *chan;
+
+	for (i = 0; i < iface->current_mode->num_channels; i++) {
+		chan = &iface->current_mode->channels[i];
+
+		if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED)
+			acs_clean_chan_surveys(chan);
+
+		dl_list_init(&chan->survey_list);
+		chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
+		chan->min_nf = 0;
+	}
+
+	iface->chans_surveyed = 0;
+	iface->acs_num_completed_scans = 0;
+}
+
+
+static void acs_fail(struct hostapd_iface *iface)
+{
+	wpa_printf(MSG_ERROR, "ACS: Failed to start");
+	acs_cleanup(iface);
+	hostapd_disable_iface(iface);
+}
+
+
+static long double
+acs_survey_interference_factor(struct freq_survey *survey, s8 min_nf)
+{
+	long double factor, busy, total;
+
+	if (survey->filled & SURVEY_HAS_CHAN_TIME_BUSY)
+		busy = survey->channel_time_busy;
+	else if (survey->filled & SURVEY_HAS_CHAN_TIME_RX)
+		busy = survey->channel_time_rx;
+	else {
+		/* This shouldn't really happen as survey data is checked in
+		 * acs_sanity_check() */
+		wpa_printf(MSG_ERROR, "ACS: Survey data missing");
+		return 0;
+	}
+
+	total = survey->channel_time;
+
+	if (survey->filled & SURVEY_HAS_CHAN_TIME_TX) {
+		busy -= survey->channel_time_tx;
+		total -= survey->channel_time_tx;
+	}
+
+	/* TODO: figure out the best multiplier for noise floor base */
+	factor = pow(10, survey->nf / 5.0L) +
+		(busy / total) *
+		pow(2, pow(10, (long double) survey->nf / 10.0L) -
+		    pow(10, (long double) min_nf / 10.0L));
+
+	return factor;
+}
+
+
+static void
+acs_survey_chan_interference_factor(struct hostapd_iface *iface,
+				    struct hostapd_channel_data *chan)
+{
+	struct freq_survey *survey;
+	unsigned int i = 0;
+	long double int_factor = 0;
+	unsigned count = 0;
+
+	if (dl_list_empty(&chan->survey_list))
+		return;
+
+	if (chan->flag & HOSTAPD_CHAN_DISABLED)
+		return;
+
+	chan->interference_factor = 0;
+
+	dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list)
+	{
+		i++;
+
+		if (!acs_survey_is_sufficient(survey)) {
+			wpa_printf(MSG_DEBUG, "ACS: %d: insufficient data", i);
+			continue;
+		}
+
+		count++;
+		int_factor = acs_survey_interference_factor(survey,
+							    iface->lowest_nf);
+		chan->interference_factor += int_factor;
+		wpa_printf(MSG_DEBUG, "ACS: %d: min_nf=%d interference_factor=%Lg nf=%d time=%lu busy=%lu rx=%lu",
+			   i, chan->min_nf, int_factor,
+			   survey->nf, (unsigned long) survey->channel_time,
+			   (unsigned long) survey->channel_time_busy,
+			   (unsigned long) survey->channel_time_rx);
+	}
+
+	if (!count)
+		return;
+	chan->interference_factor /= count;
+}
+
+
+static int acs_usable_ht40_chan(struct hostapd_channel_data *chan)
+{
+	const int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149,
+				157, 184, 192 };
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(allowed); i++)
+		if (chan->chan == allowed[i])
+			return 1;
+
+	return 0;
+}
+
+
+static int acs_usable_vht80_chan(struct hostapd_channel_data *chan)
+{
+	const int allowed[] = { 36, 52, 100, 116, 132, 149 };
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(allowed); i++)
+		if (chan->chan == allowed[i])
+			return 1;
+
+	return 0;
+}
+
+
+static int acs_survey_is_sufficient(struct freq_survey *survey)
+{
+	if (!(survey->filled & SURVEY_HAS_NF)) {
+		wpa_printf(MSG_INFO, "ACS: Survey is missing noise floor");
+		return 0;
+	}
+
+	if (!(survey->filled & SURVEY_HAS_CHAN_TIME)) {
+		wpa_printf(MSG_INFO, "ACS: Survey is missing channel time");
+		return 0;
+	}
+
+	if (!(survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) &&
+	    !(survey->filled & SURVEY_HAS_CHAN_TIME_RX)) {
+		wpa_printf(MSG_INFO,
+			   "ACS: Survey is missing RX and busy time (at least one is required)");
+		return 0;
+	}
+
+	return 1;
+}
+
+
+static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan)
+{
+	struct freq_survey *survey;
+	int ret = -1;
+
+	dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list)
+	{
+		if (acs_survey_is_sufficient(survey)) {
+			ret = 1;
+			break;
+		}
+		ret = 0;
+	}
+
+	if (ret == -1)
+		ret = 1; /* no survey list entries */
+
+	if (!ret) {
+		wpa_printf(MSG_INFO,
+			   "ACS: Channel %d has insufficient survey data",
+			   chan->chan);
+	}
+
+	return ret;
+}
+
+
+static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
+{
+	int i;
+	struct hostapd_channel_data *chan;
+	int valid = 0;
+
+	for (i = 0; i < iface->current_mode->num_channels; i++) {
+		chan = &iface->current_mode->channels[i];
+		if (chan->flag & HOSTAPD_CHAN_DISABLED)
+			continue;
+
+		if (!acs_survey_list_is_sufficient(chan))
+			continue;
+
+		valid++;
+	}
+
+	/* We need at least survey data for one channel */
+	return !!valid;
+}
+
+
+static int acs_usable_chan(struct hostapd_channel_data *chan)
+{
+	if (dl_list_empty(&chan->survey_list))
+		return 0;
+	if (chan->flag & HOSTAPD_CHAN_DISABLED)
+		return 0;
+	if (!acs_survey_list_is_sufficient(chan))
+		return 0;
+	return 1;
+}
+
+
+static int is_in_chanlist(struct hostapd_iface *iface,
+			  struct hostapd_channel_data *chan)
+{
+	if (!iface->conf->acs_ch_list.num)
+		return 1;
+
+	return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
+}
+
+
+static void acs_survey_all_chans_intereference_factor(
+	struct hostapd_iface *iface)
+{
+	int i;
+	struct hostapd_channel_data *chan;
+
+	for (i = 0; i < iface->current_mode->num_channels; i++) {
+		chan = &iface->current_mode->channels[i];
+
+		if (!acs_usable_chan(chan))
+			continue;
+
+		if (!is_in_chanlist(iface, chan))
+			continue;
+
+		wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
+			   chan->chan, chan->freq);
+
+		acs_survey_chan_interference_factor(iface, chan);
+
+		wpa_printf(MSG_DEBUG, "ACS:  * interference factor average: %Lg",
+			   chan->interference_factor);
+	}
+}
+
+
+static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
+						  int freq)
+{
+	struct hostapd_channel_data *chan;
+	int i;
+
+	for (i = 0; i < iface->current_mode->num_channels; i++) {
+		chan = &iface->current_mode->channels[i];
+
+		if (chan->flag & HOSTAPD_CHAN_DISABLED)
+			continue;
+
+		if (chan->freq == freq)
+			return chan;
+	}
+
+	return NULL;
+}
+
+
+static int is_24ghz_mode(enum hostapd_hw_mode mode)
+{
+	return mode == HOSTAPD_MODE_IEEE80211B ||
+		mode == HOSTAPD_MODE_IEEE80211G;
+}
+
+
+static int is_common_24ghz_chan(int chan)
+{
+	return chan == 1 || chan == 6 || chan == 11;
+}
+
+
+#ifndef ACS_ADJ_WEIGHT
+#define ACS_ADJ_WEIGHT 0.85
+#endif /* ACS_ADJ_WEIGHT */
+
+#ifndef ACS_NEXT_ADJ_WEIGHT
+#define ACS_NEXT_ADJ_WEIGHT 0.55
+#endif /* ACS_NEXT_ADJ_WEIGHT */
+
+#ifndef ACS_24GHZ_PREFER_1_6_11
+/*
+ * Select commonly used channels 1, 6, 11 by default even if a neighboring
+ * channel has a smaller interference factor as long as it is not better by more
+ * than this multiplier.
+ */
+#define ACS_24GHZ_PREFER_1_6_11 0.8
+#endif /* ACS_24GHZ_PREFER_1_6_11 */
+
+/*
+ * At this point it's assumed chan->interface_factor has been computed.
+ * This function should be reusable regardless of interference computation
+ * option (survey, BSS, spectral, ...). chan->interference factor must be
+ * summable (i.e., must be always greater than zero).
+ */
+static struct hostapd_channel_data *
+acs_find_ideal_chan(struct hostapd_iface *iface)
+{
+	struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL,
+		*rand_chan = NULL;
+	long double factor, ideal_factor = 0;
+	int i, j;
+	int n_chans = 1;
+	unsigned int k;
+
+	/* TODO: HT40- support */
+
+	if (iface->conf->ieee80211n &&
+	    iface->conf->secondary_channel == -1) {
+		wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
+		return NULL;
+	}
+
+	if (iface->conf->ieee80211n &&
+	    iface->conf->secondary_channel)
+		n_chans = 2;
+
+	if (iface->conf->ieee80211ac &&
+	    iface->conf->vht_oper_chwidth == 1)
+		n_chans = 4;
+
+	/* TODO: VHT80+80, VHT160. Update acs_adjust_vht_center_freq() too. */
+
+	wpa_printf(MSG_DEBUG, "ACS: Survey analysis for selected bandwidth %d MHz",
+		   n_chans == 1 ? 20 :
+		   n_chans == 2 ? 40 :
+		   80);
+
+	for (i = 0; i < iface->current_mode->num_channels; i++) {
+		double total_weight;
+		struct acs_bias *bias, tmp_bias;
+
+		chan = &iface->current_mode->channels[i];
+
+		if (chan->flag & HOSTAPD_CHAN_DISABLED)
+			continue;
+
+		if (!is_in_chanlist(iface, chan))
+			continue;
+
+		/* HT40 on 5 GHz has a limited set of primary channels as per
+		 * 11n Annex J */
+		if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+		    iface->conf->ieee80211n &&
+		    iface->conf->secondary_channel &&
+		    !acs_usable_ht40_chan(chan)) {
+			wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for HT40",
+				   chan->chan);
+			continue;
+		}
+
+		if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+		    iface->conf->ieee80211ac &&
+		    iface->conf->vht_oper_chwidth == 1 &&
+		    !acs_usable_vht80_chan(chan)) {
+			wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for VHT80",
+				   chan->chan);
+			continue;
+		}
+
+		factor = 0;
+		if (acs_usable_chan(chan))
+			factor = chan->interference_factor;
+		total_weight = 1;
+
+		for (j = 1; j < n_chans; j++) {
+			adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
+			if (!adj_chan)
+				break;
+
+			if (acs_usable_chan(adj_chan)) {
+				factor += adj_chan->interference_factor;
+				total_weight += 1;
+			}
+		}
+
+		if (j != n_chans) {
+			wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
+				   chan->chan);
+			continue;
+		}
+
+		/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
+		 * channel interference factor. */
+		if (is_24ghz_mode(iface->current_mode->mode)) {
+			for (j = 0; j < n_chans; j++) {
+				adj_chan = acs_find_chan(iface, chan->freq +
+							 (j * 20) - 5);
+				if (adj_chan && acs_usable_chan(adj_chan)) {
+					factor += ACS_ADJ_WEIGHT *
+						adj_chan->interference_factor;
+					total_weight += ACS_ADJ_WEIGHT;
+				}
+
+				adj_chan = acs_find_chan(iface, chan->freq +
+							 (j * 20) - 10);
+				if (adj_chan && acs_usable_chan(adj_chan)) {
+					factor += ACS_NEXT_ADJ_WEIGHT *
+						adj_chan->interference_factor;
+					total_weight += ACS_NEXT_ADJ_WEIGHT;
+				}
+
+				adj_chan = acs_find_chan(iface, chan->freq +
+							 (j * 20) + 5);
+				if (adj_chan && acs_usable_chan(adj_chan)) {
+					factor += ACS_ADJ_WEIGHT *
+						adj_chan->interference_factor;
+					total_weight += ACS_ADJ_WEIGHT;
+				}
+
+				adj_chan = acs_find_chan(iface, chan->freq +
+							 (j * 20) + 10);
+				if (adj_chan && acs_usable_chan(adj_chan)) {
+					factor += ACS_NEXT_ADJ_WEIGHT *
+						adj_chan->interference_factor;
+					total_weight += ACS_NEXT_ADJ_WEIGHT;
+				}
+			}
+		}
+
+		factor /= total_weight;
+
+		bias = NULL;
+		if (iface->conf->acs_chan_bias) {
+			for (k = 0; k < iface->conf->num_acs_chan_bias; k++) {
+				bias = &iface->conf->acs_chan_bias[k];
+				if (bias->channel == chan->chan)
+					break;
+				bias = NULL;
+			}
+		} else if (is_24ghz_mode(iface->current_mode->mode) &&
+			   is_common_24ghz_chan(chan->chan)) {
+			tmp_bias.channel = chan->chan;
+			tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
+			bias = &tmp_bias;
+		}
+
+		if (bias) {
+			factor *= bias->bias;
+			wpa_printf(MSG_DEBUG,
+				   "ACS:  * channel %d: total interference = %Lg (%f bias)",
+				   chan->chan, factor, bias->bias);
+		} else {
+			wpa_printf(MSG_DEBUG,
+				   "ACS:  * channel %d: total interference = %Lg",
+				   chan->chan, factor);
+		}
+
+		if (acs_usable_chan(chan) &&
+		    (!ideal_chan || factor < ideal_factor)) {
+			ideal_factor = factor;
+			ideal_chan = chan;
+		}
+
+		/* This channel would at least be usable */
+		if (!rand_chan)
+			rand_chan = chan;
+	}
+
+	if (ideal_chan) {
+		wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
+			   ideal_chan->chan, ideal_chan->freq, ideal_factor);
+		return ideal_chan;
+	}
+
+	return rand_chan;
+}
+
+
+static void acs_adjust_vht_center_freq(struct hostapd_iface *iface)
+{
+	int offset;
+
+	wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency");
+
+	switch (iface->conf->vht_oper_chwidth) {
+	case VHT_CHANWIDTH_USE_HT:
+		offset = 2 * iface->conf->secondary_channel;
+		break;
+	case VHT_CHANWIDTH_80MHZ:
+		offset = 6;
+		break;
+	default:
+		/* TODO: How can this be calculated? Adjust
+		 * acs_find_ideal_chan() */
+		wpa_printf(MSG_INFO, "ACS: Only VHT20/40/80 is supported now");
+		return;
+	}
+
+	iface->conf->vht_oper_centr_freq_seg0_idx =
+		iface->conf->channel + offset;
+}
+
+
+static int acs_study_survey_based(struct hostapd_iface *iface)
+{
+	wpa_printf(MSG_DEBUG, "ACS: Trying survey-based ACS");
+
+	if (!iface->chans_surveyed) {
+		wpa_printf(MSG_ERROR, "ACS: Unable to collect survey data");
+		return -1;
+	}
+
+	if (!acs_surveys_are_sufficient(iface)) {
+		wpa_printf(MSG_ERROR, "ACS: Surveys have insufficient data");
+		return -1;
+	}
+
+	acs_survey_all_chans_intereference_factor(iface);
+	return 0;
+}
+
+
+static int acs_study_options(struct hostapd_iface *iface)
+{
+	int err;
+
+	err = acs_study_survey_based(iface);
+	if (err == 0)
+		return 0;
+
+	/* TODO: If no surveys are available/sufficient this is a good
+	 * place to fallback to BSS-based ACS */
+
+	return -1;
+}
+
+
+static void acs_study(struct hostapd_iface *iface)
+{
+	struct hostapd_channel_data *ideal_chan;
+	int err;
+
+	err = acs_study_options(iface);
+	if (err < 0) {
+		wpa_printf(MSG_ERROR, "ACS: All study options have failed");
+		goto fail;
+	}
+
+	ideal_chan = acs_find_ideal_chan(iface);
+	if (!ideal_chan) {
+		wpa_printf(MSG_ERROR, "ACS: Failed to compute ideal channel");
+		err = -1;
+		goto fail;
+	}
+
+	iface->conf->channel = ideal_chan->chan;
+
+	if (iface->conf->ieee80211ac)
+		acs_adjust_vht_center_freq(iface);
+
+	err = 0;
+fail:
+	/*
+	 * hostapd_setup_interface_complete() will return -1 on failure,
+	 * 0 on success and 0 is HOSTAPD_CHAN_VALID :)
+	 */
+	if (hostapd_acs_completed(iface, err) == HOSTAPD_CHAN_VALID) {
+		acs_cleanup(iface);
+		return;
+	}
+
+	/* This can possibly happen if channel parameters (secondary
+	 * channel, center frequencies) are misconfigured */
+	wpa_printf(MSG_ERROR, "ACS: Possibly channel configuration is invalid, please report this along with your config file.");
+	acs_fail(iface);
+}
+
+
+static void acs_scan_complete(struct hostapd_iface *iface)
+{
+	int err;
+
+	iface->scan_cb = NULL;
+
+	wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)",
+		   iface->conf->acs_num_scans);
+
+	err = hostapd_drv_get_survey(iface->bss[0], 0);
+	if (err) {
+		wpa_printf(MSG_ERROR, "ACS: Failed to get survey data");
+		goto fail;
+	}
+
+	if (++iface->acs_num_completed_scans < iface->conf->acs_num_scans) {
+		err = acs_request_scan(iface);
+		if (err) {
+			wpa_printf(MSG_ERROR, "ACS: Failed to request scan");
+			goto fail;
+		}
+
+		return;
+	}
+
+	acs_study(iface);
+	return;
+fail:
+	hostapd_acs_completed(iface, 1);
+	acs_fail(iface);
+}
+
+
+static int acs_request_scan(struct hostapd_iface *iface)
+{
+	struct wpa_driver_scan_params params;
+	struct hostapd_channel_data *chan;
+	int i, *freq;
+
+	os_memset(&params, 0, sizeof(params));
+	params.freqs = os_calloc(iface->current_mode->num_channels + 1,
+				 sizeof(params.freqs[0]));
+	if (params.freqs == NULL)
+		return -1;
+
+	freq = params.freqs;
+	for (i = 0; i < iface->current_mode->num_channels; i++) {
+		chan = &iface->current_mode->channels[i];
+		if (chan->flag & HOSTAPD_CHAN_DISABLED)
+			continue;
+
+		if (!is_in_chanlist(iface, chan))
+			continue;
+
+		*freq++ = chan->freq;
+	}
+	*freq = 0;
+
+	iface->scan_cb = acs_scan_complete;
+
+	wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
+		   iface->acs_num_completed_scans + 1,
+		   iface->conf->acs_num_scans);
+
+	if (hostapd_driver_scan(iface->bss[0], &params) < 0) {
+		wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan");
+		acs_cleanup(iface);
+		os_free(params.freqs);
+		return -1;
+	}
+
+	os_free(params.freqs);
+	return 0;
+}
+
+
+enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
+{
+	int err;
+
+	wpa_printf(MSG_INFO, "ACS: Automatic channel selection started, this may take a bit");
+
+	if (iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) {
+		wpa_printf(MSG_INFO, "ACS: Offloading to driver");
+		err = hostapd_drv_do_acs(iface->bss[0]);
+		if (err)
+			return HOSTAPD_CHAN_INVALID;
+		return HOSTAPD_CHAN_ACS;
+	}
+
+	if (!iface->current_mode)
+		return HOSTAPD_CHAN_INVALID;
+
+	acs_cleanup(iface);
+
+	err = acs_request_scan(iface);
+	if (err < 0)
+		return HOSTAPD_CHAN_INVALID;
+
+	hostapd_set_state(iface, HAPD_IFACE_ACS);
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_STARTED);
+
+	return HOSTAPD_CHAN_ACS;
+}

+ 27 - 0
EVSE/GPL/hostapd-2.6/src/ap/acs.h

@@ -0,0 +1,27 @@
+/*
+ * ACS - Automatic Channel Selection module
+ * Copyright (c) 2011, Atheros Communications
+ * Copyright (c) 2013, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef ACS_H
+#define ACS_H
+
+#ifdef CONFIG_ACS
+
+enum hostapd_chan_status acs_init(struct hostapd_iface *iface);
+
+#else /* CONFIG_ACS */
+
+static inline enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
+{
+	wpa_printf(MSG_ERROR, "ACS was disabled on your build, rebuild hostapd with CONFIG_ACS=y or set channel");
+	return HOSTAPD_CHAN_INVALID;
+}
+
+#endif /* CONFIG_ACS */
+
+#endif /* ACS_H */

+ 1033 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_config.c

@@ -0,0 +1,1033 @@
+/*
+ * hostapd / Configuration helper functions
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "crypto/sha1.h"
+#include "radius/radius_client.h"
+#include "common/ieee802_11_defs.h"
+#include "common/eapol_common.h"
+#include "eap_common/eap_wsc_common.h"
+#include "eap_server/eap.h"
+#include "wpa_auth.h"
+#include "sta_info.h"
+#include "ap_config.h"
+
+
+static void hostapd_config_free_vlan(struct hostapd_bss_config *bss)
+{
+	struct hostapd_vlan *vlan, *prev;
+
+	vlan = bss->vlan;
+	prev = NULL;
+	while (vlan) {
+		prev = vlan;
+		vlan = vlan->next;
+		os_free(prev);
+	}
+
+	bss->vlan = NULL;
+}
+
+
+void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
+{
+	dl_list_init(&bss->anqp_elem);
+
+	bss->logger_syslog_level = HOSTAPD_LEVEL_INFO;
+	bss->logger_stdout_level = HOSTAPD_LEVEL_INFO;
+	bss->logger_syslog = (unsigned int) -1;
+	bss->logger_stdout = (unsigned int) -1;
+
+	bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
+
+	bss->wep_rekeying_period = 300;
+	/* use key0 in individual key and key1 in broadcast key */
+	bss->broadcast_key_idx_min = 1;
+	bss->broadcast_key_idx_max = 2;
+	bss->eap_reauth_period = 3600;
+
+	bss->wpa_group_rekey = 600;
+	bss->wpa_gmk_rekey = 86400;
+	bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
+	bss->wpa_pairwise = WPA_CIPHER_TKIP;
+	bss->wpa_group = WPA_CIPHER_TKIP;
+	bss->rsn_pairwise = 0;
+
+	bss->max_num_sta = MAX_STA_COUNT;
+
+	bss->dtim_period = 2;
+
+	bss->radius_server_auth_port = 1812;
+	bss->eap_sim_db_timeout = 1;
+	bss->ap_max_inactivity = AP_MAX_INACTIVITY;
+	bss->eapol_version = EAPOL_VERSION;
+
+	bss->max_listen_interval = 65535;
+
+	bss->pwd_group = 19; /* ECC: GF(p=256) */
+
+#ifdef CONFIG_IEEE80211W
+	bss->assoc_sa_query_max_timeout = 1000;
+	bss->assoc_sa_query_retry_timeout = 201;
+	bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
+#endif /* CONFIG_IEEE80211W */
+#ifdef EAP_SERVER_FAST
+	 /* both anonymous and authenticated provisioning */
+	bss->eap_fast_prov = 3;
+	bss->pac_key_lifetime = 7 * 24 * 60 * 60;
+	bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
+#endif /* EAP_SERVER_FAST */
+
+	/* Set to -1 as defaults depends on HT in setup */
+	bss->wmm_enabled = -1;
+
+#ifdef CONFIG_IEEE80211R
+	bss->ft_over_ds = 1;
+#endif /* CONFIG_IEEE80211R */
+
+	bss->radius_das_time_window = 300;
+
+	bss->sae_anti_clogging_threshold = 5;
+}
+
+
+struct hostapd_config * hostapd_config_defaults(void)
+{
+#define ecw2cw(ecw) ((1 << (ecw)) - 1)
+
+	struct hostapd_config *conf;
+	struct hostapd_bss_config *bss;
+	const int aCWmin = 4, aCWmax = 10;
+	const struct hostapd_wmm_ac_params ac_bk =
+		{ aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */
+	const struct hostapd_wmm_ac_params ac_be =
+		{ aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */
+	const struct hostapd_wmm_ac_params ac_vi = /* video traffic */
+		{ aCWmin - 1, aCWmin, 2, 3008 / 32, 0 };
+	const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */
+		{ aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 };
+	const struct hostapd_tx_queue_params txq_bk =
+		{ 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 };
+	const struct hostapd_tx_queue_params txq_be =
+		{ 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0};
+	const struct hostapd_tx_queue_params txq_vi =
+		{ 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30};
+	const struct hostapd_tx_queue_params txq_vo =
+		{ 1, (ecw2cw(aCWmin) + 1) / 4 - 1,
+		  (ecw2cw(aCWmin) + 1) / 2 - 1, 15};
+
+#undef ecw2cw
+
+	conf = os_zalloc(sizeof(*conf));
+	bss = os_zalloc(sizeof(*bss));
+	if (conf == NULL || bss == NULL) {
+		wpa_printf(MSG_ERROR, "Failed to allocate memory for "
+			   "configuration data.");
+		os_free(conf);
+		os_free(bss);
+		return NULL;
+	}
+	conf->bss = os_calloc(1, sizeof(struct hostapd_bss_config *));
+	if (conf->bss == NULL) {
+		os_free(conf);
+		os_free(bss);
+		return NULL;
+	}
+	conf->bss[0] = bss;
+
+	bss->radius = os_zalloc(sizeof(*bss->radius));
+	if (bss->radius == NULL) {
+		os_free(conf->bss);
+		os_free(conf);
+		os_free(bss);
+		return NULL;
+	}
+
+	hostapd_config_defaults_bss(bss);
+
+	conf->num_bss = 1;
+
+	conf->beacon_int = 100;
+	conf->rts_threshold = -1; /* use driver default: 2347 */
+	conf->fragm_threshold = -1; /* user driver default: 2346 */
+	conf->send_probe_response = 1;
+	/* Set to invalid value means do not add Power Constraint IE */
+	conf->local_pwr_constraint = -1;
+
+	conf->wmm_ac_params[0] = ac_be;
+	conf->wmm_ac_params[1] = ac_bk;
+	conf->wmm_ac_params[2] = ac_vi;
+	conf->wmm_ac_params[3] = ac_vo;
+
+	conf->tx_queue[0] = txq_vo;
+	conf->tx_queue[1] = txq_vi;
+	conf->tx_queue[2] = txq_be;
+	conf->tx_queue[3] = txq_bk;
+
+	conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
+
+	conf->ap_table_max_size = 255;
+	conf->ap_table_expiration_time = 60;
+	conf->track_sta_max_age = 180;
+
+#ifdef CONFIG_TESTING_OPTIONS
+	conf->ignore_probe_probability = 0.0;
+	conf->ignore_auth_probability = 0.0;
+	conf->ignore_assoc_probability = 0.0;
+	conf->ignore_reassoc_probability = 0.0;
+	conf->corrupt_gtk_rekey_mic_probability = 0.0;
+	conf->ecsa_ie_only = 0;
+#endif /* CONFIG_TESTING_OPTIONS */
+
+	conf->acs = 0;
+	conf->acs_ch_list.num = 0;
+#ifdef CONFIG_ACS
+	conf->acs_num_scans = 5;
+#endif /* CONFIG_ACS */
+
+	return conf;
+}
+
+
+int hostapd_mac_comp(const void *a, const void *b)
+{
+	return os_memcmp(a, b, sizeof(macaddr));
+}
+
+
+static int hostapd_config_read_wpa_psk(const char *fname,
+				       struct hostapd_ssid *ssid)
+{
+	FILE *f;
+	char buf[128], *pos;
+	int line = 0, ret = 0, len, ok;
+	u8 addr[ETH_ALEN];
+	struct hostapd_wpa_psk *psk;
+
+	if (!fname)
+		return 0;
+
+	f = fopen(fname, "r");
+	if (!f) {
+		wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname);
+		return -1;
+	}
+
+	while (fgets(buf, sizeof(buf), f)) {
+		line++;
+
+		if (buf[0] == '#')
+			continue;
+		pos = buf;
+		while (*pos != '\0') {
+			if (*pos == '\n') {
+				*pos = '\0';
+				break;
+			}
+			pos++;
+		}
+		if (buf[0] == '\0')
+			continue;
+
+		if (hwaddr_aton(buf, addr)) {
+			wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
+				   "line %d in '%s'", buf, line, fname);
+			ret = -1;
+			break;
+		}
+
+		psk = os_zalloc(sizeof(*psk));
+		if (psk == NULL) {
+			wpa_printf(MSG_ERROR, "WPA PSK allocation failed");
+			ret = -1;
+			break;
+		}
+		if (is_zero_ether_addr(addr))
+			psk->group = 1;
+		else
+			os_memcpy(psk->addr, addr, ETH_ALEN);
+
+		pos = buf + 17;
+		if (*pos == '\0') {
+			wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'",
+				   line, fname);
+			os_free(psk);
+			ret = -1;
+			break;
+		}
+		pos++;
+
+		ok = 0;
+		len = os_strlen(pos);
+		if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
+			ok = 1;
+		else if (len >= 8 && len < 64) {
+			pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
+				    4096, psk->psk, PMK_LEN);
+			ok = 1;
+		}
+		if (!ok) {
+			wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
+				   "'%s'", pos, line, fname);
+			os_free(psk);
+			ret = -1;
+			break;
+		}
+
+		psk->next = ssid->wpa_psk;
+		ssid->wpa_psk = psk;
+	}
+
+	fclose(f);
+
+	return ret;
+}
+
+
+static int hostapd_derive_psk(struct hostapd_ssid *ssid)
+{
+	ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk));
+	if (ssid->wpa_psk == NULL) {
+		wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
+		return -1;
+	}
+	wpa_hexdump_ascii(MSG_DEBUG, "SSID",
+			  (u8 *) ssid->ssid, ssid->ssid_len);
+	wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)",
+			      (u8 *) ssid->wpa_passphrase,
+			      os_strlen(ssid->wpa_passphrase));
+	pbkdf2_sha1(ssid->wpa_passphrase,
+		    ssid->ssid, ssid->ssid_len,
+		    4096, ssid->wpa_psk->psk, PMK_LEN);
+	wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)",
+			ssid->wpa_psk->psk, PMK_LEN);
+	return 0;
+}
+
+
+int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
+{
+	struct hostapd_ssid *ssid = &conf->ssid;
+
+	if (ssid->wpa_passphrase != NULL) {
+		if (ssid->wpa_psk != NULL) {
+			wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
+				   "instead of passphrase");
+		} else {
+			wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on "
+				   "passphrase");
+			if (hostapd_derive_psk(ssid) < 0)
+				return -1;
+		}
+		ssid->wpa_psk->group = 1;
+	}
+
+	if (ssid->wpa_psk_file) {
+		if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file,
+						&conf->ssid))
+			return -1;
+	}
+
+	return 0;
+}
+
+
+static void hostapd_config_free_radius(struct hostapd_radius_server *servers,
+				       int num_servers)
+{
+	int i;
+
+	for (i = 0; i < num_servers; i++) {
+		os_free(servers[i].shared_secret);
+	}
+	os_free(servers);
+}
+
+
+struct hostapd_radius_attr *
+hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type)
+{
+	for (; attr; attr = attr->next) {
+		if (attr->type == type)
+			return attr;
+	}
+	return NULL;
+}
+
+
+static void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
+{
+	struct hostapd_radius_attr *prev;
+
+	while (attr) {
+		prev = attr;
+		attr = attr->next;
+		wpabuf_free(prev->val);
+		os_free(prev);
+	}
+}
+
+
+void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
+{
+	hostapd_config_free_radius_attr(user->accept_attr);
+	os_free(user->identity);
+	bin_clear_free(user->password, user->password_len);
+	os_free(user);
+}
+
+
+static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
+{
+	int i;
+	for (i = 0; i < NUM_WEP_KEYS; i++) {
+		bin_clear_free(keys->key[i], keys->len[i]);
+		keys->key[i] = NULL;
+	}
+}
+
+
+void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l)
+{
+	struct hostapd_wpa_psk *psk, *tmp;
+
+	for (psk = *l; psk;) {
+		tmp = psk;
+		psk = psk->next;
+		bin_clear_free(tmp, sizeof(*tmp));
+	}
+	*l = NULL;
+}
+
+
+static void hostapd_config_free_anqp_elem(struct hostapd_bss_config *conf)
+{
+	struct anqp_element *elem;
+
+	while ((elem = dl_list_first(&conf->anqp_elem, struct anqp_element,
+				     list))) {
+		dl_list_del(&elem->list);
+		wpabuf_free(elem->payload);
+		os_free(elem);
+	}
+}
+
+
+void hostapd_config_free_bss(struct hostapd_bss_config *conf)
+{
+	struct hostapd_eap_user *user, *prev_user;
+
+	if (conf == NULL)
+		return;
+
+	hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk);
+
+	str_clear_free(conf->ssid.wpa_passphrase);
+	os_free(conf->ssid.wpa_psk_file);
+	hostapd_config_free_wep(&conf->ssid.wep);
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+	os_free(conf->ssid.vlan_tagged_interface);
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+
+	user = conf->eap_user;
+	while (user) {
+		prev_user = user;
+		user = user->next;
+		hostapd_config_free_eap_user(prev_user);
+	}
+	os_free(conf->eap_user_sqlite);
+
+	os_free(conf->eap_req_id_text);
+	os_free(conf->erp_domain);
+	os_free(conf->accept_mac);
+	os_free(conf->deny_mac);
+	os_free(conf->nas_identifier);
+	if (conf->radius) {
+		hostapd_config_free_radius(conf->radius->auth_servers,
+					   conf->radius->num_auth_servers);
+		hostapd_config_free_radius(conf->radius->acct_servers,
+					   conf->radius->num_acct_servers);
+	}
+	hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
+	hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
+	os_free(conf->rsn_preauth_interfaces);
+	os_free(conf->ctrl_interface);
+	os_free(conf->ca_cert);
+	os_free(conf->server_cert);
+	os_free(conf->private_key);
+	os_free(conf->private_key_passwd);
+	os_free(conf->ocsp_stapling_response);
+	os_free(conf->ocsp_stapling_response_multi);
+	os_free(conf->dh_file);
+	os_free(conf->openssl_ciphers);
+	os_free(conf->pac_opaque_encr_key);
+	os_free(conf->eap_fast_a_id);
+	os_free(conf->eap_fast_a_id_info);
+	os_free(conf->eap_sim_db);
+	os_free(conf->radius_server_clients);
+	os_free(conf->radius);
+	os_free(conf->radius_das_shared_secret);
+	hostapd_config_free_vlan(conf);
+	os_free(conf->time_zone);
+
+#ifdef CONFIG_IEEE80211R
+	{
+		struct ft_remote_r0kh *r0kh, *r0kh_prev;
+		struct ft_remote_r1kh *r1kh, *r1kh_prev;
+
+		r0kh = conf->r0kh_list;
+		conf->r0kh_list = NULL;
+		while (r0kh) {
+			r0kh_prev = r0kh;
+			r0kh = r0kh->next;
+			os_free(r0kh_prev);
+		}
+
+		r1kh = conf->r1kh_list;
+		conf->r1kh_list = NULL;
+		while (r1kh) {
+			r1kh_prev = r1kh;
+			r1kh = r1kh->next;
+			os_free(r1kh_prev);
+		}
+	}
+#endif /* CONFIG_IEEE80211R */
+
+#ifdef CONFIG_WPS
+	os_free(conf->wps_pin_requests);
+	os_free(conf->device_name);
+	os_free(conf->manufacturer);
+	os_free(conf->model_name);
+	os_free(conf->model_number);
+	os_free(conf->serial_number);
+	os_free(conf->config_methods);
+	os_free(conf->ap_pin);
+	os_free(conf->extra_cred);
+	os_free(conf->ap_settings);
+	os_free(conf->upnp_iface);
+	os_free(conf->friendly_name);
+	os_free(conf->manufacturer_url);
+	os_free(conf->model_description);
+	os_free(conf->model_url);
+	os_free(conf->upc);
+	{
+		unsigned int i;
+
+		for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
+			wpabuf_free(conf->wps_vendor_ext[i]);
+	}
+	wpabuf_free(conf->wps_nfc_dh_pubkey);
+	wpabuf_free(conf->wps_nfc_dh_privkey);
+	wpabuf_free(conf->wps_nfc_dev_pw);
+#endif /* CONFIG_WPS */
+
+	os_free(conf->roaming_consortium);
+	os_free(conf->venue_name);
+	os_free(conf->nai_realm_data);
+	os_free(conf->network_auth_type);
+	os_free(conf->anqp_3gpp_cell_net);
+	os_free(conf->domain_name);
+	hostapd_config_free_anqp_elem(conf);
+
+#ifdef CONFIG_RADIUS_TEST
+	os_free(conf->dump_msk_file);
+#endif /* CONFIG_RADIUS_TEST */
+
+#ifdef CONFIG_HS20
+	os_free(conf->hs20_oper_friendly_name);
+	os_free(conf->hs20_wan_metrics);
+	os_free(conf->hs20_connection_capability);
+	os_free(conf->hs20_operating_class);
+	os_free(conf->hs20_icons);
+	if (conf->hs20_osu_providers) {
+		size_t i;
+		for (i = 0; i < conf->hs20_osu_providers_count; i++) {
+			struct hs20_osu_provider *p;
+			size_t j;
+			p = &conf->hs20_osu_providers[i];
+			os_free(p->friendly_name);
+			os_free(p->server_uri);
+			os_free(p->method_list);
+			for (j = 0; j < p->icons_count; j++)
+				os_free(p->icons[j]);
+			os_free(p->icons);
+			os_free(p->osu_nai);
+			os_free(p->service_desc);
+		}
+		os_free(conf->hs20_osu_providers);
+	}
+	os_free(conf->subscr_remediation_url);
+#endif /* CONFIG_HS20 */
+
+	wpabuf_free(conf->vendor_elements);
+	wpabuf_free(conf->assocresp_elements);
+
+	os_free(conf->sae_groups);
+
+	os_free(conf->wowlan_triggers);
+
+	os_free(conf->server_id);
+
+#ifdef CONFIG_TESTING_OPTIONS
+	wpabuf_free(conf->own_ie_override);
+#endif /* CONFIG_TESTING_OPTIONS */
+
+	os_free(conf->no_probe_resp_if_seen_on);
+	os_free(conf->no_auth_if_seen_on);
+
+	os_free(conf);
+}
+
+
+/**
+ * hostapd_config_free - Free hostapd configuration
+ * @conf: Configuration data from hostapd_config_read().
+ */
+void hostapd_config_free(struct hostapd_config *conf)
+{
+	size_t i;
+
+	if (conf == NULL)
+		return;
+
+	for (i = 0; i < conf->num_bss; i++)
+		hostapd_config_free_bss(conf->bss[i]);
+	os_free(conf->bss);
+	os_free(conf->supported_rates);
+	os_free(conf->basic_rates);
+	os_free(conf->acs_ch_list.range);
+	os_free(conf->driver_params);
+#ifdef CONFIG_ACS
+	os_free(conf->acs_chan_bias);
+#endif /* CONFIG_ACS */
+	wpabuf_free(conf->lci);
+	wpabuf_free(conf->civic);
+
+	os_free(conf);
+}
+
+
+/**
+ * hostapd_maclist_found - Find a MAC address from a list
+ * @list: MAC address list
+ * @num_entries: Number of addresses in the list
+ * @addr: Address to search for
+ * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed
+ * Returns: 1 if address is in the list or 0 if not.
+ *
+ * Perform a binary search for given MAC address from a pre-sorted list.
+ */
+int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
+			  const u8 *addr, struct vlan_description *vlan_id)
+{
+	int start, end, middle, res;
+
+	start = 0;
+	end = num_entries - 1;
+
+	while (start <= end) {
+		middle = (start + end) / 2;
+		res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
+		if (res == 0) {
+			if (vlan_id)
+				*vlan_id = list[middle].vlan_id;
+			return 1;
+		}
+		if (res < 0)
+			start = middle + 1;
+		else
+			end = middle - 1;
+	}
+
+	return 0;
+}
+
+
+int hostapd_rate_found(int *list, int rate)
+{
+	int i;
+
+	if (list == NULL)
+		return 0;
+
+	for (i = 0; list[i] >= 0; i++)
+		if (list[i] == rate)
+			return 1;
+
+	return 0;
+}
+
+
+int hostapd_vlan_valid(struct hostapd_vlan *vlan,
+		       struct vlan_description *vlan_desc)
+{
+	struct hostapd_vlan *v = vlan;
+	int i;
+
+	if (!vlan_desc->notempty || vlan_desc->untagged < 0 ||
+	    vlan_desc->untagged > MAX_VLAN_ID)
+		return 0;
+	for (i = 0; i < MAX_NUM_TAGGED_VLAN; i++) {
+		if (vlan_desc->tagged[i] < 0 ||
+		    vlan_desc->tagged[i] > MAX_VLAN_ID)
+			return 0;
+	}
+	if (!vlan_desc->untagged && !vlan_desc->tagged[0])
+		return 0;
+
+	while (v) {
+		if (!vlan_compare(&v->vlan_desc, vlan_desc) ||
+		    v->vlan_id == VLAN_ID_WILDCARD)
+			return 1;
+		v = v->next;
+	}
+	return 0;
+}
+
+
+const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id)
+{
+	struct hostapd_vlan *v = vlan;
+	while (v) {
+		if (v->vlan_id == vlan_id)
+			return v->ifname;
+		v = v->next;
+	}
+	return NULL;
+}
+
+
+const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
+			   const u8 *addr, const u8 *p2p_dev_addr,
+			   const u8 *prev_psk)
+{
+	struct hostapd_wpa_psk *psk;
+	int next_ok = prev_psk == NULL;
+
+	if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) {
+		wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR
+			   " p2p_dev_addr=" MACSTR " prev_psk=%p",
+			   MAC2STR(addr), MAC2STR(p2p_dev_addr), prev_psk);
+		addr = NULL; /* Use P2P Device Address for matching */
+	} else {
+		wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR
+			   " prev_psk=%p",
+			   MAC2STR(addr), prev_psk);
+	}
+
+	for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
+		if (next_ok &&
+		    (psk->group ||
+		     (addr && os_memcmp(psk->addr, addr, ETH_ALEN) == 0) ||
+		     (!addr && p2p_dev_addr &&
+		      os_memcmp(psk->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) ==
+		      0)))
+			return psk->psk;
+
+		if (psk->psk == prev_psk)
+			next_ok = 1;
+	}
+
+	return NULL;
+}
+
+
+static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
+				    struct hostapd_config *conf,
+				    int full_config)
+{
+	if (full_config && bss->ieee802_1x && !bss->eap_server &&
+	    !bss->radius->auth_servers) {
+		wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no "
+			   "EAP authenticator configured).");
+		return -1;
+	}
+
+	if (bss->wpa) {
+		int wep, i;
+
+		wep = bss->default_wep_key_len > 0 ||
+		       bss->individual_wep_key_len > 0;
+		for (i = 0; i < NUM_WEP_KEYS; i++) {
+			if (bss->ssid.wep.keys_set) {
+				wep = 1;
+				break;
+			}
+		}
+
+		if (wep) {
+			wpa_printf(MSG_ERROR, "WEP configuration in a WPA network is not supported");
+			return -1;
+		}
+	}
+
+	if (full_config && bss->wpa &&
+	    bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
+	    bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
+		wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
+			   "RADIUS checking (macaddr_acl=2) enabled.");
+		return -1;
+	}
+
+	if (full_config && bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
+	    bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
+	    bss->ssid.wpa_psk_file == NULL &&
+	    (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
+	     bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) {
+		wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
+			   "is not configured.");
+		return -1;
+	}
+
+	if (full_config && !is_zero_ether_addr(bss->bssid)) {
+		size_t i;
+
+		for (i = 0; i < conf->num_bss; i++) {
+			if (conf->bss[i] != bss &&
+			    (hostapd_mac_comp(conf->bss[i]->bssid,
+					      bss->bssid) == 0)) {
+				wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR
+					   " on interface '%s' and '%s'.",
+					   MAC2STR(bss->bssid),
+					   conf->bss[i]->iface, bss->iface);
+				return -1;
+			}
+		}
+	}
+
+#ifdef CONFIG_IEEE80211R
+	if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) &&
+	    (bss->nas_identifier == NULL ||
+	     os_strlen(bss->nas_identifier) < 1 ||
+	     os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) {
+		wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires "
+			   "nas_identifier to be configured as a 1..48 octet "
+			   "string");
+		return -1;
+	}
+#endif /* CONFIG_IEEE80211R */
+
+#ifdef CONFIG_IEEE80211N
+	if (full_config && conf->ieee80211n &&
+	    conf->hw_mode == HOSTAPD_MODE_IEEE80211B) {
+		bss->disable_11n = 1;
+		wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not "
+			   "allowed, disabling HT capabilities");
+	}
+
+	if (full_config && conf->ieee80211n &&
+	    bss->ssid.security_policy == SECURITY_STATIC_WEP) {
+		bss->disable_11n = 1;
+		wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not "
+			   "allowed, disabling HT capabilities");
+	}
+
+	if (full_config && conf->ieee80211n && bss->wpa &&
+	    !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
+	    !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
+				   WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))
+	{
+		bss->disable_11n = 1;
+		wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
+			   "requires CCMP/GCMP to be enabled, disabling HT "
+			   "capabilities");
+	}
+#endif /* CONFIG_IEEE80211N */
+
+#ifdef CONFIG_IEEE80211AC
+	if (full_config && conf->ieee80211ac &&
+	    bss->ssid.security_policy == SECURITY_STATIC_WEP) {
+		bss->disable_11ac = 1;
+		wpa_printf(MSG_ERROR,
+			   "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities");
+	}
+#endif /* CONFIG_IEEE80211AC */
+
+#ifdef CONFIG_WPS
+	if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) {
+		wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid "
+			   "configuration forced WPS to be disabled");
+		bss->wps_state = 0;
+	}
+
+	if (full_config && bss->wps_state &&
+	    bss->ssid.wep.keys_set && bss->wpa == 0) {
+		wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be "
+			   "disabled");
+		bss->wps_state = 0;
+	}
+
+	if (full_config && bss->wps_state && bss->wpa &&
+	    (!(bss->wpa & 2) ||
+	     !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)))) {
+		wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without "
+			   "WPA2/CCMP/GCMP forced WPS to be disabled");
+		bss->wps_state = 0;
+	}
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_HS20
+	if (full_config && bss->hs20 &&
+	    (!(bss->wpa & 2) ||
+	     !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP |
+				    WPA_CIPHER_CCMP_256 |
+				    WPA_CIPHER_GCMP_256)))) {
+		wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP "
+			   "configuration is required for Hotspot 2.0 "
+			   "functionality");
+		return -1;
+	}
+#endif /* CONFIG_HS20 */
+
+#ifdef CONFIG_MBO
+	if (full_config && bss->mbo_enabled && (bss->wpa & 2) &&
+	    bss->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
+		wpa_printf(MSG_ERROR,
+			   "MBO: PMF needs to be enabled whenever using WPA2 with MBO");
+		return -1;
+	}
+#endif /* CONFIG_MBO */
+
+	return 0;
+}
+
+
+static int hostapd_config_check_cw(struct hostapd_config *conf, int queue)
+{
+	int tx_cwmin = conf->tx_queue[queue].cwmin;
+	int tx_cwmax = conf->tx_queue[queue].cwmax;
+	int ac_cwmin = conf->wmm_ac_params[queue].cwmin;
+	int ac_cwmax = conf->wmm_ac_params[queue].cwmax;
+
+	if (tx_cwmin > tx_cwmax) {
+		wpa_printf(MSG_ERROR,
+			   "Invalid TX queue cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)",
+			   tx_cwmin, tx_cwmax);
+		return -1;
+	}
+	if (ac_cwmin > ac_cwmax) {
+		wpa_printf(MSG_ERROR,
+			   "Invalid WMM AC cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)",
+			   ac_cwmin, ac_cwmax);
+		return -1;
+	}
+	return 0;
+}
+
+
+int hostapd_config_check(struct hostapd_config *conf, int full_config)
+{
+	size_t i;
+
+	if (full_config && conf->ieee80211d &&
+	    (!conf->country[0] || !conf->country[1])) {
+		wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without "
+			   "setting the country_code");
+		return -1;
+	}
+
+	if (full_config && conf->ieee80211h && !conf->ieee80211d) {
+		wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without "
+			   "IEEE 802.11d enabled");
+		return -1;
+	}
+
+	if (full_config && conf->local_pwr_constraint != -1 &&
+	    !conf->ieee80211d) {
+		wpa_printf(MSG_ERROR, "Cannot add Power Constraint element without Country element");
+		return -1;
+	}
+
+	if (full_config && conf->spectrum_mgmt_required &&
+	    conf->local_pwr_constraint == -1) {
+		wpa_printf(MSG_ERROR, "Cannot set Spectrum Management bit without Country and Power Constraint elements");
+		return -1;
+	}
+
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		if (hostapd_config_check_cw(conf, i))
+			return -1;
+	}
+
+	for (i = 0; i < conf->num_bss; i++) {
+		if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
+			return -1;
+	}
+
+	return 0;
+}
+
+
+void hostapd_set_security_params(struct hostapd_bss_config *bss,
+				 int full_config)
+{
+	if (bss->individual_wep_key_len == 0) {
+		/* individual keys are not use; can use key idx0 for
+		 * broadcast keys */
+		bss->broadcast_key_idx_min = 0;
+	}
+
+	if ((bss->wpa & 2) && bss->rsn_pairwise == 0)
+		bss->rsn_pairwise = bss->wpa_pairwise;
+	bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise,
+						    bss->rsn_pairwise);
+
+	if (full_config) {
+		bss->radius->auth_server = bss->radius->auth_servers;
+		bss->radius->acct_server = bss->radius->acct_servers;
+	}
+
+	if (bss->wpa && bss->ieee802_1x) {
+		bss->ssid.security_policy = SECURITY_WPA;
+	} else if (bss->wpa) {
+		bss->ssid.security_policy = SECURITY_WPA_PSK;
+	} else if (bss->ieee802_1x) {
+		int cipher = WPA_CIPHER_NONE;
+		bss->ssid.security_policy = SECURITY_IEEE_802_1X;
+		bss->ssid.wep.default_len = bss->default_wep_key_len;
+		if (full_config && bss->default_wep_key_len) {
+			cipher = bss->default_wep_key_len >= 13 ?
+				WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40;
+		} else if (full_config && bss->ssid.wep.keys_set) {
+			if (bss->ssid.wep.len[0] >= 13)
+				cipher = WPA_CIPHER_WEP104;
+			else
+				cipher = WPA_CIPHER_WEP40;
+		}
+		bss->wpa_group = cipher;
+		bss->wpa_pairwise = cipher;
+		bss->rsn_pairwise = cipher;
+		if (full_config)
+			bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
+	} else if (bss->ssid.wep.keys_set) {
+		int cipher = WPA_CIPHER_WEP40;
+		if (bss->ssid.wep.len[0] >= 13)
+			cipher = WPA_CIPHER_WEP104;
+		bss->ssid.security_policy = SECURITY_STATIC_WEP;
+		bss->wpa_group = cipher;
+		bss->wpa_pairwise = cipher;
+		bss->rsn_pairwise = cipher;
+		if (full_config)
+			bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
+	} else if (bss->osen) {
+		bss->ssid.security_policy = SECURITY_OSEN;
+		bss->wpa_group = WPA_CIPHER_CCMP;
+		bss->wpa_pairwise = 0;
+		bss->rsn_pairwise = WPA_CIPHER_CCMP;
+	} else {
+		bss->ssid.security_policy = SECURITY_PLAINTEXT;
+		if (full_config) {
+			bss->wpa_group = WPA_CIPHER_NONE;
+			bss->wpa_pairwise = WPA_CIPHER_NONE;
+			bss->rsn_pairwise = WPA_CIPHER_NONE;
+			bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
+		}
+	}
+}

+ 29 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_config.d

@@ -0,0 +1,29 @@
+../src/ap/ap_config.o: ../src/ap/ap_config.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/crypto/sha1.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius_client.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/eapol_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_common/eap_wsc_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_common/eap_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap_methods.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ ../src/ap/wpa_auth.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ ../src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/vlan.h ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h

+ 737 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_config.h

@@ -0,0 +1,737 @@
+/*
+ * hostapd / Configuration definitions and helpers functions
+ * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef HOSTAPD_CONFIG_H
+#define HOSTAPD_CONFIG_H
+
+#include "common/defs.h"
+#include "utils/list.h"
+#include "ip_addr.h"
+#include "common/wpa_common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "wps/wps.h"
+#include "fst/fst.h"
+#include "vlan.h"
+
+/**
+ * mesh_conf - local MBSS state and settings
+ */
+struct mesh_conf {
+	u8 meshid[32];
+	u8 meshid_len;
+	/* Active Path Selection Protocol Identifier */
+	u8 mesh_pp_id;
+	/* Active Path Selection Metric Identifier */
+	u8 mesh_pm_id;
+	/* Congestion Control Mode Identifier */
+	u8 mesh_cc_id;
+	/* Synchronization Protocol Identifier */
+	u8 mesh_sp_id;
+	/* Authentication Protocol Identifier */
+	u8 mesh_auth_id;
+	u8 *rsn_ie;
+	int rsn_ie_len;
+#define MESH_CONF_SEC_NONE BIT(0)
+#define MESH_CONF_SEC_AUTH BIT(1)
+#define MESH_CONF_SEC_AMPE BIT(2)
+	unsigned int security;
+	enum mfp_options ieee80211w;
+	unsigned int pairwise_cipher;
+	unsigned int group_cipher;
+	unsigned int mgmt_group_cipher;
+	int dot11MeshMaxRetries;
+	int dot11MeshRetryTimeout; /* msec */
+	int dot11MeshConfirmTimeout; /* msec */
+	int dot11MeshHoldingTimeout; /* msec */
+};
+
+#define MAX_STA_COUNT 2007
+#define MAX_VLAN_ID 4094
+
+typedef u8 macaddr[ETH_ALEN];
+
+struct mac_acl_entry {
+	macaddr addr;
+	struct vlan_description vlan_id;
+};
+
+struct hostapd_radius_servers;
+struct ft_remote_r0kh;
+struct ft_remote_r1kh;
+
+#define NUM_WEP_KEYS 4
+struct hostapd_wep_keys {
+	u8 idx;
+	u8 *key[NUM_WEP_KEYS];
+	size_t len[NUM_WEP_KEYS];
+	int keys_set;
+	size_t default_len; /* key length used for dynamic key generation */
+};
+
+typedef enum hostap_security_policy {
+	SECURITY_PLAINTEXT = 0,
+	SECURITY_STATIC_WEP = 1,
+	SECURITY_IEEE_802_1X = 2,
+	SECURITY_WPA_PSK = 3,
+	SECURITY_WPA = 4,
+	SECURITY_OSEN = 5
+} secpolicy;
+
+struct hostapd_ssid {
+	u8 ssid[SSID_MAX_LEN];
+	size_t ssid_len;
+	unsigned int ssid_set:1;
+	unsigned int utf8_ssid:1;
+	unsigned int wpa_passphrase_set:1;
+	unsigned int wpa_psk_set:1;
+
+	char vlan[IFNAMSIZ + 1];
+	secpolicy security_policy;
+
+	struct hostapd_wpa_psk *wpa_psk;
+	char *wpa_passphrase;
+	char *wpa_psk_file;
+
+	struct hostapd_wep_keys wep;
+
+#define DYNAMIC_VLAN_DISABLED 0
+#define DYNAMIC_VLAN_OPTIONAL 1
+#define DYNAMIC_VLAN_REQUIRED 2
+	int dynamic_vlan;
+#define DYNAMIC_VLAN_NAMING_WITHOUT_DEVICE 0
+#define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1
+#define DYNAMIC_VLAN_NAMING_END 2
+	int vlan_naming;
+	int per_sta_vif;
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+	char *vlan_tagged_interface;
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+};
+
+
+#define VLAN_ID_WILDCARD -1
+
+struct hostapd_vlan {
+	struct hostapd_vlan *next;
+	int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
+	struct vlan_description vlan_desc;
+	char ifname[IFNAMSIZ + 1];
+	int configured;
+	int dynamic_vlan;
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+
+#define DVLAN_CLEAN_WLAN_PORT	0x8
+	int clean;
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+};
+
+#define PMK_LEN 32
+#define MIN_PASSPHRASE_LEN 8
+#define MAX_PASSPHRASE_LEN 63
+struct hostapd_sta_wpa_psk_short {
+	struct hostapd_sta_wpa_psk_short *next;
+	unsigned int is_passphrase:1;
+	u8 psk[PMK_LEN];
+	char passphrase[MAX_PASSPHRASE_LEN + 1];
+	int ref; /* (number of references held) - 1 */
+};
+
+struct hostapd_wpa_psk {
+	struct hostapd_wpa_psk *next;
+	int group;
+	u8 psk[PMK_LEN];
+	u8 addr[ETH_ALEN];
+	u8 p2p_dev_addr[ETH_ALEN];
+};
+
+struct hostapd_eap_user {
+	struct hostapd_eap_user *next;
+	u8 *identity;
+	size_t identity_len;
+	struct {
+		int vendor;
+		u32 method;
+	} methods[EAP_MAX_METHODS];
+	u8 *password;
+	size_t password_len;
+	int phase2;
+	int force_version;
+	unsigned int wildcard_prefix:1;
+	unsigned int password_hash:1; /* whether password is hashed with
+				       * nt_password_hash() */
+	unsigned int remediation:1;
+	unsigned int macacl:1;
+	int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
+	struct hostapd_radius_attr *accept_attr;
+};
+
+struct hostapd_radius_attr {
+	u8 type;
+	struct wpabuf *val;
+	struct hostapd_radius_attr *next;
+};
+
+
+#define NUM_TX_QUEUES 4
+
+struct hostapd_tx_queue_params {
+	int aifs;
+	int cwmin;
+	int cwmax;
+	int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
+};
+
+
+#define MAX_ROAMING_CONSORTIUM_LEN 15
+
+struct hostapd_roaming_consortium {
+	u8 len;
+	u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
+};
+
+struct hostapd_lang_string {
+	u8 lang[3];
+	u8 name_len;
+	u8 name[252];
+};
+
+#define MAX_NAI_REALMS 10
+#define MAX_NAI_REALMLEN 255
+#define MAX_NAI_EAP_METHODS 5
+#define MAX_NAI_AUTH_TYPES 4
+struct hostapd_nai_realm_data {
+	u8 encoding;
+	char realm_buf[MAX_NAI_REALMLEN + 1];
+	char *realm[MAX_NAI_REALMS];
+	u8 eap_method_count;
+	struct hostapd_nai_realm_eap {
+		u8 eap_method;
+		u8 num_auths;
+		u8 auth_id[MAX_NAI_AUTH_TYPES];
+		u8 auth_val[MAX_NAI_AUTH_TYPES];
+	} eap_method[MAX_NAI_EAP_METHODS];
+};
+
+struct anqp_element {
+	struct dl_list list;
+	u16 infoid;
+	struct wpabuf *payload;
+};
+
+
+/**
+ * struct hostapd_bss_config - Per-BSS configuration
+ */
+struct hostapd_bss_config {
+	char iface[IFNAMSIZ + 1];
+	char bridge[IFNAMSIZ + 1];
+	char vlan_bridge[IFNAMSIZ + 1];
+	char wds_bridge[IFNAMSIZ + 1];
+
+	enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
+
+	unsigned int logger_syslog; /* module bitfield */
+	unsigned int logger_stdout; /* module bitfield */
+
+	int max_num_sta; /* maximum number of STAs in station table */
+
+	int dtim_period;
+	int bss_load_update_period;
+
+	int ieee802_1x; /* use IEEE 802.1X */
+	int eapol_version;
+	int eap_server; /* Use internal EAP server instead of external
+			 * RADIUS server */
+	struct hostapd_eap_user *eap_user;
+	char *eap_user_sqlite;
+	char *eap_sim_db;
+	unsigned int eap_sim_db_timeout;
+	int eap_server_erp; /* Whether ERP is enabled on internal EAP server */
+	struct hostapd_ip_addr own_ip_addr;
+	char *nas_identifier;
+	struct hostapd_radius_servers *radius;
+	int acct_interim_interval;
+	int radius_request_cui;
+	struct hostapd_radius_attr *radius_auth_req_attr;
+	struct hostapd_radius_attr *radius_acct_req_attr;
+	int radius_das_port;
+	unsigned int radius_das_time_window;
+	int radius_das_require_event_timestamp;
+	int radius_das_require_message_authenticator;
+	struct hostapd_ip_addr radius_das_client_addr;
+	u8 *radius_das_shared_secret;
+	size_t radius_das_shared_secret_len;
+
+	struct hostapd_ssid ssid;
+
+	char *eap_req_id_text; /* optional displayable message sent with
+				* EAP Request-Identity */
+	size_t eap_req_id_text_len;
+	int eapol_key_index_workaround;
+
+	size_t default_wep_key_len;
+	int individual_wep_key_len;
+	int wep_rekeying_period;
+	int broadcast_key_idx_min, broadcast_key_idx_max;
+	int eap_reauth_period;
+	int erp_send_reauth_start;
+	char *erp_domain;
+
+	int ieee802_11f; /* use IEEE 802.11f (IAPP) */
+	char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast
+					* frames */
+
+	enum {
+		ACCEPT_UNLESS_DENIED = 0,
+		DENY_UNLESS_ACCEPTED = 1,
+		USE_EXTERNAL_RADIUS_AUTH = 2
+	} macaddr_acl;
+	struct mac_acl_entry *accept_mac;
+	int num_accept_mac;
+	struct mac_acl_entry *deny_mac;
+	int num_deny_mac;
+	int wds_sta;
+	int isolate;
+	int start_disabled;
+
+	int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
+			* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
+
+	int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
+	int wpa_key_mgmt;
+#ifdef CONFIG_IEEE80211W
+	enum mfp_options ieee80211w;
+	int group_mgmt_cipher;
+	/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
+	unsigned int assoc_sa_query_max_timeout;
+	/* dot11AssociationSAQueryRetryTimeout (in TUs) */
+	int assoc_sa_query_retry_timeout;
+#endif /* CONFIG_IEEE80211W */
+	enum {
+		PSK_RADIUS_IGNORED = 0,
+		PSK_RADIUS_ACCEPTED = 1,
+		PSK_RADIUS_REQUIRED = 2
+	} wpa_psk_radius;
+	int wpa_pairwise;
+	int wpa_group;
+	int wpa_group_rekey;
+	int wpa_strict_rekey;
+	int wpa_gmk_rekey;
+	int wpa_ptk_rekey;
+	int rsn_pairwise;
+	int rsn_preauth;
+	char *rsn_preauth_interfaces;
+	int peerkey;
+
+#ifdef CONFIG_IEEE80211R
+	/* IEEE 802.11r - Fast BSS Transition */
+	u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
+	u8 r1_key_holder[FT_R1KH_ID_LEN];
+	u32 r0_key_lifetime;
+	u32 reassociation_deadline;
+	struct ft_remote_r0kh *r0kh_list;
+	struct ft_remote_r1kh *r1kh_list;
+	int pmk_r1_push;
+	int ft_over_ds;
+#endif /* CONFIG_IEEE80211R */
+
+	char *ctrl_interface; /* directory for UNIX domain sockets */
+#ifndef CONFIG_NATIVE_WINDOWS
+	gid_t ctrl_interface_gid;
+#endif /* CONFIG_NATIVE_WINDOWS */
+	int ctrl_interface_gid_set;
+
+	char *ca_cert;
+	char *server_cert;
+	char *private_key;
+	char *private_key_passwd;
+	int check_crl;
+	unsigned int tls_session_lifetime;
+	char *ocsp_stapling_response;
+	char *ocsp_stapling_response_multi;
+	char *dh_file;
+	char *openssl_ciphers;
+	u8 *pac_opaque_encr_key;
+	u8 *eap_fast_a_id;
+	size_t eap_fast_a_id_len;
+	char *eap_fast_a_id_info;
+	int eap_fast_prov;
+	int pac_key_lifetime;
+	int pac_key_refresh_time;
+	int eap_sim_aka_result_ind;
+	int tnc;
+	int fragment_size;
+	u16 pwd_group;
+
+	char *radius_server_clients;
+	int radius_server_auth_port;
+	int radius_server_acct_port;
+	int radius_server_ipv6;
+
+	int use_pae_group_addr; /* Whether to send EAPOL frames to PAE group
+				 * address instead of individual address
+				 * (for driver_wired.c).
+				 */
+
+	int ap_max_inactivity;
+	int ignore_broadcast_ssid;
+	int no_probe_resp_if_max_sta;
+
+	int wmm_enabled;
+	int wmm_uapsd;
+
+	struct hostapd_vlan *vlan;
+
+	macaddr bssid;
+
+	/*
+	 * Maximum listen interval that STAs can use when associating with this
+	 * BSS. If a STA tries to use larger value, the association will be
+	 * denied with status code 51.
+	 */
+	u16 max_listen_interval;
+
+	int disable_pmksa_caching;
+	int okc; /* Opportunistic Key Caching */
+
+	int wps_state;
+#ifdef CONFIG_WPS
+	int wps_independent;
+	int ap_setup_locked;
+	u8 uuid[16];
+	char *wps_pin_requests;
+	char *device_name;
+	char *manufacturer;
+	char *model_name;
+	char *model_number;
+	char *serial_number;
+	u8 device_type[WPS_DEV_TYPE_LEN];
+	char *config_methods;
+	u8 os_version[4];
+	char *ap_pin;
+	int skip_cred_build;
+	u8 *extra_cred;
+	size_t extra_cred_len;
+	int wps_cred_processing;
+	int force_per_enrollee_psk;
+	u8 *ap_settings;
+	size_t ap_settings_len;
+	char *upnp_iface;
+	char *friendly_name;
+	char *manufacturer_url;
+	char *model_description;
+	char *model_url;
+	char *upc;
+	struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
+	int wps_nfc_pw_from_config;
+	int wps_nfc_dev_pw_id;
+	struct wpabuf *wps_nfc_dh_pubkey;
+	struct wpabuf *wps_nfc_dh_privkey;
+	struct wpabuf *wps_nfc_dev_pw;
+#endif /* CONFIG_WPS */
+	int pbc_in_m1;
+	char *server_id;
+
+#define P2P_ENABLED BIT(0)
+#define P2P_GROUP_OWNER BIT(1)
+#define P2P_GROUP_FORMATION BIT(2)
+#define P2P_MANAGE BIT(3)
+#define P2P_ALLOW_CROSS_CONNECTION BIT(4)
+	int p2p;
+#ifdef CONFIG_P2P
+	u8 ip_addr_go[4];
+	u8 ip_addr_mask[4];
+	u8 ip_addr_start[4];
+	u8 ip_addr_end[4];
+#endif /* CONFIG_P2P */
+
+	int disassoc_low_ack;
+	int skip_inactivity_poll;
+
+#define TDLS_PROHIBIT BIT(0)
+#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1)
+	int tdls;
+	int disable_11n;
+	int disable_11ac;
+
+	/* IEEE 802.11v */
+	int time_advertisement;
+	char *time_zone;
+	int wnm_sleep_mode;
+	int bss_transition;
+
+	/* IEEE 802.11u - Interworking */
+	int interworking;
+	int access_network_type;
+	int internet;
+	int asra;
+	int esr;
+	int uesa;
+	int venue_info_set;
+	u8 venue_group;
+	u8 venue_type;
+	u8 hessid[ETH_ALEN];
+
+	/* IEEE 802.11u - Roaming Consortium list */
+	unsigned int roaming_consortium_count;
+	struct hostapd_roaming_consortium *roaming_consortium;
+
+	/* IEEE 802.11u - Venue Name duples */
+	unsigned int venue_name_count;
+	struct hostapd_lang_string *venue_name;
+
+	/* IEEE 802.11u - Network Authentication Type */
+	u8 *network_auth_type;
+	size_t network_auth_type_len;
+
+	/* IEEE 802.11u - IP Address Type Availability */
+	u8 ipaddr_type_availability;
+	u8 ipaddr_type_configured;
+
+	/* IEEE 802.11u - 3GPP Cellular Network */
+	u8 *anqp_3gpp_cell_net;
+	size_t anqp_3gpp_cell_net_len;
+
+	/* IEEE 802.11u - Domain Name */
+	u8 *domain_name;
+	size_t domain_name_len;
+
+	unsigned int nai_realm_count;
+	struct hostapd_nai_realm_data *nai_realm_data;
+
+	struct dl_list anqp_elem; /* list of struct anqp_element */
+
+	u16 gas_comeback_delay;
+	int gas_frag_limit;
+	int gas_address3;
+
+	u8 qos_map_set[16 + 2 * 21];
+	unsigned int qos_map_set_len;
+
+	int osen;
+	int proxy_arp;
+	int na_mcast_to_ucast;
+#ifdef CONFIG_HS20
+	int hs20;
+	int disable_dgaf;
+	u16 anqp_domain_id;
+	unsigned int hs20_oper_friendly_name_count;
+	struct hostapd_lang_string *hs20_oper_friendly_name;
+	u8 *hs20_wan_metrics;
+	u8 *hs20_connection_capability;
+	size_t hs20_connection_capability_len;
+	u8 *hs20_operating_class;
+	u8 hs20_operating_class_len;
+	struct hs20_icon {
+		u16 width;
+		u16 height;
+		char language[3];
+		char type[256];
+		char name[256];
+		char file[256];
+	} *hs20_icons;
+	size_t hs20_icons_count;
+	u8 osu_ssid[SSID_MAX_LEN];
+	size_t osu_ssid_len;
+	struct hs20_osu_provider {
+		unsigned int friendly_name_count;
+		struct hostapd_lang_string *friendly_name;
+		char *server_uri;
+		int *method_list;
+		char **icons;
+		size_t icons_count;
+		char *osu_nai;
+		unsigned int service_desc_count;
+		struct hostapd_lang_string *service_desc;
+	} *hs20_osu_providers, *last_osu;
+	size_t hs20_osu_providers_count;
+	unsigned int hs20_deauth_req_timeout;
+	char *subscr_remediation_url;
+	u8 subscr_remediation_method;
+#endif /* CONFIG_HS20 */
+
+	u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */
+
+#ifdef CONFIG_RADIUS_TEST
+	char *dump_msk_file;
+#endif /* CONFIG_RADIUS_TEST */
+
+	struct wpabuf *vendor_elements;
+	struct wpabuf *assocresp_elements;
+
+	unsigned int sae_anti_clogging_threshold;
+	int *sae_groups;
+
+	char *wowlan_triggers; /* Wake-on-WLAN triggers */
+
+#ifdef CONFIG_TESTING_OPTIONS
+	u8 bss_load_test[5];
+	u8 bss_load_test_set;
+	struct wpabuf *own_ie_override;
+#endif /* CONFIG_TESTING_OPTIONS */
+
+#define MESH_ENABLED BIT(0)
+	int mesh;
+
+	u8 radio_measurements[RRM_CAPABILITIES_IE_LEN];
+
+	int vendor_vht;
+	int use_sta_nsts;
+
+	char *no_probe_resp_if_seen_on;
+	char *no_auth_if_seen_on;
+
+	int pbss;
+
+#ifdef CONFIG_MBO
+	int mbo_enabled;
+#endif /* CONFIG_MBO */
+
+	int ftm_responder;
+	int ftm_initiator;
+};
+
+
+/**
+ * struct hostapd_config - Per-radio interface configuration
+ */
+struct hostapd_config {
+	struct hostapd_bss_config **bss, *last_bss;
+	size_t num_bss;
+
+	u16 beacon_int;
+	int rts_threshold;
+	int fragm_threshold;
+	u8 send_probe_response;
+	u8 channel;
+	u8 acs;
+	struct wpa_freq_range_list acs_ch_list;
+	enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
+	enum {
+		LONG_PREAMBLE = 0,
+		SHORT_PREAMBLE = 1
+	} preamble;
+
+	int *supported_rates;
+	int *basic_rates;
+
+	const struct wpa_driver_ops *driver;
+	char *driver_params;
+
+	int ap_table_max_size;
+	int ap_table_expiration_time;
+
+	unsigned int track_sta_max_num;
+	unsigned int track_sta_max_age;
+
+	char country[3]; /* first two octets: country code as described in
+			  * ISO/IEC 3166-1. Third octet:
+			  * ' ' (ascii 32): all environments
+			  * 'O': Outdoor environemnt only
+			  * 'I': Indoor environment only
+			  */
+
+	int ieee80211d;
+
+	int ieee80211h; /* DFS */
+
+	/*
+	 * Local power constraint is an octet encoded as an unsigned integer in
+	 * units of decibels. Invalid value -1 indicates that Power Constraint
+	 * element will not be added.
+	 */
+	int local_pwr_constraint;
+
+	/* Control Spectrum Management bit */
+	int spectrum_mgmt_required;
+
+	struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES];
+
+	/*
+	 * WMM AC parameters, in same order as 802.1D, i.e.
+	 * 0 = BE (best effort)
+	 * 1 = BK (background)
+	 * 2 = VI (video)
+	 * 3 = VO (voice)
+	 */
+	struct hostapd_wmm_ac_params wmm_ac_params[4];
+
+	int ht_op_mode_fixed;
+	u16 ht_capab;
+	int ieee80211n;
+	int secondary_channel;
+	int no_pri_sec_switch;
+	int require_ht;
+	int obss_interval;
+	u32 vht_capab;
+	int ieee80211ac;
+	int require_vht;
+	u8 vht_oper_chwidth;
+	u8 vht_oper_centr_freq_seg0_idx;
+	u8 vht_oper_centr_freq_seg1_idx;
+
+	/* Use driver-generated interface addresses when adding multiple BSSs */
+	u8 use_driver_iface_addr;
+
+#ifdef CONFIG_FST
+	struct fst_iface_cfg fst_cfg;
+#endif /* CONFIG_FST */
+
+#ifdef CONFIG_P2P
+	u8 p2p_go_ctwindow;
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_TESTING_OPTIONS
+	double ignore_probe_probability;
+	double ignore_auth_probability;
+	double ignore_assoc_probability;
+	double ignore_reassoc_probability;
+	double corrupt_gtk_rekey_mic_probability;
+	int ecsa_ie_only;
+#endif /* CONFIG_TESTING_OPTIONS */
+
+#ifdef CONFIG_ACS
+	unsigned int acs_num_scans;
+	struct acs_bias {
+		int channel;
+		double bias;
+	} *acs_chan_bias;
+	unsigned int num_acs_chan_bias;
+#endif /* CONFIG_ACS */
+
+	struct wpabuf *lci;
+	struct wpabuf *civic;
+};
+
+
+int hostapd_mac_comp(const void *a, const void *b);
+struct hostapd_config * hostapd_config_defaults(void);
+void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
+void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
+void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p);
+void hostapd_config_free_bss(struct hostapd_bss_config *conf);
+void hostapd_config_free(struct hostapd_config *conf);
+int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
+			  const u8 *addr, struct vlan_description *vlan_id);
+int hostapd_rate_found(int *list, int rate);
+const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
+			   const u8 *addr, const u8 *p2p_dev_addr,
+			   const u8 *prev_psk);
+int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
+int hostapd_vlan_valid(struct hostapd_vlan *vlan,
+		       struct vlan_description *vlan_desc);
+const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan,
+					int vlan_id);
+struct hostapd_radius_attr *
+hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type);
+int hostapd_config_check(struct hostapd_config *conf, int full_config);
+void hostapd_set_security_params(struct hostapd_bss_config *bss,
+				 int full_config);
+
+#endif /* HOSTAPD_CONFIG_H */

+ 874 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_drv_ops.c

@@ -0,0 +1,874 @@
+/*
+ * hostapd - Driver operations
+ * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/hw_features_common.h"
+#include "wps/wps.h"
+#include "p2p/p2p.h"
+#include "hostapd.h"
+#include "ieee802_11.h"
+#include "sta_info.h"
+#include "ap_config.h"
+#include "p2p_hostapd.h"
+#include "hs20.h"
+#include "ap_drv_ops.h"
+
+
+u32 hostapd_sta_flags_to_drv(u32 flags)
+{
+	int res = 0;
+	if (flags & WLAN_STA_AUTHORIZED)
+		res |= WPA_STA_AUTHORIZED;
+	if (flags & WLAN_STA_WMM)
+		res |= WPA_STA_WMM;
+	if (flags & WLAN_STA_SHORT_PREAMBLE)
+		res |= WPA_STA_SHORT_PREAMBLE;
+	if (flags & WLAN_STA_MFP)
+		res |= WPA_STA_MFP;
+	if (flags & WLAN_STA_AUTH)
+		res |= WPA_STA_AUTHENTICATED;
+	if (flags & WLAN_STA_ASSOC)
+		res |= WPA_STA_ASSOCIATED;
+	return res;
+}
+
+
+static int add_buf(struct wpabuf **dst, const struct wpabuf *src)
+{
+	if (!src)
+		return 0;
+	if (wpabuf_resize(dst, wpabuf_len(src)) != 0)
+		return -1;
+	wpabuf_put_buf(*dst, src);
+	return 0;
+}
+
+
+static int add_buf_data(struct wpabuf **dst, const u8 *data, size_t len)
+{
+	if (!data || !len)
+		return 0;
+	if (wpabuf_resize(dst, len) != 0)
+		return -1;
+	wpabuf_put_data(*dst, data, len);
+	return 0;
+}
+
+
+int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
+			       struct wpabuf **beacon_ret,
+			       struct wpabuf **proberesp_ret,
+			       struct wpabuf **assocresp_ret)
+{
+	struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL;
+	u8 buf[200], *pos;
+
+	*beacon_ret = *proberesp_ret = *assocresp_ret = NULL;
+
+	pos = buf;
+	pos = hostapd_eid_time_adv(hapd, pos);
+	if (add_buf_data(&beacon, buf, pos - buf) < 0)
+		goto fail;
+	pos = hostapd_eid_time_zone(hapd, pos);
+	if (add_buf_data(&proberesp, buf, pos - buf) < 0)
+		goto fail;
+
+	pos = buf;
+	pos = hostapd_eid_ext_capab(hapd, pos);
+	if (add_buf_data(&assocresp, buf, pos - buf) < 0)
+		goto fail;
+	pos = hostapd_eid_interworking(hapd, pos);
+	pos = hostapd_eid_adv_proto(hapd, pos);
+	pos = hostapd_eid_roaming_consortium(hapd, pos);
+	if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+	    add_buf_data(&proberesp, buf, pos - buf) < 0)
+		goto fail;
+
+#ifdef CONFIG_FST
+	if (add_buf(&beacon, hapd->iface->fst_ies) < 0 ||
+	    add_buf(&proberesp, hapd->iface->fst_ies) < 0 ||
+	    add_buf(&assocresp, hapd->iface->fst_ies) < 0)
+		goto fail;
+#endif /* CONFIG_FST */
+
+	if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 ||
+	    add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0)
+		goto fail;
+
+#ifdef CONFIG_P2P
+	if (add_buf(&beacon, hapd->p2p_beacon_ie) < 0 ||
+	    add_buf(&proberesp, hapd->p2p_probe_resp_ie) < 0)
+		goto fail;
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_P2P_MANAGER
+	if (hapd->conf->p2p & P2P_MANAGE) {
+		if (wpabuf_resize(&beacon, 100) == 0) {
+			u8 *start, *p;
+			start = wpabuf_put(beacon, 0);
+			p = hostapd_eid_p2p_manage(hapd, start);
+			wpabuf_put(beacon, p - start);
+		}
+
+		if (wpabuf_resize(&proberesp, 100) == 0) {
+			u8 *start, *p;
+			start = wpabuf_put(proberesp, 0);
+			p = hostapd_eid_p2p_manage(hapd, start);
+			wpabuf_put(proberesp, p - start);
+		}
+	}
+#endif /* CONFIG_P2P_MANAGER */
+
+#ifdef CONFIG_WPS
+	if (hapd->conf->wps_state) {
+		struct wpabuf *a = wps_build_assoc_resp_ie();
+		add_buf(&assocresp, a);
+		wpabuf_free(a);
+	}
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_P2P_MANAGER
+	if (hapd->conf->p2p & P2P_MANAGE) {
+		if (wpabuf_resize(&assocresp, 100) == 0) {
+			u8 *start, *p;
+			start = wpabuf_put(assocresp, 0);
+			p = hostapd_eid_p2p_manage(hapd, start);
+			wpabuf_put(assocresp, p - start);
+		}
+	}
+#endif /* CONFIG_P2P_MANAGER */
+
+#ifdef CONFIG_WIFI_DISPLAY
+	if (hapd->p2p_group) {
+		struct wpabuf *a;
+		a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS);
+		add_buf(&assocresp, a);
+		wpabuf_free(a);
+	}
+#endif /* CONFIG_WIFI_DISPLAY */
+
+#ifdef CONFIG_HS20
+	pos = hostapd_eid_hs20_indication(hapd, buf);
+	if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+	    add_buf_data(&proberesp, buf, pos - buf) < 0)
+		goto fail;
+
+	pos = hostapd_eid_osen(hapd, buf);
+	if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+	    add_buf_data(&proberesp, buf, pos - buf) < 0)
+		goto fail;
+#endif /* CONFIG_HS20 */
+
+#ifdef CONFIG_MBO
+	if (hapd->conf->mbo_enabled) {
+		pos = hostapd_eid_mbo(hapd, buf, sizeof(buf));
+		if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
+		    add_buf_data(&proberesp, buf, pos - buf) < 0 ||
+		    add_buf_data(&assocresp, buf, pos - buf) < 0)
+			goto fail;
+	}
+#endif /* CONFIG_MBO */
+
+	add_buf(&beacon, hapd->conf->vendor_elements);
+	add_buf(&proberesp, hapd->conf->vendor_elements);
+	add_buf(&assocresp, hapd->conf->assocresp_elements);
+
+	*beacon_ret = beacon;
+	*proberesp_ret = proberesp;
+	*assocresp_ret = assocresp;
+
+	return 0;
+
+fail:
+	wpabuf_free(beacon);
+	wpabuf_free(proberesp);
+	wpabuf_free(assocresp);
+	return -1;
+}
+
+
+void hostapd_free_ap_extra_ies(struct hostapd_data *hapd,
+			       struct wpabuf *beacon,
+			       struct wpabuf *proberesp,
+			       struct wpabuf *assocresp)
+{
+	wpabuf_free(beacon);
+	wpabuf_free(proberesp);
+	wpabuf_free(assocresp);
+}
+
+
+int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd)
+{
+	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
+		return 0;
+
+	return hapd->driver->set_ap_wps_ie(hapd->drv_priv, NULL, NULL, NULL);
+}
+
+
+int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
+{
+	struct wpabuf *beacon, *proberesp, *assocresp;
+	int ret;
+
+	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
+		return 0;
+
+	if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
+	    0)
+		return -1;
+
+	ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
+					  assocresp);
+
+	hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
+
+	return ret;
+}
+
+
+int hostapd_set_authorized(struct hostapd_data *hapd,
+			   struct sta_info *sta, int authorized)
+{
+	if (authorized) {
+		return hostapd_sta_set_flags(hapd, sta->addr,
+					     hostapd_sta_flags_to_drv(
+						     sta->flags),
+					     WPA_STA_AUTHORIZED, ~0);
+	}
+
+	return hostapd_sta_set_flags(hapd, sta->addr,
+				     hostapd_sta_flags_to_drv(sta->flags),
+				     0, ~WPA_STA_AUTHORIZED);
+}
+
+
+int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	int set_flags, total_flags, flags_and, flags_or;
+	total_flags = hostapd_sta_flags_to_drv(sta->flags);
+	set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP;
+	if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) ||
+	     sta->auth_alg == WLAN_AUTH_FT) &&
+	    sta->flags & WLAN_STA_AUTHORIZED)
+		set_flags |= WPA_STA_AUTHORIZED;
+	flags_or = total_flags & set_flags;
+	flags_and = total_flags | ~set_flags;
+	return hostapd_sta_set_flags(hapd, sta->addr, total_flags,
+				     flags_or, flags_and);
+}
+
+
+int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
+			      int enabled)
+{
+	struct wpa_bss_params params;
+	os_memset(&params, 0, sizeof(params));
+	params.ifname = ifname;
+	params.enabled = enabled;
+	if (enabled) {
+		params.wpa = hapd->conf->wpa;
+		params.ieee802_1x = hapd->conf->ieee802_1x;
+		params.wpa_group = hapd->conf->wpa_group;
+		if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) ==
+		    (WPA_PROTO_WPA | WPA_PROTO_RSN))
+			params.wpa_pairwise = hapd->conf->wpa_pairwise |
+				hapd->conf->rsn_pairwise;
+		else if (hapd->conf->wpa & WPA_PROTO_RSN)
+			params.wpa_pairwise = hapd->conf->rsn_pairwise;
+		else if (hapd->conf->wpa & WPA_PROTO_WPA)
+			params.wpa_pairwise = hapd->conf->wpa_pairwise;
+		params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
+		params.rsn_preauth = hapd->conf->rsn_preauth;
+#ifdef CONFIG_IEEE80211W
+		params.ieee80211w = hapd->conf->ieee80211w;
+#endif /* CONFIG_IEEE80211W */
+	}
+	return hostapd_set_ieee8021x(hapd, &params);
+}
+
+
+int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
+{
+	char force_ifname[IFNAMSIZ];
+	u8 if_addr[ETH_ALEN];
+	return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr,
+			      NULL, NULL, force_ifname, if_addr, NULL, 0);
+}
+
+
+int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname)
+{
+	return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname);
+}
+
+
+int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
+			const u8 *addr, int aid, int val)
+{
+	const char *bridge = NULL;
+
+	if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL)
+		return -1;
+	if (hapd->conf->wds_bridge[0])
+		bridge = hapd->conf->wds_bridge;
+	else if (hapd->conf->bridge[0])
+		bridge = hapd->conf->bridge;
+	return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
+					 bridge, ifname_wds);
+}
+
+
+int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
+			 u16 auth_alg)
+{
+	if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL)
+		return 0;
+	return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg);
+}
+
+
+int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
+		     u16 seq, u16 status, const u8 *ie, size_t len)
+{
+	if (hapd->driver == NULL || hapd->driver->sta_auth == NULL)
+		return 0;
+	return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr,
+				      seq, status, ie, len);
+}
+
+
+int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
+		      int reassoc, u16 status, const u8 *ie, size_t len)
+{
+	if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL)
+		return 0;
+	return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr,
+				       reassoc, status, ie, len);
+}
+
+
+int hostapd_sta_add(struct hostapd_data *hapd,
+		    const u8 *addr, u16 aid, u16 capability,
+		    const u8 *supp_rates, size_t supp_rates_len,
+		    u16 listen_interval,
+		    const struct ieee80211_ht_capabilities *ht_capab,
+		    const struct ieee80211_vht_capabilities *vht_capab,
+		    u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
+		    int set)
+{
+	struct hostapd_sta_add_params params;
+
+	if (hapd->driver == NULL)
+		return 0;
+	if (hapd->driver->sta_add == NULL)
+		return 0;
+
+	os_memset(&params, 0, sizeof(params));
+	params.addr = addr;
+	params.aid = aid;
+	params.capability = capability;
+	params.supp_rates = supp_rates;
+	params.supp_rates_len = supp_rates_len;
+	params.listen_interval = listen_interval;
+	params.ht_capabilities = ht_capab;
+	params.vht_capabilities = vht_capab;
+	params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED);
+	params.vht_opmode = vht_opmode;
+	params.flags = hostapd_sta_flags_to_drv(flags);
+	params.qosinfo = qosinfo;
+	params.support_p2p_ps = supp_p2p_ps;
+	params.set = set;
+	return hapd->driver->sta_add(hapd->drv_priv, &params);
+}
+
+
+int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
+		      u8 *tspec_ie, size_t tspec_ielen)
+{
+	if (hapd->driver == NULL || hapd->driver->add_tspec == NULL)
+		return 0;
+	return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie,
+				       tspec_ielen);
+}
+
+
+int hostapd_set_privacy(struct hostapd_data *hapd, int enabled)
+{
+	if (hapd->driver == NULL || hapd->driver->set_privacy == NULL)
+		return 0;
+	return hapd->driver->set_privacy(hapd->drv_priv, enabled);
+}
+
+
+int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
+			     size_t elem_len)
+{
+	if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL)
+		return 0;
+	return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len);
+}
+
+
+int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len)
+{
+	if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL)
+		return 0;
+	return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len);
+}
+
+
+int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
+{
+	if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL)
+		return 0;
+	return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len);
+}
+
+
+int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
+		   const char *ifname, const u8 *addr, void *bss_ctx,
+		   void **drv_priv, char *force_ifname, u8 *if_addr,
+		   const char *bridge, int use_existing)
+{
+	if (hapd->driver == NULL || hapd->driver->if_add == NULL)
+		return -1;
+	return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
+				    bss_ctx, drv_priv, force_ifname, if_addr,
+				    bridge, use_existing, 1);
+}
+
+
+int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
+		      const char *ifname)
+{
+	if (hapd->driver == NULL || hapd->drv_priv == NULL ||
+	    hapd->driver->if_remove == NULL)
+		return -1;
+	return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
+}
+
+
+int hostapd_set_ieee8021x(struct hostapd_data *hapd,
+			  struct wpa_bss_params *params)
+{
+	if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL)
+		return 0;
+	return hapd->driver->set_ieee8021x(hapd->drv_priv, params);
+}
+
+
+int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
+		       const u8 *addr, int idx, u8 *seq)
+{
+	if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL)
+		return 0;
+	return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx,
+					seq);
+}
+
+
+int hostapd_flush(struct hostapd_data *hapd)
+{
+	if (hapd->driver == NULL || hapd->driver->flush == NULL)
+		return 0;
+	return hapd->driver->flush(hapd->drv_priv);
+}
+
+
+int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
+		     int freq, int channel, int ht_enabled, int vht_enabled,
+		     int sec_channel_offset, int vht_oper_chwidth,
+		     int center_segment0, int center_segment1)
+{
+	struct hostapd_freq_params data;
+
+	if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
+				    vht_enabled, sec_channel_offset,
+				    vht_oper_chwidth,
+				    center_segment0, center_segment1,
+				    hapd->iface->current_mode ?
+				    hapd->iface->current_mode->vht_capab : 0))
+		return -1;
+
+	if (hapd->driver == NULL)
+		return 0;
+	if (hapd->driver->set_freq == NULL)
+		return 0;
+	return hapd->driver->set_freq(hapd->drv_priv, &data);
+}
+
+int hostapd_set_rts(struct hostapd_data *hapd, int rts)
+{
+	if (hapd->driver == NULL || hapd->driver->set_rts == NULL)
+		return 0;
+	return hapd->driver->set_rts(hapd->drv_priv, rts);
+}
+
+
+int hostapd_set_frag(struct hostapd_data *hapd, int frag)
+{
+	if (hapd->driver == NULL || hapd->driver->set_frag == NULL)
+		return 0;
+	return hapd->driver->set_frag(hapd->drv_priv, frag);
+}
+
+
+int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
+			  int total_flags, int flags_or, int flags_and)
+{
+	if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL)
+		return 0;
+	return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags,
+					   flags_or, flags_and);
+}
+
+
+int hostapd_set_country(struct hostapd_data *hapd, const char *country)
+{
+	if (hapd->driver == NULL ||
+	    hapd->driver->set_country == NULL)
+		return 0;
+	return hapd->driver->set_country(hapd->drv_priv, country);
+}
+
+
+int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
+				int cw_min, int cw_max, int burst_time)
+{
+	if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL)
+		return 0;
+	return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs,
+						 cw_min, cw_max, burst_time);
+}
+
+
+struct hostapd_hw_modes *
+hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
+			    u16 *flags)
+{
+	if (hapd->driver == NULL ||
+	    hapd->driver->get_hw_feature_data == NULL)
+		return NULL;
+	return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
+						 flags);
+}
+
+
+int hostapd_driver_commit(struct hostapd_data *hapd)
+{
+	if (hapd->driver == NULL || hapd->driver->commit == NULL)
+		return 0;
+	return hapd->driver->commit(hapd->drv_priv);
+}
+
+
+int hostapd_drv_none(struct hostapd_data *hapd)
+{
+	return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0;
+}
+
+
+int hostapd_driver_scan(struct hostapd_data *hapd,
+			struct wpa_driver_scan_params *params)
+{
+	if (hapd->driver && hapd->driver->scan2)
+		return hapd->driver->scan2(hapd->drv_priv, params);
+	return -1;
+}
+
+
+struct wpa_scan_results * hostapd_driver_get_scan_results(
+	struct hostapd_data *hapd)
+{
+	if (hapd->driver && hapd->driver->get_scan_results2)
+		return hapd->driver->get_scan_results2(hapd->drv_priv);
+	return NULL;
+}
+
+
+int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
+			   int duration)
+{
+	if (hapd->driver && hapd->driver->set_noa)
+		return hapd->driver->set_noa(hapd->drv_priv, count, start,
+					     duration);
+	return -1;
+}
+
+
+int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
+			enum wpa_alg alg, const u8 *addr,
+			int key_idx, int set_tx,
+			const u8 *seq, size_t seq_len,
+			const u8 *key, size_t key_len)
+{
+	if (hapd->driver == NULL || hapd->driver->set_key == NULL)
+		return 0;
+	return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
+				     key_idx, set_tx, seq, seq_len, key,
+				     key_len);
+}
+
+
+int hostapd_drv_send_mlme(struct hostapd_data *hapd,
+			  const void *msg, size_t len, int noack)
+{
+	if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv)
+		return 0;
+	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
+				       NULL, 0);
+}
+
+
+int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
+			      const void *msg, size_t len, int noack,
+			      const u16 *csa_offs, size_t csa_offs_len)
+{
+	if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
+		return 0;
+	return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0,
+				       csa_offs, csa_offs_len);
+}
+
+
+int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
+			   const u8 *addr, int reason)
+{
+	if (!hapd->driver || !hapd->driver->sta_deauth || !hapd->drv_priv)
+		return 0;
+	return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr,
+					reason);
+}
+
+
+int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
+			     const u8 *addr, int reason)
+{
+	if (!hapd->driver || !hapd->driver->sta_disassoc || !hapd->drv_priv)
+		return 0;
+	return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr,
+					  reason);
+}
+
+
+int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper,
+			 const u8 *peer, u8 *buf, u16 *buf_len)
+{
+	if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL)
+		return -1;
+	return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf,
+				      buf_len);
+}
+
+
+int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
+			    unsigned int wait, const u8 *dst, const u8 *data,
+			    size_t len)
+{
+	const u8 *bssid;
+	const u8 wildcard_bssid[ETH_ALEN] = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	};
+
+	if (!hapd->driver || !hapd->driver->send_action || !hapd->drv_priv)
+		return 0;
+	bssid = hapd->own_addr;
+	if (!is_multicast_ether_addr(dst) &&
+	    len > 0 && data[0] == WLAN_ACTION_PUBLIC) {
+		struct sta_info *sta;
+
+		/*
+		 * Public Action frames to a STA that is not a member of the BSS
+		 * shall use wildcard BSSID value.
+		 */
+		sta = ap_get_sta(hapd, dst);
+		if (!sta || !(sta->flags & WLAN_STA_ASSOC))
+			bssid = wildcard_bssid;
+	}
+	return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
+					 hapd->own_addr, bssid, data, len, 0);
+}
+
+
+int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
+				     unsigned int freq,
+				     unsigned int wait, const u8 *dst,
+				     const u8 *data, size_t len)
+{
+	if (hapd->driver == NULL || hapd->driver->send_action == NULL)
+		return 0;
+	return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst,
+					 hapd->own_addr, hapd->own_addr, data,
+					 len, 0);
+}
+
+
+int hostapd_start_dfs_cac(struct hostapd_iface *iface,
+			  enum hostapd_hw_mode mode, int freq,
+			  int channel, int ht_enabled, int vht_enabled,
+			  int sec_channel_offset, int vht_oper_chwidth,
+			  int center_segment0, int center_segment1)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+	struct hostapd_freq_params data;
+	int res;
+
+	if (!hapd->driver || !hapd->driver->start_dfs_cac)
+		return 0;
+
+	if (!iface->conf->ieee80211h) {
+		wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality "
+			   "is not enabled");
+		return -1;
+	}
+
+	if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled,
+				    vht_enabled, sec_channel_offset,
+				    vht_oper_chwidth, center_segment0,
+				    center_segment1,
+				    iface->current_mode->vht_capab)) {
+		wpa_printf(MSG_ERROR, "Can't set freq params");
+		return -1;
+	}
+
+	res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
+	if (!res) {
+		iface->cac_started = 1;
+		os_get_reltime(&iface->dfs_cac_start);
+	}
+
+	return res;
+}
+
+
+int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
+			    const u8 *qos_map_set, u8 qos_map_set_len)
+{
+	if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv)
+		return 0;
+	return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
+					 qos_map_set_len);
+}
+
+
+static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
+					     struct hostapd_hw_modes *mode,
+					     int acs_ch_list_all,
+					     int **freq_list)
+{
+	int i;
+
+	for (i = 0; i < mode->num_channels; i++) {
+		struct hostapd_channel_data *chan = &mode->channels[i];
+
+		if ((acs_ch_list_all ||
+		     freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
+					      chan->chan)) &&
+		    !(chan->flag & HOSTAPD_CHAN_DISABLED))
+			int_array_add_unique(freq_list, chan->freq);
+	}
+}
+
+
+void hostapd_get_ext_capa(struct hostapd_iface *iface)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+
+	if (!hapd->driver || !hapd->driver->get_ext_capab)
+		return;
+
+	hapd->driver->get_ext_capab(hapd->drv_priv, WPA_IF_AP_BSS,
+				    &iface->extended_capa,
+				    &iface->extended_capa_mask,
+				    &iface->extended_capa_len);
+}
+
+
+int hostapd_drv_do_acs(struct hostapd_data *hapd)
+{
+	struct drv_acs_params params;
+	int ret, i, acs_ch_list_all = 0;
+	u8 *channels = NULL;
+	unsigned int num_channels = 0;
+	struct hostapd_hw_modes *mode;
+	int *freq_list = NULL;
+
+	if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
+		return 0;
+
+	os_memset(&params, 0, sizeof(params));
+	params.hw_mode = hapd->iface->conf->hw_mode;
+
+	/*
+	 * If no chanlist config parameter is provided, include all enabled
+	 * channels of the selected hw_mode.
+	 */
+	if (!hapd->iface->conf->acs_ch_list.num)
+		acs_ch_list_all = 1;
+
+	mode = hapd->iface->current_mode;
+	if (mode) {
+		channels = os_malloc(mode->num_channels);
+		if (channels == NULL)
+			return -1;
+
+		for (i = 0; i < mode->num_channels; i++) {
+			struct hostapd_channel_data *chan = &mode->channels[i];
+			if (!acs_ch_list_all &&
+			    !freq_range_list_includes(
+				    &hapd->iface->conf->acs_ch_list,
+				    chan->chan))
+				continue;
+			if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) {
+				channels[num_channels++] = chan->chan;
+				int_array_add_unique(&freq_list, chan->freq);
+			}
+		}
+	} else {
+		for (i = 0; i < hapd->iface->num_hw_features; i++) {
+			mode = &hapd->iface->hw_features[i];
+			hostapd_get_hw_mode_any_channels(hapd, mode,
+							 acs_ch_list_all,
+							 &freq_list);
+		}
+	}
+
+	params.ch_list = channels;
+	params.ch_list_len = num_channels;
+	params.freq_list = freq_list;
+
+	params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
+	params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
+				 HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
+	params.vht_enabled = !!(hapd->iface->conf->ieee80211ac);
+	params.ch_width = 20;
+	if (hapd->iface->conf->ieee80211n && params.ht40_enabled)
+		params.ch_width = 40;
+
+	/* Note: VHT20 is defined by combination of ht_capab & vht_oper_chwidth
+	 */
+	if (hapd->iface->conf->ieee80211ac && params.ht40_enabled) {
+		if (hapd->iface->conf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
+			params.ch_width = 80;
+		else if (hapd->iface->conf->vht_oper_chwidth ==
+			 VHT_CHANWIDTH_160MHZ ||
+			 hapd->iface->conf->vht_oper_chwidth ==
+			 VHT_CHANWIDTH_80P80MHZ)
+			params.ch_width = 160;
+	}
+
+	ret = hapd->driver->do_acs(hapd->drv_priv, &params);
+	os_free(channels);
+
+	return ret;
+}

+ 24 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_drv_ops.d

@@ -0,0 +1,24 @@
+../src/ap/ap_drv_ops.o: ../src/ap/ap_drv_ops.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/hw_features_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/p2p/p2p.h \
+ ../src/ap/hostapd.h ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/vlan.h ../src/ap/ieee802_11.h ../src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/p2p_hostapd.h ../src/ap/hs20.h ../src/ap/ap_drv_ops.h

+ 350 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_drv_ops.h

@@ -0,0 +1,350 @@
+/*
+ * hostapd - Driver operations
+ * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AP_DRV_OPS
+#define AP_DRV_OPS
+
+enum wpa_driver_if_type;
+struct wpa_bss_params;
+struct wpa_driver_scan_params;
+struct ieee80211_ht_capabilities;
+struct ieee80211_vht_capabilities;
+struct hostapd_freq_params;
+
+u32 hostapd_sta_flags_to_drv(u32 flags);
+int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
+			       struct wpabuf **beacon,
+			       struct wpabuf **proberesp,
+			       struct wpabuf **assocresp);
+void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
+			       struct wpabuf *proberesp,
+			       struct wpabuf *assocresp);
+int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd);
+int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
+int hostapd_set_authorized(struct hostapd_data *hapd,
+			   struct sta_info *sta, int authorized);
+int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta);
+int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
+			      int enabled);
+int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname);
+int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname);
+int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds,
+			const u8 *addr, int aid, int val);
+int hostapd_sta_add(struct hostapd_data *hapd,
+		    const u8 *addr, u16 aid, u16 capability,
+		    const u8 *supp_rates, size_t supp_rates_len,
+		    u16 listen_interval,
+		    const struct ieee80211_ht_capabilities *ht_capab,
+		    const struct ieee80211_vht_capabilities *vht_capab,
+		    u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps,
+		    int set);
+int hostapd_set_privacy(struct hostapd_data *hapd, int enabled);
+int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem,
+			     size_t elem_len);
+int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len);
+int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len);
+int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
+		   const char *ifname, const u8 *addr, void *bss_ctx,
+		   void **drv_priv, char *force_ifname, u8 *if_addr,
+		   const char *bridge, int use_existing);
+int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
+		      const char *ifname);
+int hostapd_set_ieee8021x(struct hostapd_data *hapd,
+			  struct wpa_bss_params *params);
+int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
+		       const u8 *addr, int idx, u8 *seq);
+int hostapd_flush(struct hostapd_data *hapd);
+int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
+		     int freq, int channel, int ht_enabled, int vht_enabled,
+		     int sec_channel_offset, int vht_oper_chwidth,
+		     int center_segment0, int center_segment1);
+int hostapd_set_rts(struct hostapd_data *hapd, int rts);
+int hostapd_set_frag(struct hostapd_data *hapd, int frag);
+int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr,
+			  int total_flags, int flags_or, int flags_and);
+int hostapd_set_country(struct hostapd_data *hapd, const char *country);
+int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
+				int cw_min, int cw_max, int burst_time);
+struct hostapd_hw_modes *
+hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes,
+			    u16 *flags);
+int hostapd_driver_commit(struct hostapd_data *hapd);
+int hostapd_drv_none(struct hostapd_data *hapd);
+int hostapd_driver_scan(struct hostapd_data *hapd,
+			struct wpa_driver_scan_params *params);
+struct wpa_scan_results * hostapd_driver_get_scan_results(
+	struct hostapd_data *hapd);
+int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
+			   int duration);
+int hostapd_drv_set_key(const char *ifname,
+			struct hostapd_data *hapd,
+			enum wpa_alg alg, const u8 *addr,
+			int key_idx, int set_tx,
+			const u8 *seq, size_t seq_len,
+			const u8 *key, size_t key_len);
+int hostapd_drv_send_mlme(struct hostapd_data *hapd,
+			  const void *msg, size_t len, int noack);
+int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
+			      const void *msg, size_t len, int noack,
+			      const u16 *csa_offs, size_t csa_offs_len);
+int hostapd_drv_sta_deauth(struct hostapd_data *hapd,
+			   const u8 *addr, int reason);
+int hostapd_drv_sta_disassoc(struct hostapd_data *hapd,
+			     const u8 *addr, int reason);
+int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
+			    unsigned int wait, const u8 *dst, const u8 *data,
+			    size_t len);
+int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd,
+				     unsigned int freq,
+				     unsigned int wait, const u8 *dst,
+				     const u8 *data, size_t len);
+int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr,
+			 u16 auth_alg);
+int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr,
+		     u16 seq, u16 status, const u8 *ie, size_t len);
+int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
+		      int reassoc, u16 status, const u8 *ie, size_t len);
+int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
+		      u8 *tspec_ie, size_t tspec_ielen);
+int hostapd_start_dfs_cac(struct hostapd_iface *iface,
+			  enum hostapd_hw_mode mode, int freq,
+			  int channel, int ht_enabled, int vht_enabled,
+			  int sec_channel_offset, int vht_oper_chwidth,
+			  int center_segment0, int center_segment1);
+int hostapd_drv_do_acs(struct hostapd_data *hapd);
+
+
+#include "drivers/driver.h"
+
+int hostapd_drv_wnm_oper(struct hostapd_data *hapd,
+			 enum wnm_oper oper, const u8 *peer,
+			 u8 *buf, u16 *buf_len);
+
+int hostapd_drv_set_qos_map(struct hostapd_data *hapd, const u8 *qos_map_set,
+			    u8 qos_map_set_len);
+
+void hostapd_get_ext_capa(struct hostapd_iface *iface);
+
+static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd,
+						  int enabled)
+{
+	if (hapd->driver == NULL ||
+	    hapd->driver->hapd_set_countermeasures == NULL)
+		return 0;
+	return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled);
+}
+
+static inline int hostapd_drv_set_sta_vlan(const char *ifname,
+					   struct hostapd_data *hapd,
+					   const u8 *addr, int vlan_id)
+{
+	if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL)
+		return 0;
+	return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname,
+					  vlan_id);
+}
+
+static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd,
+					    const u8 *addr)
+{
+	if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL)
+		return 0;
+	return hapd->driver->get_inact_sec(hapd->drv_priv, addr);
+}
+
+static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd,
+					 const u8 *addr)
+{
+	if (!hapd->driver || !hapd->driver->sta_remove || !hapd->drv_priv)
+		return 0;
+	return hapd->driver->sta_remove(hapd->drv_priv, addr);
+}
+
+static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd,
+					      const u8 *addr, const u8 *data,
+					      size_t data_len, int encrypt,
+					      u32 flags)
+{
+	if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL)
+		return 0;
+	return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data,
+					     data_len, encrypt,
+					     hapd->own_addr, flags);
+}
+
+static inline int hostapd_drv_read_sta_data(
+	struct hostapd_data *hapd, struct hostap_sta_driver_data *data,
+	const u8 *addr)
+{
+	if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL)
+		return -1;
+	return hapd->driver->read_sta_data(hapd->drv_priv, data, addr);
+}
+
+static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd,
+					      const u8 *addr)
+{
+	if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL)
+		return 0;
+	return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
+}
+
+static inline int hostapd_drv_set_acl(struct hostapd_data *hapd,
+				      struct hostapd_acl_params *params)
+{
+	if (hapd->driver == NULL || hapd->driver->set_acl == NULL)
+		return 0;
+	return hapd->driver->set_acl(hapd->drv_priv, params);
+}
+
+static inline int hostapd_drv_set_ap(struct hostapd_data *hapd,
+				     struct wpa_driver_ap_params *params)
+{
+	if (hapd->driver == NULL || hapd->driver->set_ap == NULL)
+		return 0;
+	return hapd->driver->set_ap(hapd->drv_priv, params);
+}
+
+static inline int hostapd_drv_set_radius_acl_auth(struct hostapd_data *hapd,
+						  const u8 *mac, int accepted,
+						  u32 session_timeout)
+{
+	if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL)
+		return 0;
+	return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted,
+						 session_timeout);
+}
+
+static inline int hostapd_drv_set_radius_acl_expire(struct hostapd_data *hapd,
+						    const u8 *mac)
+{
+	if (hapd->driver == NULL ||
+	    hapd->driver->set_radius_acl_expire == NULL)
+		return 0;
+	return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac);
+}
+
+static inline int hostapd_drv_set_authmode(struct hostapd_data *hapd,
+					   int auth_algs)
+{
+	if (hapd->driver == NULL || hapd->driver->set_authmode == NULL)
+		return 0;
+	return hapd->driver->set_authmode(hapd->drv_priv, auth_algs);
+}
+
+static inline void hostapd_drv_poll_client(struct hostapd_data *hapd,
+					   const u8 *own_addr, const u8 *addr,
+					   int qos)
+{
+	if (hapd->driver == NULL || hapd->driver->poll_client == NULL)
+		return;
+	hapd->driver->poll_client(hapd->drv_priv, own_addr, addr, qos);
+}
+
+static inline int hostapd_drv_get_survey(struct hostapd_data *hapd,
+					 unsigned int freq)
+{
+	if (hapd->driver == NULL)
+		return -1;
+	if (!hapd->driver->get_survey)
+		return -1;
+	return hapd->driver->get_survey(hapd->drv_priv, freq);
+}
+
+static inline int hostapd_get_country(struct hostapd_data *hapd, char *alpha2)
+{
+	if (hapd->driver == NULL || hapd->driver->get_country == NULL)
+		return -1;
+	return hapd->driver->get_country(hapd->drv_priv, alpha2);
+}
+
+static inline const char * hostapd_drv_get_radio_name(struct hostapd_data *hapd)
+{
+	if (hapd->driver == NULL || hapd->drv_priv == NULL ||
+	    hapd->driver->get_radio_name == NULL)
+		return NULL;
+	return hapd->driver->get_radio_name(hapd->drv_priv);
+}
+
+static inline int hostapd_drv_switch_channel(struct hostapd_data *hapd,
+					     struct csa_settings *settings)
+{
+	if (hapd->driver == NULL || hapd->driver->switch_channel == NULL)
+		return -ENOTSUP;
+
+	return hapd->driver->switch_channel(hapd->drv_priv, settings);
+}
+
+static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf,
+				     size_t buflen)
+{
+	if (!hapd->driver || !hapd->driver->status || !hapd->drv_priv)
+		return -1;
+	return hapd->driver->status(hapd->drv_priv, buf, buflen);
+}
+
+static inline int hostapd_drv_br_add_ip_neigh(struct hostapd_data *hapd,
+					      int version, const u8 *ipaddr,
+					      int prefixlen, const u8 *addr)
+{
+	if (hapd->driver == NULL || hapd->drv_priv == NULL ||
+	    hapd->driver->br_add_ip_neigh == NULL)
+		return -1;
+	return hapd->driver->br_add_ip_neigh(hapd->drv_priv, version, ipaddr,
+					     prefixlen, addr);
+}
+
+static inline int hostapd_drv_br_delete_ip_neigh(struct hostapd_data *hapd,
+						 u8 version, const u8 *ipaddr)
+{
+	if (hapd->driver == NULL || hapd->drv_priv == NULL ||
+	    hapd->driver->br_delete_ip_neigh == NULL)
+		return -1;
+	return hapd->driver->br_delete_ip_neigh(hapd->drv_priv, version,
+						ipaddr);
+}
+
+static inline int hostapd_drv_br_port_set_attr(struct hostapd_data *hapd,
+					       enum drv_br_port_attr attr,
+					       unsigned int val)
+{
+	if (hapd->driver == NULL || hapd->drv_priv == NULL ||
+	    hapd->driver->br_port_set_attr == NULL)
+		return -1;
+	return hapd->driver->br_port_set_attr(hapd->drv_priv, attr, val);
+}
+
+static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd,
+					       enum drv_br_net_param param,
+					       unsigned int val)
+{
+	if (hapd->driver == NULL || hapd->drv_priv == NULL ||
+	    hapd->driver->br_set_net_param == NULL)
+		return -1;
+	return hapd->driver->br_set_net_param(hapd->drv_priv, param, val);
+}
+
+static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd,
+					 int vendor_id, int subcmd,
+					 const u8 *data, size_t data_len,
+					 struct wpabuf *buf)
+{
+	if (hapd->driver == NULL || hapd->driver->vendor_cmd == NULL)
+		return -1;
+	return hapd->driver->vendor_cmd(hapd->drv_priv, vendor_id, subcmd, data,
+					data_len, buf);
+}
+
+static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd)
+{
+	if (!hapd->driver || !hapd->driver->stop_ap || !hapd->drv_priv)
+		return 0;
+	return hapd->driver->stop_ap(hapd->drv_priv);
+}
+
+#endif /* AP_DRV_OPS */

+ 312 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_list.c

@@ -0,0 +1,312 @@
+/*
+ * hostapd / AP table
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2004, Instant802 Networks, Inc.
+ * Copyright (c) 2006, Devicescape Software, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "hostapd.h"
+#include "ap_config.h"
+#include "ieee802_11.h"
+#include "sta_info.h"
+#include "beacon.h"
+#include "ap_list.h"
+
+
+/* AP list is a double linked list with head->prev pointing to the end of the
+ * list and tail->next = NULL. Entries are moved to the head of the list
+ * whenever a beacon has been received from the AP in question. The tail entry
+ * in this link will thus be the least recently used entry. */
+
+
+static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap)
+{
+	int i;
+
+	if (iface->current_mode == NULL ||
+	    iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G ||
+	    iface->conf->channel != ap->channel)
+		return 0;
+
+	if (ap->erp != -1 && (ap->erp & ERP_INFO_NON_ERP_PRESENT))
+		return 1;
+
+	for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) {
+		int rate = (ap->supported_rates[i] & 0x7f) * 5;
+		if (rate == 60 || rate == 90 || rate > 110)
+			return 0;
+	}
+
+	return 1;
+}
+
+
+static struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *ap)
+{
+	struct ap_info *s;
+
+	s = iface->ap_hash[STA_HASH(ap)];
+	while (s != NULL && os_memcmp(s->addr, ap, ETH_ALEN) != 0)
+		s = s->hnext;
+	return s;
+}
+
+
+static void ap_ap_list_add(struct hostapd_iface *iface, struct ap_info *ap)
+{
+	if (iface->ap_list) {
+		ap->prev = iface->ap_list->prev;
+		iface->ap_list->prev = ap;
+	} else
+		ap->prev = ap;
+	ap->next = iface->ap_list;
+	iface->ap_list = ap;
+}
+
+
+static void ap_ap_list_del(struct hostapd_iface *iface, struct ap_info *ap)
+{
+	if (iface->ap_list == ap)
+		iface->ap_list = ap->next;
+	else
+		ap->prev->next = ap->next;
+
+	if (ap->next)
+		ap->next->prev = ap->prev;
+	else if (iface->ap_list)
+		iface->ap_list->prev = ap->prev;
+}
+
+
+static void ap_ap_hash_add(struct hostapd_iface *iface, struct ap_info *ap)
+{
+	ap->hnext = iface->ap_hash[STA_HASH(ap->addr)];
+	iface->ap_hash[STA_HASH(ap->addr)] = ap;
+}
+
+
+static void ap_ap_hash_del(struct hostapd_iface *iface, struct ap_info *ap)
+{
+	struct ap_info *s;
+
+	s = iface->ap_hash[STA_HASH(ap->addr)];
+	if (s == NULL) return;
+	if (os_memcmp(s->addr, ap->addr, ETH_ALEN) == 0) {
+		iface->ap_hash[STA_HASH(ap->addr)] = s->hnext;
+		return;
+	}
+
+	while (s->hnext != NULL &&
+	       os_memcmp(s->hnext->addr, ap->addr, ETH_ALEN) != 0)
+		s = s->hnext;
+	if (s->hnext != NULL)
+		s->hnext = s->hnext->hnext;
+	else
+		wpa_printf(MSG_INFO, "AP: could not remove AP " MACSTR
+			   " from hash table",  MAC2STR(ap->addr));
+}
+
+
+static void ap_free_ap(struct hostapd_iface *iface, struct ap_info *ap)
+{
+	ap_ap_hash_del(iface, ap);
+	ap_ap_list_del(iface, ap);
+
+	iface->num_ap--;
+	os_free(ap);
+}
+
+
+static void hostapd_free_aps(struct hostapd_iface *iface)
+{
+	struct ap_info *ap, *prev;
+
+	ap = iface->ap_list;
+
+	while (ap) {
+		prev = ap;
+		ap = ap->next;
+		ap_free_ap(iface, prev);
+	}
+
+	iface->ap_list = NULL;
+}
+
+
+static struct ap_info * ap_ap_add(struct hostapd_iface *iface, const u8 *addr)
+{
+	struct ap_info *ap;
+
+	ap = os_zalloc(sizeof(struct ap_info));
+	if (ap == NULL)
+		return NULL;
+
+	/* initialize AP info data */
+	os_memcpy(ap->addr, addr, ETH_ALEN);
+	ap_ap_list_add(iface, ap);
+	iface->num_ap++;
+	ap_ap_hash_add(iface, ap);
+
+	if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) {
+		wpa_printf(MSG_DEBUG, "Removing the least recently used AP "
+			   MACSTR " from AP table", MAC2STR(ap->prev->addr));
+		ap_free_ap(iface, ap->prev);
+	}
+
+	return ap;
+}
+
+
+void ap_list_process_beacon(struct hostapd_iface *iface,
+			    const struct ieee80211_mgmt *mgmt,
+			    struct ieee802_11_elems *elems,
+			    struct hostapd_frame_info *fi)
+{
+	struct ap_info *ap;
+	int new_ap = 0;
+	int set_beacon = 0;
+
+	if (iface->conf->ap_table_max_size < 1)
+		return;
+
+	ap = ap_get_ap(iface, mgmt->bssid);
+	if (!ap) {
+		ap = ap_ap_add(iface, mgmt->bssid);
+		if (!ap) {
+			wpa_printf(MSG_INFO,
+				   "Failed to allocate AP information entry");
+			return;
+		}
+		new_ap = 1;
+	}
+
+	merge_byte_arrays(ap->supported_rates, WLAN_SUPP_RATES_MAX,
+			  elems->supp_rates, elems->supp_rates_len,
+			  elems->ext_supp_rates, elems->ext_supp_rates_len);
+
+	if (elems->erp_info)
+		ap->erp = elems->erp_info[0];
+	else
+		ap->erp = -1;
+
+	if (elems->ds_params)
+		ap->channel = elems->ds_params[0];
+	else if (elems->ht_operation)
+		ap->channel = elems->ht_operation[0];
+	else if (fi)
+		ap->channel = fi->channel;
+
+	if (elems->ht_capabilities)
+		ap->ht_support = 1;
+	else
+		ap->ht_support = 0;
+
+	os_get_reltime(&ap->last_beacon);
+
+	if (!new_ap && ap != iface->ap_list) {
+		/* move AP entry into the beginning of the list so that the
+		 * oldest entry is always in the end of the list */
+		ap_ap_list_del(iface, ap);
+		ap_ap_list_add(iface, ap);
+	}
+
+	if (!iface->olbc &&
+	    ap_list_beacon_olbc(iface, ap)) {
+		iface->olbc = 1;
+		wpa_printf(MSG_DEBUG, "OLBC AP detected: " MACSTR
+			   " (channel %d) - enable protection",
+			   MAC2STR(ap->addr), ap->channel);
+		set_beacon++;
+	}
+
+#ifdef CONFIG_IEEE80211N
+	if (!iface->olbc_ht && !ap->ht_support &&
+	    (ap->channel == 0 ||
+	     ap->channel == iface->conf->channel ||
+	     ap->channel == iface->conf->channel +
+	     iface->conf->secondary_channel * 4)) {
+		iface->olbc_ht = 1;
+		hostapd_ht_operation_update(iface);
+		wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR
+			   " (channel %d) - enable protection",
+			   MAC2STR(ap->addr), ap->channel);
+		set_beacon++;
+	}
+#endif /* CONFIG_IEEE80211N */
+
+	if (set_beacon)
+		ieee802_11_update_beacons(iface);
+}
+
+
+void ap_list_timer(struct hostapd_iface *iface)
+{
+	struct os_reltime now;
+	struct ap_info *ap;
+	int set_beacon = 0;
+
+	if (!iface->ap_list)
+		return;
+
+	os_get_reltime(&now);
+
+	while (iface->ap_list) {
+		ap = iface->ap_list->prev;
+		if (!os_reltime_expired(&now, &ap->last_beacon,
+					iface->conf->ap_table_expiration_time))
+			break;
+
+		ap_free_ap(iface, ap);
+	}
+
+	if (iface->olbc || iface->olbc_ht) {
+		int olbc = 0;
+		int olbc_ht = 0;
+
+		ap = iface->ap_list;
+		while (ap && (olbc == 0 || olbc_ht == 0)) {
+			if (ap_list_beacon_olbc(iface, ap))
+				olbc = 1;
+			if (!ap->ht_support)
+				olbc_ht = 1;
+			ap = ap->next;
+		}
+		if (!olbc && iface->olbc) {
+			wpa_printf(MSG_DEBUG, "OLBC not detected anymore");
+			iface->olbc = 0;
+			set_beacon++;
+		}
+#ifdef CONFIG_IEEE80211N
+		if (!olbc_ht && iface->olbc_ht) {
+			wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore");
+			iface->olbc_ht = 0;
+			hostapd_ht_operation_update(iface);
+			set_beacon++;
+		}
+#endif /* CONFIG_IEEE80211N */
+	}
+
+	if (set_beacon)
+		ieee802_11_update_beacons(iface);
+}
+
+
+int ap_list_init(struct hostapd_iface *iface)
+{
+	return 0;
+}
+
+
+void ap_list_deinit(struct hostapd_iface *iface)
+{
+	hostapd_free_aps(iface);
+}

+ 25 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_list.d

@@ -0,0 +1,25 @@
+../src/ap/ap_list.o: ../src/ap/ap_list.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/eloop.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ ../src/ap/hostapd.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/vlan.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ ../src/ap/ieee802_11.h ../src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/beacon.h ../src/ap/ap_list.h

+ 58 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_list.h

@@ -0,0 +1,58 @@
+/*
+ * hostapd / AP table
+ * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2004, Instant802 Networks, Inc.
+ * Copyright (c) 2006, Devicescape Software, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AP_LIST_H
+#define AP_LIST_H
+
+struct ap_info {
+	/* Note: next/prev pointers are updated whenever a new beacon is
+	 * received because these are used to find the least recently used
+	 * entries. */
+	struct ap_info *next; /* next entry in AP list */
+	struct ap_info *prev; /* previous entry in AP list */
+	struct ap_info *hnext; /* next entry in hash table list */
+	u8 addr[6];
+	u8 supported_rates[WLAN_SUPP_RATES_MAX];
+	int erp; /* ERP Info or -1 if ERP info element not present */
+
+	int channel;
+
+	int ht_support;
+
+	struct os_reltime last_beacon;
+};
+
+struct ieee802_11_elems;
+struct hostapd_frame_info;
+
+void ap_list_process_beacon(struct hostapd_iface *iface,
+			    const struct ieee80211_mgmt *mgmt,
+			    struct ieee802_11_elems *elems,
+			    struct hostapd_frame_info *fi);
+#ifdef NEED_AP_MLME
+int ap_list_init(struct hostapd_iface *iface);
+void ap_list_deinit(struct hostapd_iface *iface);
+void ap_list_timer(struct hostapd_iface *iface);
+#else /* NEED_AP_MLME */
+static inline int ap_list_init(struct hostapd_iface *iface)
+{
+	return 0;
+}
+
+static inline void ap_list_deinit(struct hostapd_iface *iface)
+{
+}
+
+static inline void ap_list_timer(struct hostapd_iface *iface)
+{
+}
+#endif /* NEED_AP_MLME */
+
+#endif /* AP_LIST_H */

+ 181 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_mlme.c

@@ -0,0 +1,181 @@
+/*
+ * hostapd / IEEE 802.11 MLME
+ * Copyright 2003-2006, Jouni Malinen <j@w1.fi>
+ * Copyright 2003-2004, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "ieee802_11.h"
+#include "wpa_auth.h"
+#include "sta_info.h"
+#include "ap_mlme.h"
+#include "hostapd.h"
+
+
+#ifndef CONFIG_NO_HOSTAPD_LOGGER
+static const char * mlme_auth_alg_str(int alg)
+{
+	switch (alg) {
+	case WLAN_AUTH_OPEN:
+		return "OPEN_SYSTEM";
+	case WLAN_AUTH_SHARED_KEY:
+		return "SHARED_KEY";
+	case WLAN_AUTH_FT:
+		return "FT";
+	}
+
+	return "unknown";
+}
+#endif /* CONFIG_NO_HOSTAPD_LOGGER */
+
+
+/**
+ * mlme_authenticate_indication - Report the establishment of an authentication
+ * relationship with a specific peer MAC entity
+ * @hapd: BSS data
+ * @sta: peer STA data
+ *
+ * MLME calls this function as a result of the establishment of an
+ * authentication relationship with a specific peer MAC entity that
+ * resulted from an authentication procedure that was initiated by
+ * that specific peer MAC entity.
+ *
+ * PeerSTAAddress = sta->addr
+ * AuthenticationType = sta->auth_alg (WLAN_AUTH_OPEN / WLAN_AUTH_SHARED_KEY)
+ */
+void mlme_authenticate_indication(struct hostapd_data *hapd,
+				  struct sta_info *sta)
+{
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
+		       HOSTAPD_LEVEL_DEBUG,
+		       "MLME-AUTHENTICATE.indication(" MACSTR ", %s)",
+		       MAC2STR(sta->addr), mlme_auth_alg_str(sta->auth_alg));
+	if (sta->auth_alg != WLAN_AUTH_FT && !(sta->flags & WLAN_STA_MFP))
+		mlme_deletekeys_request(hapd, sta);
+	ap_sta_clear_disconnect_timeouts(hapd, sta);
+}
+
+
+/**
+ * mlme_deauthenticate_indication - Report the invalidation of an
+ * authentication relationship with a specific peer MAC entity
+ * @hapd: BSS data
+ * @sta: Peer STA data
+ * @reason_code: ReasonCode from Deauthentication frame
+ *
+ * MLME calls this function as a result of the invalidation of an
+ * authentication relationship with a specific peer MAC entity.
+ *
+ * PeerSTAAddress = sta->addr
+ */
+void mlme_deauthenticate_indication(struct hostapd_data *hapd,
+				    struct sta_info *sta, u16 reason_code)
+{
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
+		       HOSTAPD_LEVEL_DEBUG,
+		       "MLME-DEAUTHENTICATE.indication(" MACSTR ", %d)",
+		       MAC2STR(sta->addr), reason_code);
+	if (!hapd->iface->driver_ap_teardown)
+		mlme_deletekeys_request(hapd, sta);
+}
+
+
+/**
+ * mlme_associate_indication - Report the establishment of an association with
+ * a specific peer MAC entity
+ * @hapd: BSS data
+ * @sta: peer STA data
+ *
+ * MLME calls this function as a result of the establishment of an
+ * association with a specific peer MAC entity that resulted from an
+ * association procedure that was initiated by that specific peer MAC entity.
+ *
+ * PeerSTAAddress = sta->addr
+ */
+void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
+		       HOSTAPD_LEVEL_DEBUG,
+		       "MLME-ASSOCIATE.indication(" MACSTR ")",
+		       MAC2STR(sta->addr));
+	if (sta->auth_alg != WLAN_AUTH_FT)
+		mlme_deletekeys_request(hapd, sta);
+	ap_sta_clear_disconnect_timeouts(hapd, sta);
+}
+
+
+/**
+ * mlme_reassociate_indication - Report the establishment of an reassociation
+ * with a specific peer MAC entity
+ * @hapd: BSS data
+ * @sta: peer STA data
+ *
+ * MLME calls this function as a result of the establishment of an
+ * reassociation with a specific peer MAC entity that resulted from a
+ * reassociation procedure that was initiated by that specific peer MAC entity.
+ *
+ * PeerSTAAddress = sta->addr
+ */
+void mlme_reassociate_indication(struct hostapd_data *hapd,
+				 struct sta_info *sta)
+{
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
+		       HOSTAPD_LEVEL_DEBUG,
+		       "MLME-REASSOCIATE.indication(" MACSTR ")",
+		       MAC2STR(sta->addr));
+	if (sta->auth_alg != WLAN_AUTH_FT)
+		mlme_deletekeys_request(hapd, sta);
+	ap_sta_clear_disconnect_timeouts(hapd, sta);
+}
+
+
+/**
+ * mlme_disassociate_indication - Report disassociation with a specific peer
+ * MAC entity
+ * @hapd: BSS data
+ * @sta: Peer STA data
+ * @reason_code: ReasonCode from Disassociation frame
+ *
+ * MLME calls this function as a result of the invalidation of an association
+ * relationship with a specific peer MAC entity.
+ *
+ * PeerSTAAddress = sta->addr
+ */
+void mlme_disassociate_indication(struct hostapd_data *hapd,
+				  struct sta_info *sta, u16 reason_code)
+{
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
+		       HOSTAPD_LEVEL_DEBUG,
+		       "MLME-DISASSOCIATE.indication(" MACSTR ", %d)",
+		       MAC2STR(sta->addr), reason_code);
+	mlme_deletekeys_request(hapd, sta);
+}
+
+
+void mlme_michaelmicfailure_indication(struct hostapd_data *hapd,
+				       const u8 *addr)
+{
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_MLME,
+		       HOSTAPD_LEVEL_DEBUG,
+		       "MLME-MichaelMICFailure.indication(" MACSTR ")",
+		       MAC2STR(addr));
+}
+
+
+void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME,
+		       HOSTAPD_LEVEL_DEBUG,
+		       "MLME-DELETEKEYS.request(" MACSTR ")",
+		       MAC2STR(sta->addr));
+
+	if (sta->wpa_sm)
+		wpa_remove_ptk(sta->wpa_sm);
+}

+ 24 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_mlme.d

@@ -0,0 +1,24 @@
+../src/ap/ap_mlme.o: ../src/ap/ap_mlme.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ ../src/ap/ieee802_11.h ../src/ap/wpa_auth.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/eapol_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ ../src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/vlan.h ../src/ap/ap_mlme.h ../src/ap/hostapd.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h

+ 34 - 0
EVSE/GPL/hostapd-2.6/src/ap/ap_mlme.h

@@ -0,0 +1,34 @@
+/*
+ * hostapd / IEEE 802.11 MLME
+ * Copyright 2003, Jouni Malinen <j@w1.fi>
+ * Copyright 2003-2004, Instant802 Networks, Inc.
+ * Copyright 2005-2006, Devicescape Software, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef MLME_H
+#define MLME_H
+
+void mlme_authenticate_indication(struct hostapd_data *hapd,
+				  struct sta_info *sta);
+
+void mlme_deauthenticate_indication(struct hostapd_data *hapd,
+				    struct sta_info *sta, u16 reason_code);
+
+void mlme_associate_indication(struct hostapd_data *hapd,
+			       struct sta_info *sta);
+
+void mlme_reassociate_indication(struct hostapd_data *hapd,
+				 struct sta_info *sta);
+
+void mlme_disassociate_indication(struct hostapd_data *hapd,
+				  struct sta_info *sta, u16 reason_code);
+
+void mlme_michaelmicfailure_indication(struct hostapd_data *hapd,
+				       const u8 *addr);
+
+void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta);
+
+#endif /* MLME_H */

+ 239 - 0
EVSE/GPL/hostapd-2.6/src/ap/authsrv.c

@@ -0,0 +1,239 @@
+/*
+ * Authentication server setup
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "crypto/tls.h"
+#include "eap_server/eap.h"
+#include "eap_server/eap_sim_db.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "radius/radius_server.h"
+#include "hostapd.h"
+#include "ap_config.h"
+#include "sta_info.h"
+#include "authsrv.h"
+
+
+#if defined(EAP_SERVER_SIM) || defined(EAP_SERVER_AKA)
+#define EAP_SIM_DB
+#endif /* EAP_SERVER_SIM || EAP_SERVER_AKA */
+
+
+#ifdef EAP_SIM_DB
+static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd,
+				 struct sta_info *sta, void *ctx)
+{
+	if (eapol_auth_eap_pending_cb(sta->eapol_sm, ctx) == 0)
+		return 1;
+	return 0;
+}
+
+
+static void hostapd_sim_db_cb(void *ctx, void *session_ctx)
+{
+	struct hostapd_data *hapd = ctx;
+	if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0) {
+#ifdef RADIUS_SERVER
+		radius_server_eap_pending_cb(hapd->radius_srv, session_ctx);
+#endif /* RADIUS_SERVER */
+	}
+}
+#endif /* EAP_SIM_DB */
+
+
+#ifdef RADIUS_SERVER
+
+static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
+				       size_t identity_len, int phase2,
+				       struct eap_user *user)
+{
+	const struct hostapd_eap_user *eap_user;
+	int i;
+	int rv = -1;
+
+	eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
+	if (eap_user == NULL)
+		goto out;
+
+	if (user == NULL)
+		return 0;
+
+	os_memset(user, 0, sizeof(*user));
+	for (i = 0; i < EAP_MAX_METHODS; i++) {
+		user->methods[i].vendor = eap_user->methods[i].vendor;
+		user->methods[i].method = eap_user->methods[i].method;
+	}
+
+	if (eap_user->password) {
+		user->password = os_malloc(eap_user->password_len);
+		if (user->password == NULL)
+			goto out;
+		os_memcpy(user->password, eap_user->password,
+			  eap_user->password_len);
+		user->password_len = eap_user->password_len;
+		user->password_hash = eap_user->password_hash;
+	}
+	user->force_version = eap_user->force_version;
+	user->macacl = eap_user->macacl;
+	user->ttls_auth = eap_user->ttls_auth;
+	user->remediation = eap_user->remediation;
+	user->accept_attr = eap_user->accept_attr;
+	rv = 0;
+
+out:
+	if (rv)
+		wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__);
+
+	return rv;
+}
+
+
+static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
+{
+	struct radius_server_conf srv;
+	struct hostapd_bss_config *conf = hapd->conf;
+	os_memset(&srv, 0, sizeof(srv));
+	srv.client_file = conf->radius_server_clients;
+	srv.auth_port = conf->radius_server_auth_port;
+	srv.acct_port = conf->radius_server_acct_port;
+	srv.conf_ctx = hapd;
+	srv.eap_sim_db_priv = hapd->eap_sim_db_priv;
+	srv.ssl_ctx = hapd->ssl_ctx;
+	srv.msg_ctx = hapd->msg_ctx;
+	srv.pac_opaque_encr_key = conf->pac_opaque_encr_key;
+	srv.eap_fast_a_id = conf->eap_fast_a_id;
+	srv.eap_fast_a_id_len = conf->eap_fast_a_id_len;
+	srv.eap_fast_a_id_info = conf->eap_fast_a_id_info;
+	srv.eap_fast_prov = conf->eap_fast_prov;
+	srv.pac_key_lifetime = conf->pac_key_lifetime;
+	srv.pac_key_refresh_time = conf->pac_key_refresh_time;
+	srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind;
+	srv.tnc = conf->tnc;
+	srv.wps = hapd->wps;
+	srv.ipv6 = conf->radius_server_ipv6;
+	srv.get_eap_user = hostapd_radius_get_eap_user;
+	srv.eap_req_id_text = conf->eap_req_id_text;
+	srv.eap_req_id_text_len = conf->eap_req_id_text_len;
+	srv.pwd_group = conf->pwd_group;
+	srv.server_id = conf->server_id ? conf->server_id : "hostapd";
+	srv.sqlite_file = conf->eap_user_sqlite;
+#ifdef CONFIG_RADIUS_TEST
+	srv.dump_msk_file = conf->dump_msk_file;
+#endif /* CONFIG_RADIUS_TEST */
+#ifdef CONFIG_HS20
+	srv.subscr_remediation_url = conf->subscr_remediation_url;
+	srv.subscr_remediation_method = conf->subscr_remediation_method;
+#endif /* CONFIG_HS20 */
+	srv.erp = conf->eap_server_erp;
+	srv.erp_domain = conf->erp_domain;
+	srv.tls_session_lifetime = conf->tls_session_lifetime;
+
+	hapd->radius_srv = radius_server_init(&srv);
+	if (hapd->radius_srv == NULL) {
+		wpa_printf(MSG_ERROR, "RADIUS server initialization failed.");
+		return -1;
+	}
+
+	return 0;
+}
+
+#endif /* RADIUS_SERVER */
+
+
+int authsrv_init(struct hostapd_data *hapd)
+{
+#ifdef EAP_TLS_FUNCS
+	if (hapd->conf->eap_server &&
+	    (hapd->conf->ca_cert || hapd->conf->server_cert ||
+	     hapd->conf->private_key || hapd->conf->dh_file)) {
+		struct tls_config conf;
+		struct tls_connection_params params;
+
+		os_memset(&conf, 0, sizeof(conf));
+		conf.tls_session_lifetime = hapd->conf->tls_session_lifetime;
+		hapd->ssl_ctx = tls_init(&conf);
+		if (hapd->ssl_ctx == NULL) {
+			wpa_printf(MSG_ERROR, "Failed to initialize TLS");
+			authsrv_deinit(hapd);
+			return -1;
+		}
+
+		os_memset(&params, 0, sizeof(params));
+		params.ca_cert = hapd->conf->ca_cert;
+		params.client_cert = hapd->conf->server_cert;
+		params.private_key = hapd->conf->private_key;
+		params.private_key_passwd = hapd->conf->private_key_passwd;
+		params.dh_file = hapd->conf->dh_file;
+		params.openssl_ciphers = hapd->conf->openssl_ciphers;
+		params.ocsp_stapling_response =
+			hapd->conf->ocsp_stapling_response;
+		params.ocsp_stapling_response_multi =
+			hapd->conf->ocsp_stapling_response_multi;
+
+		if (tls_global_set_params(hapd->ssl_ctx, &params)) {
+			wpa_printf(MSG_ERROR, "Failed to set TLS parameters");
+			authsrv_deinit(hapd);
+			return -1;
+		}
+
+		if (tls_global_set_verify(hapd->ssl_ctx,
+					  hapd->conf->check_crl)) {
+			wpa_printf(MSG_ERROR, "Failed to enable check_crl");
+			authsrv_deinit(hapd);
+			return -1;
+		}
+	}
+#endif /* EAP_TLS_FUNCS */
+
+#ifdef EAP_SIM_DB
+	if (hapd->conf->eap_sim_db) {
+		hapd->eap_sim_db_priv =
+			eap_sim_db_init(hapd->conf->eap_sim_db,
+					hapd->conf->eap_sim_db_timeout,
+					hostapd_sim_db_cb, hapd);
+		if (hapd->eap_sim_db_priv == NULL) {
+			wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM "
+				   "database interface");
+			authsrv_deinit(hapd);
+			return -1;
+		}
+	}
+#endif /* EAP_SIM_DB */
+
+#ifdef RADIUS_SERVER
+	if (hapd->conf->radius_server_clients &&
+	    hostapd_setup_radius_srv(hapd))
+		return -1;
+#endif /* RADIUS_SERVER */
+
+	return 0;
+}
+
+
+void authsrv_deinit(struct hostapd_data *hapd)
+{
+#ifdef RADIUS_SERVER
+	radius_server_deinit(hapd->radius_srv);
+	hapd->radius_srv = NULL;
+#endif /* RADIUS_SERVER */
+
+#ifdef EAP_TLS_FUNCS
+	if (hapd->ssl_ctx) {
+		tls_deinit(hapd->ssl_ctx);
+		hapd->ssl_ctx = NULL;
+	}
+#endif /* EAP_TLS_FUNCS */
+
+#ifdef EAP_SIM_DB
+	if (hapd->eap_sim_db_priv) {
+		eap_sim_db_deinit(hapd->eap_sim_db_priv);
+		hapd->eap_sim_db_priv = NULL;
+	}
+#endif /* EAP_SIM_DB */
+}

+ 32 - 0
EVSE/GPL/hostapd-2.6/src/ap/authsrv.d

@@ -0,0 +1,32 @@
+../src/ap/authsrv.o: ../src/ap/authsrv.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/crypto/tls.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_common/eap_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap_methods.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap_sim_db.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_common/eap_sim_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eapol_auth/eapol_auth_sm.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius_server.h \
+ ../src/ap/hostapd.h ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/vlan.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ ../src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/authsrv.h

+ 15 - 0
EVSE/GPL/hostapd-2.6/src/ap/authsrv.h

@@ -0,0 +1,15 @@
+/*
+ * Authentication server setup
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef AUTHSRV_H
+#define AUTHSRV_H
+
+int authsrv_init(struct hostapd_data *hapd);
+void authsrv_deinit(struct hostapd_data *hapd);
+
+#endif /* AUTHSRV_H */

+ 1375 - 0
EVSE/GPL/hostapd-2.6/src/ap/beacon.c

@@ -0,0 +1,1375 @@
+/*
+ * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
+ * Copyright (c) 2002-2004, Instant802 Networks, Inc.
+ * Copyright (c) 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#ifndef CONFIG_NATIVE_WINDOWS
+
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "common/hw_features_common.h"
+#include "wps/wps_defs.h"
+#include "p2p/p2p.h"
+#include "hostapd.h"
+#include "ieee802_11.h"
+#include "wpa_auth.h"
+#include "wmm.h"
+#include "ap_config.h"
+#include "sta_info.h"
+#include "p2p_hostapd.h"
+#include "ap_drv_ops.h"
+#include "beacon.h"
+#include "hs20.h"
+#include "dfs.h"
+#include "taxonomy.h"
+
+
+#ifdef NEED_AP_MLME
+
+static u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid,
+					 size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
+		if (hapd->conf->radio_measurements[i])
+			break;
+	}
+
+	if (i == RRM_CAPABILITIES_IE_LEN || len < 2 + RRM_CAPABILITIES_IE_LEN)
+		return eid;
+
+	*eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
+	*eid++ = RRM_CAPABILITIES_IE_LEN;
+	os_memcpy(eid, hapd->conf->radio_measurements, RRM_CAPABILITIES_IE_LEN);
+
+	return eid + RRM_CAPABILITIES_IE_LEN;
+}
+
+
+static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
+{
+	if (len < 2 + 5)
+		return eid;
+
+#ifdef CONFIG_TESTING_OPTIONS
+	if (hapd->conf->bss_load_test_set) {
+		*eid++ = WLAN_EID_BSS_LOAD;
+		*eid++ = 5;
+		os_memcpy(eid, hapd->conf->bss_load_test, 5);
+		eid += 5;
+		return eid;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+	if (hapd->conf->bss_load_update_period) {
+		*eid++ = WLAN_EID_BSS_LOAD;
+		*eid++ = 5;
+		WPA_PUT_LE16(eid, hapd->num_sta);
+		eid += 2;
+		*eid++ = hapd->iface->channel_utilization;
+		WPA_PUT_LE16(eid, 0); /* no available admission capabity */
+		eid += 2;
+	}
+	return eid;
+}
+
+
+static u8 ieee802_11_erp_info(struct hostapd_data *hapd)
+{
+	u8 erp = 0;
+
+	if (hapd->iface->current_mode == NULL ||
+	    hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
+		return 0;
+
+	if (hapd->iface->olbc)
+		erp |= ERP_INFO_USE_PROTECTION;
+	if (hapd->iface->num_sta_non_erp > 0) {
+		erp |= ERP_INFO_NON_ERP_PRESENT |
+			ERP_INFO_USE_PROTECTION;
+	}
+	if (hapd->iface->num_sta_no_short_preamble > 0 ||
+	    hapd->iconf->preamble == LONG_PREAMBLE)
+		erp |= ERP_INFO_BARKER_PREAMBLE_MODE;
+
+	return erp;
+}
+
+
+static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid)
+{
+	*eid++ = WLAN_EID_DS_PARAMS;
+	*eid++ = 1;
+	*eid++ = hapd->iconf->channel;
+	return eid;
+}
+
+
+static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid)
+{
+	if (hapd->iface->current_mode == NULL ||
+	    hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
+		return eid;
+
+	/* Set NonERP_present and use_protection bits if there
+	 * are any associated NonERP stations. */
+	/* TODO: use_protection bit can be set to zero even if
+	 * there are NonERP stations present. This optimization
+	 * might be useful if NonERP stations are "quiet".
+	 * See 802.11g/D6 E-1 for recommended practice.
+	 * In addition, Non ERP present might be set, if AP detects Non ERP
+	 * operation on other APs. */
+
+	/* Add ERP Information element */
+	*eid++ = WLAN_EID_ERP_INFO;
+	*eid++ = 1;
+	*eid++ = ieee802_11_erp_info(hapd);
+
+	return eid;
+}
+
+
+static u8 * hostapd_eid_pwr_constraint(struct hostapd_data *hapd, u8 *eid)
+{
+	u8 *pos = eid;
+	u8 local_pwr_constraint = 0;
+	int dfs;
+
+	if (hapd->iface->current_mode == NULL ||
+	    hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
+		return eid;
+
+	/* Let host drivers add this IE if DFS support is offloaded */
+	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
+		return eid;
+
+	/*
+	 * There is no DFS support and power constraint was not directly
+	 * requested by config option.
+	 */
+	if (!hapd->iconf->ieee80211h &&
+	    hapd->iconf->local_pwr_constraint == -1)
+		return eid;
+
+	/* Check if DFS is required by regulatory. */
+	dfs = hostapd_is_dfs_required(hapd->iface);
+	if (dfs < 0) {
+		wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
+			   dfs);
+		dfs = 0;
+	}
+
+	if (dfs == 0 && hapd->iconf->local_pwr_constraint == -1)
+		return eid;
+
+	/*
+	 * ieee80211h (DFS) is enabled so Power Constraint element shall
+	 * be added when running on DFS channel whenever local_pwr_constraint
+	 * is configured or not. In order to meet regulations when TPC is not
+	 * implemented using a transmit power that is below the legal maximum
+	 * (including any mitigation factor) should help. In this case,
+	 * indicate 3 dB below maximum allowed transmit power.
+	 */
+	if (hapd->iconf->local_pwr_constraint == -1)
+		local_pwr_constraint = 3;
+
+	/*
+	 * A STA that is not an AP shall use a transmit power less than or
+	 * equal to the local maximum transmit power level for the channel.
+	 * The local maximum transmit power can be calculated from the formula:
+	 * local max TX pwr = max TX pwr - local pwr constraint
+	 * Where max TX pwr is maximum transmit power level specified for
+	 * channel in Country element and local pwr constraint is specified
+	 * for channel in this Power Constraint element.
+	 */
+
+	/* Element ID */
+	*pos++ = WLAN_EID_PWR_CONSTRAINT;
+	/* Length */
+	*pos++ = 1;
+	/* Local Power Constraint */
+	if (local_pwr_constraint)
+		*pos++ = local_pwr_constraint;
+	else
+		*pos++ = hapd->iconf->local_pwr_constraint;
+
+	return pos;
+}
+
+
+static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing,
+				    struct hostapd_channel_data *start,
+				    struct hostapd_channel_data *prev)
+{
+	if (end - pos < 3)
+		return pos;
+
+	/* first channel number */
+	*pos++ = start->chan;
+	/* number of channels */
+	*pos++ = (prev->chan - start->chan) / chan_spacing + 1;
+	/* maximum transmit power level */
+	*pos++ = start->max_tx_power;
+
+	return pos;
+}
+
+
+static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
+				int max_len)
+{
+	u8 *pos = eid;
+	u8 *end = eid + max_len;
+	int i;
+	struct hostapd_hw_modes *mode;
+	struct hostapd_channel_data *start, *prev;
+	int chan_spacing = 1;
+
+	if (!hapd->iconf->ieee80211d || max_len < 6 ||
+	    hapd->iface->current_mode == NULL)
+		return eid;
+
+	*pos++ = WLAN_EID_COUNTRY;
+	pos++; /* length will be set later */
+	os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */
+	pos += 3;
+
+	mode = hapd->iface->current_mode;
+	if (mode->mode == HOSTAPD_MODE_IEEE80211A)
+		chan_spacing = 4;
+
+	start = prev = NULL;
+	for (i = 0; i < mode->num_channels; i++) {
+		struct hostapd_channel_data *chan = &mode->channels[i];
+		if (chan->flag & HOSTAPD_CHAN_DISABLED)
+			continue;
+		if (start && prev &&
+		    prev->chan + chan_spacing == chan->chan &&
+		    start->max_tx_power == chan->max_tx_power) {
+			prev = chan;
+			continue; /* can use same entry */
+		}
+
+		if (start && prev) {
+			pos = hostapd_eid_country_add(pos, end, chan_spacing,
+						      start, prev);
+			start = NULL;
+		}
+
+		/* Start new group */
+		start = prev = chan;
+	}
+
+	if (start) {
+		pos = hostapd_eid_country_add(pos, end, chan_spacing,
+					      start, prev);
+	}
+
+	if ((pos - eid) & 1) {
+		if (end - pos < 1)
+			return eid;
+		*pos++ = 0; /* pad for 16-bit alignment */
+	}
+
+	eid[1] = (pos - eid) - 2;
+
+	return pos;
+}
+
+
+static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
+{
+	const u8 *ie;
+	size_t ielen;
+
+	ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
+	if (ie == NULL || ielen > len)
+		return eid;
+
+	os_memcpy(eid, ie, ielen);
+	return eid + ielen;
+}
+
+
+static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
+{
+#ifdef CONFIG_TESTING_OPTIONS
+	if (hapd->iface->cs_oper_class && hapd->iconf->ecsa_ie_only)
+		return eid;
+#endif /* CONFIG_TESTING_OPTIONS */
+
+	if (!hapd->cs_freq_params.channel)
+		return eid;
+
+	*eid++ = WLAN_EID_CHANNEL_SWITCH;
+	*eid++ = 3;
+	*eid++ = hapd->cs_block_tx;
+	*eid++ = hapd->cs_freq_params.channel;
+	*eid++ = hapd->cs_count;
+
+	return eid;
+}
+
+
+static u8 * hostapd_eid_ecsa(struct hostapd_data *hapd, u8 *eid)
+{
+	if (!hapd->cs_freq_params.channel || !hapd->iface->cs_oper_class)
+		return eid;
+
+	*eid++ = WLAN_EID_EXT_CHANSWITCH_ANN;
+	*eid++ = 4;
+	*eid++ = hapd->cs_block_tx;
+	*eid++ = hapd->iface->cs_oper_class;
+	*eid++ = hapd->cs_freq_params.channel;
+	*eid++ = hapd->cs_count;
+
+	return eid;
+}
+
+
+static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+{
+	u8 op_class, channel;
+
+	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) ||
+	    !hapd->iface->freq)
+		return eid;
+
+	if (ieee80211_freq_to_channel_ext(hapd->iface->freq,
+					  hapd->iconf->secondary_channel,
+					  hapd->iconf->vht_oper_chwidth,
+					  &op_class, &channel) ==
+	    NUM_HOSTAPD_MODES)
+		return eid;
+
+	*eid++ = WLAN_EID_SUPPORTED_OPERATING_CLASSES;
+	*eid++ = 2;
+
+	/* Current Operating Class */
+	*eid++ = op_class;
+
+	/* TODO: Advertise all the supported operating classes */
+	*eid++ = 0;
+
+	return eid;
+}
+
+
+static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+				   const struct ieee80211_mgmt *req,
+				   int is_p2p, size_t *resp_len)
+{
+	struct ieee80211_mgmt *resp;
+	u8 *pos, *epos, *csa_pos;
+	size_t buflen;
+
+#define MAX_PROBERESP_LEN 768
+	buflen = MAX_PROBERESP_LEN;
+#ifdef CONFIG_WPS
+	if (hapd->wps_probe_resp_ie)
+		buflen += wpabuf_len(hapd->wps_probe_resp_ie);
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+	if (hapd->p2p_probe_resp_ie)
+		buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_FST
+	if (hapd->iface->fst_ies)
+		buflen += wpabuf_len(hapd->iface->fst_ies);
+#endif /* CONFIG_FST */
+	if (hapd->conf->vendor_elements)
+		buflen += wpabuf_len(hapd->conf->vendor_elements);
+	if (hapd->conf->vendor_vht) {
+		buflen += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) +
+			2 + sizeof(struct ieee80211_vht_operation);
+	}
+
+	buflen += hostapd_mbo_ie_len(hapd);
+
+	resp = os_zalloc(buflen);
+	if (resp == NULL)
+		return NULL;
+
+	epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
+
+	resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+					   WLAN_FC_STYPE_PROBE_RESP);
+	if (req)
+		os_memcpy(resp->da, req->sa, ETH_ALEN);
+	os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
+
+	os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
+	resp->u.probe_resp.beacon_int =
+		host_to_le16(hapd->iconf->beacon_int);
+
+	/* hardware or low-level driver will setup seq_ctrl and timestamp */
+	resp->u.probe_resp.capab_info =
+		host_to_le16(hostapd_own_capab_info(hapd));
+
+	pos = resp->u.probe_resp.variable;
+	*pos++ = WLAN_EID_SSID;
+	*pos++ = hapd->conf->ssid.ssid_len;
+	os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
+	pos += hapd->conf->ssid.ssid_len;
+
+	/* Supported rates */
+	pos = hostapd_eid_supp_rates(hapd, pos);
+
+	/* DS Params */
+	pos = hostapd_eid_ds_params(hapd, pos);
+
+	pos = hostapd_eid_country(hapd, pos, epos - pos);
+
+	/* Power Constraint element */
+	pos = hostapd_eid_pwr_constraint(hapd, pos);
+
+	/* CSA IE */
+	csa_pos = hostapd_eid_csa(hapd, pos);
+	if (csa_pos != pos)
+		hapd->cs_c_off_proberesp = csa_pos - (u8 *) resp - 1;
+	pos = csa_pos;
+
+	/* ERP Information element */
+	pos = hostapd_eid_erp_info(hapd, pos);
+
+	/* Extended supported rates */
+	pos = hostapd_eid_ext_supp_rates(hapd, pos);
+
+	/* RSN, MDIE, WPA */
+	pos = hostapd_eid_wpa(hapd, pos, epos - pos);
+
+	pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
+
+	pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos);
+
+	/* eCSA IE */
+	csa_pos = hostapd_eid_ecsa(hapd, pos);
+	if (csa_pos != pos)
+		hapd->cs_c_off_ecsa_proberesp = csa_pos - (u8 *) resp - 1;
+	pos = csa_pos;
+
+	pos = hostapd_eid_supported_op_classes(hapd, pos);
+
+#ifdef CONFIG_IEEE80211N
+	/* Secondary Channel Offset element */
+	/* TODO: The standard doesn't specify a position for this element. */
+	pos = hostapd_eid_secondary_channel(hapd, pos);
+
+	pos = hostapd_eid_ht_capabilities(hapd, pos);
+	pos = hostapd_eid_ht_operation(hapd, pos);
+#endif /* CONFIG_IEEE80211N */
+
+	pos = hostapd_eid_ext_capab(hapd, pos);
+
+	pos = hostapd_eid_time_adv(hapd, pos);
+	pos = hostapd_eid_time_zone(hapd, pos);
+
+	pos = hostapd_eid_interworking(hapd, pos);
+	pos = hostapd_eid_adv_proto(hapd, pos);
+	pos = hostapd_eid_roaming_consortium(hapd, pos);
+
+#ifdef CONFIG_FST
+	if (hapd->iface->fst_ies) {
+		os_memcpy(pos, wpabuf_head(hapd->iface->fst_ies),
+			  wpabuf_len(hapd->iface->fst_ies));
+		pos += wpabuf_len(hapd->iface->fst_ies);
+	}
+#endif /* CONFIG_FST */
+
+#ifdef CONFIG_IEEE80211AC
+	if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
+		pos = hostapd_eid_vht_capabilities(hapd, pos, 0);
+		pos = hostapd_eid_vht_operation(hapd, pos);
+		pos = hostapd_eid_txpower_envelope(hapd, pos);
+		pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
+	}
+	if (hapd->conf->vendor_vht)
+		pos = hostapd_eid_vendor_vht(hapd, pos);
+#endif /* CONFIG_IEEE80211AC */
+
+	/* Wi-Fi Alliance WMM */
+	pos = hostapd_eid_wmm(hapd, pos);
+
+#ifdef CONFIG_WPS
+	if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
+		os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
+			  wpabuf_len(hapd->wps_probe_resp_ie));
+		pos += wpabuf_len(hapd->wps_probe_resp_ie);
+	}
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_P2P
+	if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
+	    hapd->p2p_probe_resp_ie) {
+		os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
+			  wpabuf_len(hapd->p2p_probe_resp_ie));
+		pos += wpabuf_len(hapd->p2p_probe_resp_ie);
+	}
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_P2P_MANAGER
+	if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
+	    P2P_MANAGE)
+		pos = hostapd_eid_p2p_manage(hapd, pos);
+#endif /* CONFIG_P2P_MANAGER */
+
+#ifdef CONFIG_HS20
+	pos = hostapd_eid_hs20_indication(hapd, pos);
+	pos = hostapd_eid_osen(hapd, pos);
+#endif /* CONFIG_HS20 */
+
+	pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos);
+
+	if (hapd->conf->vendor_elements) {
+		os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
+			  wpabuf_len(hapd->conf->vendor_elements));
+		pos += wpabuf_len(hapd->conf->vendor_elements);
+	}
+
+	*resp_len = pos - (u8 *) resp;
+	return (u8 *) resp;
+}
+
+
+enum ssid_match_result {
+	NO_SSID_MATCH,
+	EXACT_SSID_MATCH,
+	WILDCARD_SSID_MATCH
+};
+
+static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
+					 const u8 *ssid, size_t ssid_len,
+					 const u8 *ssid_list,
+					 size_t ssid_list_len)
+{
+	const u8 *pos, *end;
+	int wildcard = 0;
+
+	if (ssid_len == 0)
+		wildcard = 1;
+	if (ssid_len == hapd->conf->ssid.ssid_len &&
+	    os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
+		return EXACT_SSID_MATCH;
+
+	if (ssid_list == NULL)
+		return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
+
+	pos = ssid_list;
+	end = ssid_list + ssid_list_len;
+	while (end - pos >= 1) {
+		if (2 + pos[1] > end - pos)
+			break;
+		if (pos[1] == 0)
+			wildcard = 1;
+		if (pos[1] == hapd->conf->ssid.ssid_len &&
+		    os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
+			return EXACT_SSID_MATCH;
+		pos += 2 + pos[1];
+	}
+
+	return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
+}
+
+
+void sta_track_expire(struct hostapd_iface *iface, int force)
+{
+	struct os_reltime now;
+	struct hostapd_sta_info *info;
+
+	if (!iface->num_sta_seen)
+		return;
+
+	os_get_reltime(&now);
+	while ((info = dl_list_first(&iface->sta_seen, struct hostapd_sta_info,
+				     list))) {
+		if (!force &&
+		    !os_reltime_expired(&now, &info->last_seen,
+					iface->conf->track_sta_max_age))
+			break;
+		force = 0;
+
+		wpa_printf(MSG_MSGDUMP, "%s: Expire STA tracking entry for "
+			   MACSTR, iface->bss[0]->conf->iface,
+			   MAC2STR(info->addr));
+		dl_list_del(&info->list);
+		iface->num_sta_seen--;
+		sta_track_del(info);
+	}
+}
+
+
+static struct hostapd_sta_info * sta_track_get(struct hostapd_iface *iface,
+					       const u8 *addr)
+{
+	struct hostapd_sta_info *info;
+
+	dl_list_for_each(info, &iface->sta_seen, struct hostapd_sta_info, list)
+		if (os_memcmp(addr, info->addr, ETH_ALEN) == 0)
+			return info;
+
+	return NULL;
+}
+
+
+void sta_track_add(struct hostapd_iface *iface, const u8 *addr)
+{
+	struct hostapd_sta_info *info;
+
+	info = sta_track_get(iface, addr);
+	if (info) {
+		/* Move the most recent entry to the end of the list */
+		dl_list_del(&info->list);
+		dl_list_add_tail(&iface->sta_seen, &info->list);
+		os_get_reltime(&info->last_seen);
+		return;
+	}
+
+	/* Add a new entry */
+	info = os_zalloc(sizeof(*info));
+	if (info == NULL)
+		return;
+	os_memcpy(info->addr, addr, ETH_ALEN);
+	os_get_reltime(&info->last_seen);
+
+	if (iface->num_sta_seen >= iface->conf->track_sta_max_num) {
+		/* Expire oldest entry to make room for a new one */
+		sta_track_expire(iface, 1);
+	}
+
+	wpa_printf(MSG_MSGDUMP, "%s: Add STA tracking entry for "
+		   MACSTR, iface->bss[0]->conf->iface, MAC2STR(addr));
+	dl_list_add_tail(&iface->sta_seen, &info->list);
+	iface->num_sta_seen++;
+}
+
+
+struct hostapd_data *
+sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr,
+		  const char *ifname)
+{
+	struct hapd_interfaces *interfaces = iface->interfaces;
+	size_t i, j;
+
+	for (i = 0; i < interfaces->count; i++) {
+		struct hostapd_data *hapd = NULL;
+
+		iface = interfaces->iface[i];
+		for (j = 0; j < iface->num_bss; j++) {
+			hapd = iface->bss[j];
+			if (os_strcmp(ifname, hapd->conf->iface) == 0)
+				break;
+			hapd = NULL;
+		}
+
+		if (hapd && sta_track_get(iface, addr))
+			return hapd;
+	}
+
+	return NULL;
+}
+
+
+#ifdef CONFIG_TAXONOMY
+void sta_track_claim_taxonomy_info(struct hostapd_iface *iface, const u8 *addr,
+				   struct wpabuf **probe_ie_taxonomy)
+{
+	struct hostapd_sta_info *info;
+
+	info = sta_track_get(iface, addr);
+	if (!info)
+		return;
+
+	wpabuf_free(*probe_ie_taxonomy);
+	*probe_ie_taxonomy = info->probe_ie_taxonomy;
+	info->probe_ie_taxonomy = NULL;
+}
+#endif /* CONFIG_TAXONOMY */
+
+
+void handle_probe_req(struct hostapd_data *hapd,
+		      const struct ieee80211_mgmt *mgmt, size_t len,
+		      int ssi_signal)
+{
+	u8 *resp;
+	struct ieee802_11_elems elems;
+	const u8 *ie;
+	size_t ie_len;
+	size_t i, resp_len;
+	int noack;
+	enum ssid_match_result res;
+	int ret;
+	u16 csa_offs[2];
+	size_t csa_offs_len;
+
+	if (len < IEEE80211_HDRLEN)
+		return;
+	ie = ((const u8 *) mgmt) + IEEE80211_HDRLEN;
+	if (hapd->iconf->track_sta_max_num)
+		sta_track_add(hapd->iface, mgmt->sa);
+	ie_len = len - IEEE80211_HDRLEN;
+
+	for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
+		if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
+					    mgmt->sa, mgmt->da, mgmt->bssid,
+					    ie, ie_len, ssi_signal) > 0)
+			return;
+
+	if (!hapd->iconf->send_probe_response)
+		return;
+
+	if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
+		wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
+			   MAC2STR(mgmt->sa));
+		return;
+	}
+
+	if ((!elems.ssid || !elems.supp_rates)) {
+		wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
+			   "without SSID or supported rates element",
+			   MAC2STR(mgmt->sa));
+		return;
+	}
+
+	/*
+	 * No need to reply if the Probe Request frame was sent on an adjacent
+	 * channel. IEEE Std 802.11-2012 describes this as a requirement for an
+	 * AP with dot11RadioMeasurementActivated set to true, but strictly
+	 * speaking does not allow such ignoring of Probe Request frames if
+	 * dot11RadioMeasurementActivated is false. Anyway, this can help reduce
+	 * number of unnecessary Probe Response frames for cases where the STA
+	 * is less likely to see them (Probe Request frame sent on a
+	 * neighboring, but partially overlapping, channel).
+	 */
+	if (elems.ds_params &&
+	    hapd->iface->current_mode &&
+	    (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G ||
+	     hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B) &&
+	    hapd->iconf->channel != elems.ds_params[0]) {
+		wpa_printf(MSG_DEBUG,
+			   "Ignore Probe Request due to DS Params mismatch: chan=%u != ds.chan=%u",
+			   hapd->iconf->channel, elems.ds_params[0]);
+		return;
+	}
+
+#ifdef CONFIG_P2P
+	if (hapd->p2p && hapd->p2p_group && elems.wps_ie) {
+		struct wpabuf *wps;
+		wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
+		if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
+			wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
+				   "due to mismatch with Requested Device "
+				   "Type");
+			wpabuf_free(wps);
+			return;
+		}
+		wpabuf_free(wps);
+	}
+
+	if (hapd->p2p && hapd->p2p_group && elems.p2p) {
+		struct wpabuf *p2p;
+		p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE);
+		if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) {
+			wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
+				   "due to mismatch with Device ID");
+			wpabuf_free(p2p);
+			return;
+		}
+		wpabuf_free(p2p);
+	}
+#endif /* CONFIG_P2P */
+
+	if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
+	    elems.ssid_list_len == 0) {
+		wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
+			   "broadcast SSID ignored", MAC2STR(mgmt->sa));
+		return;
+	}
+
+#ifdef CONFIG_P2P
+	if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
+	    elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
+	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
+		      P2P_WILDCARD_SSID_LEN) == 0) {
+		/* Process P2P Wildcard SSID like Wildcard SSID */
+		elems.ssid_len = 0;
+	}
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_TAXONOMY
+	{
+		struct sta_info *sta;
+		struct hostapd_sta_info *info;
+
+		if ((sta = ap_get_sta(hapd, mgmt->sa)) != NULL) {
+			taxonomy_sta_info_probe_req(hapd, sta, ie, ie_len);
+		} else if ((info = sta_track_get(hapd->iface,
+						 mgmt->sa)) != NULL) {
+			taxonomy_hostapd_sta_info_probe_req(hapd, info,
+							    ie, ie_len);
+		}
+	}
+#endif /* CONFIG_TAXONOMY */
+
+	res = ssid_match(hapd, elems.ssid, elems.ssid_len,
+			 elems.ssid_list, elems.ssid_list_len);
+	if (res == NO_SSID_MATCH) {
+		if (!(mgmt->da[0] & 0x01)) {
+			wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
+				   " for foreign SSID '%s' (DA " MACSTR ")%s",
+				   MAC2STR(mgmt->sa),
+				   wpa_ssid_txt(elems.ssid, elems.ssid_len),
+				   MAC2STR(mgmt->da),
+				   elems.ssid_list ? " (SSID list)" : "");
+		}
+		return;
+	}
+
+#ifdef CONFIG_INTERWORKING
+	if (hapd->conf->interworking &&
+	    elems.interworking && elems.interworking_len >= 1) {
+		u8 ant = elems.interworking[0] & 0x0f;
+		if (ant != INTERWORKING_ANT_WILDCARD &&
+		    ant != hapd->conf->access_network_type) {
+			wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
+				   " for mismatching ANT %u ignored",
+				   MAC2STR(mgmt->sa), ant);
+			return;
+		}
+	}
+
+	if (hapd->conf->interworking && elems.interworking &&
+	    (elems.interworking_len == 7 || elems.interworking_len == 9)) {
+		const u8 *hessid;
+		if (elems.interworking_len == 7)
+			hessid = elems.interworking + 1;
+		else
+			hessid = elems.interworking + 1 + 2;
+		if (!is_broadcast_ether_addr(hessid) &&
+		    os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) {
+			wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
+				   " for mismatching HESSID " MACSTR
+				   " ignored",
+				   MAC2STR(mgmt->sa), MAC2STR(hessid));
+			return;
+		}
+	}
+#endif /* CONFIG_INTERWORKING */
+
+#ifdef CONFIG_P2P
+	if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
+	    supp_rates_11b_only(&elems)) {
+		/* Indicates support for 11b rates only */
+		wpa_printf(MSG_EXCESSIVE, "P2P: Ignore Probe Request from "
+			   MACSTR " with only 802.11b rates",
+			   MAC2STR(mgmt->sa));
+		return;
+	}
+#endif /* CONFIG_P2P */
+
+	/* TODO: verify that supp_rates contains at least one matching rate
+	 * with AP configuration */
+
+	if (hapd->conf->no_probe_resp_if_seen_on &&
+	    is_multicast_ether_addr(mgmt->da) &&
+	    is_multicast_ether_addr(mgmt->bssid) &&
+	    sta_track_seen_on(hapd->iface, mgmt->sa,
+			      hapd->conf->no_probe_resp_if_seen_on)) {
+		wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
+			   " since STA has been seen on %s",
+			   hapd->conf->iface, MAC2STR(mgmt->sa),
+			   hapd->conf->no_probe_resp_if_seen_on);
+		return;
+	}
+
+	if (hapd->conf->no_probe_resp_if_max_sta &&
+	    is_multicast_ether_addr(mgmt->da) &&
+	    is_multicast_ether_addr(mgmt->bssid) &&
+	    hapd->num_sta >= hapd->conf->max_num_sta &&
+	    !ap_get_sta(hapd, mgmt->sa)) {
+		wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
+			   " since no room for additional STA",
+			   hapd->conf->iface, MAC2STR(mgmt->sa));
+		return;
+	}
+
+#ifdef CONFIG_TESTING_OPTIONS
+	if (hapd->iconf->ignore_probe_probability > 0.0 &&
+	    drand48() < hapd->iconf->ignore_probe_probability) {
+		wpa_printf(MSG_INFO,
+			   "TESTING: ignoring probe request from " MACSTR,
+			   MAC2STR(mgmt->sa));
+		return;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+	resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+				      &resp_len);
+	if (resp == NULL)
+		return;
+
+	/*
+	 * If this is a broadcast probe request, apply no ack policy to avoid
+	 * excessive retries.
+	 */
+	noack = !!(res == WILDCARD_SSID_MATCH &&
+		   is_broadcast_ether_addr(mgmt->da));
+
+	csa_offs_len = 0;
+	if (hapd->csa_in_progress) {
+		if (hapd->cs_c_off_proberesp)
+			csa_offs[csa_offs_len++] =
+				hapd->cs_c_off_proberesp;
+
+		if (hapd->cs_c_off_ecsa_proberesp)
+			csa_offs[csa_offs_len++] =
+				hapd->cs_c_off_ecsa_proberesp;
+	}
+
+	ret = hostapd_drv_send_mlme_csa(hapd, resp, resp_len, noack,
+					csa_offs_len ? csa_offs : NULL,
+					csa_offs_len);
+
+	if (ret < 0)
+		wpa_printf(MSG_INFO, "handle_probe_req: send failed");
+
+	os_free(resp);
+
+	wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
+		   "SSID", MAC2STR(mgmt->sa),
+		   elems.ssid_len == 0 ? "broadcast" : "our");
+}
+
+
+static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
+					size_t *resp_len)
+{
+	/* check probe response offloading caps and print warnings */
+	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
+		return NULL;
+
+#ifdef CONFIG_WPS
+	if (hapd->conf->wps_state && hapd->wps_probe_resp_ie &&
+	    (!(hapd->iface->probe_resp_offloads &
+	       (WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS |
+		WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2))))
+		wpa_printf(MSG_WARNING, "Device is trying to offload WPS "
+			   "Probe Response while not supporting this");
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_P2P
+	if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie &&
+	    !(hapd->iface->probe_resp_offloads &
+	      WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P))
+		wpa_printf(MSG_WARNING, "Device is trying to offload P2P "
+			   "Probe Response while not supporting this");
+#endif  /* CONFIG_P2P */
+
+	if (hapd->conf->interworking &&
+	    !(hapd->iface->probe_resp_offloads &
+	      WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING))
+		wpa_printf(MSG_WARNING, "Device is trying to offload "
+			   "Interworking Probe Response while not supporting "
+			   "this");
+
+	/* Generate a Probe Response template for the non-P2P case */
+	return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len);
+}
+
+#endif /* NEED_AP_MLME */
+
+
+void sta_track_del(struct hostapd_sta_info *info)
+{
+#ifdef CONFIG_TAXONOMY
+	wpabuf_free(info->probe_ie_taxonomy);
+	info->probe_ie_taxonomy = NULL;
+#endif /* CONFIG_TAXONOMY */
+	os_free(info);
+}
+
+
+int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+			       struct wpa_driver_ap_params *params)
+{
+	struct ieee80211_mgmt *head = NULL;
+	u8 *tail = NULL;
+	size_t head_len = 0, tail_len = 0;
+	u8 *resp = NULL;
+	size_t resp_len = 0;
+#ifdef NEED_AP_MLME
+	u16 capab_info;
+	u8 *pos, *tailpos, *csa_pos;
+
+#define BEACON_HEAD_BUF_SIZE 256
+#define BEACON_TAIL_BUF_SIZE 512
+	head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+	tail_len = BEACON_TAIL_BUF_SIZE;
+#ifdef CONFIG_WPS
+	if (hapd->conf->wps_state && hapd->wps_beacon_ie)
+		tail_len += wpabuf_len(hapd->wps_beacon_ie);
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+	if (hapd->p2p_beacon_ie)
+		tail_len += wpabuf_len(hapd->p2p_beacon_ie);
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_FST
+	if (hapd->iface->fst_ies)
+		tail_len += wpabuf_len(hapd->iface->fst_ies);
+#endif /* CONFIG_FST */
+	if (hapd->conf->vendor_elements)
+		tail_len += wpabuf_len(hapd->conf->vendor_elements);
+
+#ifdef CONFIG_IEEE80211AC
+	if (hapd->conf->vendor_vht) {
+		tail_len += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) +
+			2 + sizeof(struct ieee80211_vht_operation);
+	}
+#endif /* CONFIG_IEEE80211AC */
+
+	tail_len += hostapd_mbo_ie_len(hapd);
+
+	tailpos = tail = os_malloc(tail_len);
+	if (head == NULL || tail == NULL) {
+		wpa_printf(MSG_ERROR, "Failed to set beacon data");
+		os_free(head);
+		os_free(tail);
+		return -1;
+	}
+
+	head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+					   WLAN_FC_STYPE_BEACON);
+	head->duration = host_to_le16(0);
+	os_memset(head->da, 0xff, ETH_ALEN);
+
+	os_memcpy(head->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN);
+	head->u.beacon.beacon_int =
+		host_to_le16(hapd->iconf->beacon_int);
+
+	/* hardware or low-level driver will setup seq_ctrl and timestamp */
+	capab_info = hostapd_own_capab_info(hapd);
+	head->u.beacon.capab_info = host_to_le16(capab_info);
+	pos = &head->u.beacon.variable[0];
+
+	/* SSID */
+	*pos++ = WLAN_EID_SSID;
+	if (hapd->conf->ignore_broadcast_ssid == 2) {
+		/* clear the data, but keep the correct length of the SSID */
+		*pos++ = hapd->conf->ssid.ssid_len;
+		os_memset(pos, 0, hapd->conf->ssid.ssid_len);
+		pos += hapd->conf->ssid.ssid_len;
+	} else if (hapd->conf->ignore_broadcast_ssid) {
+		*pos++ = 0; /* empty SSID */
+	} else {
+		*pos++ = hapd->conf->ssid.ssid_len;
+		os_memcpy(pos, hapd->conf->ssid.ssid,
+			  hapd->conf->ssid.ssid_len);
+		pos += hapd->conf->ssid.ssid_len;
+	}
+
+	/* Supported rates */
+	pos = hostapd_eid_supp_rates(hapd, pos);
+
+	/* DS Params */
+	pos = hostapd_eid_ds_params(hapd, pos);
+
+	head_len = pos - (u8 *) head;
+
+	tailpos = hostapd_eid_country(hapd, tailpos,
+				      tail + BEACON_TAIL_BUF_SIZE - tailpos);
+
+	/* Power Constraint element */
+	tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
+
+	/* CSA IE */
+	csa_pos = hostapd_eid_csa(hapd, tailpos);
+	if (csa_pos != tailpos)
+		hapd->cs_c_off_beacon = csa_pos - tail - 1;
+	tailpos = csa_pos;
+
+	/* ERP Information element */
+	tailpos = hostapd_eid_erp_info(hapd, tailpos);
+
+	/* Extended supported rates */
+	tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
+
+	/* RSN, MDIE, WPA */
+	tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
+				  tailpos);
+
+	tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos,
+					       tail + BEACON_TAIL_BUF_SIZE -
+					       tailpos);
+
+	tailpos = hostapd_eid_bss_load(hapd, tailpos,
+				       tail + BEACON_TAIL_BUF_SIZE - tailpos);
+
+	/* eCSA IE */
+	csa_pos = hostapd_eid_ecsa(hapd, tailpos);
+	if (csa_pos != tailpos)
+		hapd->cs_c_off_ecsa_beacon = csa_pos - tail - 1;
+	tailpos = csa_pos;
+
+	tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
+
+#ifdef CONFIG_IEEE80211N
+	/* Secondary Channel Offset element */
+	/* TODO: The standard doesn't specify a position for this element. */
+	tailpos = hostapd_eid_secondary_channel(hapd, tailpos);
+
+	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+#endif /* CONFIG_IEEE80211N */
+
+	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+
+	/*
+	 * TODO: Time Advertisement element should only be included in some
+	 * DTIM Beacon frames.
+	 */
+	tailpos = hostapd_eid_time_adv(hapd, tailpos);
+
+	tailpos = hostapd_eid_interworking(hapd, tailpos);
+	tailpos = hostapd_eid_adv_proto(hapd, tailpos);
+	tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
+
+#ifdef CONFIG_FST
+	if (hapd->iface->fst_ies) {
+		os_memcpy(tailpos, wpabuf_head(hapd->iface->fst_ies),
+			  wpabuf_len(hapd->iface->fst_ies));
+		tailpos += wpabuf_len(hapd->iface->fst_ies);
+	}
+#endif /* CONFIG_FST */
+
+#ifdef CONFIG_IEEE80211AC
+	if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
+		tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0);
+		tailpos = hostapd_eid_vht_operation(hapd, tailpos);
+		tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
+		tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
+	}
+	if (hapd->conf->vendor_vht)
+		tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
+#endif /* CONFIG_IEEE80211AC */
+
+	/* Wi-Fi Alliance WMM */
+	tailpos = hostapd_eid_wmm(hapd, tailpos);
+
+#ifdef CONFIG_WPS
+	if (hapd->conf->wps_state && hapd->wps_beacon_ie) {
+		os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie),
+			  wpabuf_len(hapd->wps_beacon_ie));
+		tailpos += wpabuf_len(hapd->wps_beacon_ie);
+	}
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_P2P
+	if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) {
+		os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie),
+			  wpabuf_len(hapd->p2p_beacon_ie));
+		tailpos += wpabuf_len(hapd->p2p_beacon_ie);
+	}
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_P2P_MANAGER
+	if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
+	    P2P_MANAGE)
+		tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
+#endif /* CONFIG_P2P_MANAGER */
+
+#ifdef CONFIG_HS20
+	tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
+	tailpos = hostapd_eid_osen(hapd, tailpos);
+#endif /* CONFIG_HS20 */
+
+	tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos);
+
+	if (hapd->conf->vendor_elements) {
+		os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
+			  wpabuf_len(hapd->conf->vendor_elements));
+		tailpos += wpabuf_len(hapd->conf->vendor_elements);
+	}
+
+	tail_len = tailpos > tail ? tailpos - tail : 0;
+
+	resp = hostapd_probe_resp_offloads(hapd, &resp_len);
+#endif /* NEED_AP_MLME */
+
+	os_memset(params, 0, sizeof(*params));
+	params->head = (u8 *) head;
+	params->head_len = head_len;
+	params->tail = tail;
+	params->tail_len = tail_len;
+	params->proberesp = resp;
+	params->proberesp_len = resp_len;
+	params->dtim_period = hapd->conf->dtim_period;
+	params->beacon_int = hapd->iconf->beacon_int;
+	params->basic_rates = hapd->iface->basic_rates;
+	params->ssid = hapd->conf->ssid.ssid;
+	params->ssid_len = hapd->conf->ssid.ssid_len;
+	if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) ==
+	    (WPA_PROTO_WPA | WPA_PROTO_RSN))
+		params->pairwise_ciphers = hapd->conf->wpa_pairwise |
+			hapd->conf->rsn_pairwise;
+	else if (hapd->conf->wpa & WPA_PROTO_RSN)
+		params->pairwise_ciphers = hapd->conf->rsn_pairwise;
+	else if (hapd->conf->wpa & WPA_PROTO_WPA)
+		params->pairwise_ciphers = hapd->conf->wpa_pairwise;
+	params->group_cipher = hapd->conf->wpa_group;
+	params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
+	params->auth_algs = hapd->conf->auth_algs;
+	params->wpa_version = hapd->conf->wpa;
+	params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
+		(hapd->conf->ieee802_1x &&
+		 (hapd->conf->default_wep_key_len ||
+		  hapd->conf->individual_wep_key_len));
+	switch (hapd->conf->ignore_broadcast_ssid) {
+	case 0:
+		params->hide_ssid = NO_SSID_HIDING;
+		break;
+	case 1:
+		params->hide_ssid = HIDDEN_SSID_ZERO_LEN;
+		break;
+	case 2:
+		params->hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
+		break;
+	}
+	params->isolate = hapd->conf->isolate;
+	params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK;
+#ifdef NEED_AP_MLME
+	params->cts_protect = !!(ieee802_11_erp_info(hapd) &
+				ERP_INFO_USE_PROTECTION);
+	params->preamble = hapd->iface->num_sta_no_short_preamble == 0 &&
+		hapd->iconf->preamble == SHORT_PREAMBLE;
+	if (hapd->iface->current_mode &&
+	    hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
+		params->short_slot_time =
+			hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1;
+	else
+		params->short_slot_time = -1;
+	if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
+		params->ht_opmode = -1;
+	else
+		params->ht_opmode = hapd->iface->ht_op_mode;
+#endif /* NEED_AP_MLME */
+	params->interworking = hapd->conf->interworking;
+	if (hapd->conf->interworking &&
+	    !is_zero_ether_addr(hapd->conf->hessid))
+		params->hessid = hapd->conf->hessid;
+	params->access_network_type = hapd->conf->access_network_type;
+	params->ap_max_inactivity = hapd->conf->ap_max_inactivity;
+#ifdef CONFIG_P2P
+	params->p2p_go_ctwindow = hapd->iconf->p2p_go_ctwindow;
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_HS20
+	params->disable_dgaf = hapd->conf->disable_dgaf;
+	if (hapd->conf->osen) {
+		params->privacy = 1;
+		params->osen = 1;
+	}
+#endif /* CONFIG_HS20 */
+	params->pbss = hapd->conf->pbss;
+	return 0;
+}
+
+
+void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
+{
+	os_free(params->tail);
+	params->tail = NULL;
+	os_free(params->head);
+	params->head = NULL;
+	os_free(params->proberesp);
+	params->proberesp = NULL;
+}
+
+
+int ieee802_11_set_beacon(struct hostapd_data *hapd)
+{
+	struct wpa_driver_ap_params params;
+	struct hostapd_freq_params freq;
+	struct hostapd_iface *iface = hapd->iface;
+	struct hostapd_config *iconf = iface->conf;
+	struct wpabuf *beacon, *proberesp, *assocresp;
+	int res, ret = -1;
+
+	if (hapd->csa_in_progress) {
+		wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period");
+		return -1;
+	}
+
+	hapd->beacon_set_done = 1;
+
+	if (ieee802_11_build_ap_params(hapd, &params) < 0)
+		return -1;
+
+	if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
+	    0)
+		goto fail;
+
+	params.beacon_ies = beacon;
+	params.proberesp_ies = proberesp;
+	params.assocresp_ies = assocresp;
+	params.reenable = hapd->reenable_beacon;
+	hapd->reenable_beacon = 0;
+
+	if (iface->current_mode &&
+	    hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
+				    iconf->channel, iconf->ieee80211n,
+				    iconf->ieee80211ac,
+				    iconf->secondary_channel,
+				    iconf->vht_oper_chwidth,
+				    iconf->vht_oper_centr_freq_seg0_idx,
+				    iconf->vht_oper_centr_freq_seg1_idx,
+				    iface->current_mode->vht_capab) == 0)
+		params.freq = &freq;
+
+	res = hostapd_drv_set_ap(hapd, &params);
+	hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
+	if (res)
+		wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
+	else
+		ret = 0;
+fail:
+	ieee802_11_free_ap_params(&params);
+	return ret;
+}
+
+
+int ieee802_11_set_beacons(struct hostapd_iface *iface)
+{
+	size_t i;
+	int ret = 0;
+
+	for (i = 0; i < iface->num_bss; i++) {
+		if (iface->bss[i]->started &&
+		    ieee802_11_set_beacon(iface->bss[i]) < 0)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+
+/* only update beacons if started */
+int ieee802_11_update_beacons(struct hostapd_iface *iface)
+{
+	size_t i;
+	int ret = 0;
+
+	for (i = 0; i < iface->num_bss; i++) {
+		if (iface->bss[i]->beacon_set_done && iface->bss[i]->started &&
+		    ieee802_11_set_beacon(iface->bss[i]) < 0)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+#endif /* CONFIG_NATIVE_WINDOWS */

+ 28 - 0
EVSE/GPL/hostapd-2.6/src/ap/beacon.d

@@ -0,0 +1,28 @@
+../src/ap/beacon.o: ../src/ap/beacon.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/hw_features_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/p2p/p2p.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ ../src/ap/hostapd.h ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/vlan.h ../src/ap/ieee802_11.h ../src/ap/wpa_auth.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/eapol_common.h \
+ ../src/ap/wmm.h ../src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/p2p_hostapd.h ../src/ap/ap_drv_ops.h ../src/ap/beacon.h \
+ ../src/ap/hs20.h ../src/ap/dfs.h ../src/ap/taxonomy.h

+ 33 - 0
EVSE/GPL/hostapd-2.6/src/ap/beacon.h

@@ -0,0 +1,33 @@
+/*
+ * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
+ * Copyright (c) 2002-2004, Instant802 Networks, Inc.
+ * Copyright (c) 2005-2006, Devicescape Software, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BEACON_H
+#define BEACON_H
+
+struct ieee80211_mgmt;
+
+void handle_probe_req(struct hostapd_data *hapd,
+		      const struct ieee80211_mgmt *mgmt, size_t len,
+		      int ssi_signal);
+int ieee802_11_set_beacon(struct hostapd_data *hapd);
+int ieee802_11_set_beacons(struct hostapd_iface *iface);
+int ieee802_11_update_beacons(struct hostapd_iface *iface);
+int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+			       struct wpa_driver_ap_params *params);
+void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params);
+void sta_track_add(struct hostapd_iface *iface, const u8 *addr);
+void sta_track_del(struct hostapd_sta_info *info);
+void sta_track_expire(struct hostapd_iface *iface, int force);
+struct hostapd_data *
+sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr,
+		  const char *ifname);
+void sta_track_claim_taxonomy_info(struct hostapd_iface *iface, const u8 *addr,
+				   struct wpabuf **probe_ie_taxonomy);
+
+#endif /* BEACON_H */

+ 65 - 0
EVSE/GPL/hostapd-2.6/src/ap/bss_load.c

@@ -0,0 +1,65 @@
+/*
+ * BSS Load Element / Channel Utilization
+ * Copyright (c) 2014, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "hostapd.h"
+#include "bss_load.h"
+#include "ap_drv_ops.h"
+#include "beacon.h"
+
+
+static void update_channel_utilization(void *eloop_data, void *user_data)
+{
+	struct hostapd_data *hapd = eloop_data;
+	unsigned int sec, usec;
+	int err;
+
+	if (!(hapd->beacon_set_done && hapd->started))
+		return;
+
+	err = hostapd_drv_get_survey(hapd, hapd->iface->freq);
+	if (err) {
+		wpa_printf(MSG_ERROR, "BSS Load: Failed to get survey data");
+		return;
+	}
+
+	ieee802_11_set_beacon(hapd);
+
+	sec = ((hapd->bss_load_update_timeout / 1000) * 1024) / 1000;
+	usec = (hapd->bss_load_update_timeout % 1000) * 1024;
+	eloop_register_timeout(sec, usec, update_channel_utilization, hapd,
+			       NULL);
+}
+
+
+int bss_load_update_init(struct hostapd_data *hapd)
+{
+	struct hostapd_bss_config *conf = hapd->conf;
+	struct hostapd_config *iconf = hapd->iconf;
+	unsigned int sec, usec;
+
+	if (!conf->bss_load_update_period || !iconf->beacon_int)
+		return -1;
+
+	hapd->bss_load_update_timeout = conf->bss_load_update_period *
+					iconf->beacon_int;
+	sec = ((hapd->bss_load_update_timeout / 1000) * 1024) / 1000;
+	usec = (hapd->bss_load_update_timeout % 1000) * 1024;
+	eloop_register_timeout(sec, usec, update_channel_utilization, hapd,
+			       NULL);
+	return 0;
+}
+
+
+void bss_load_update_deinit(struct hostapd_data *hapd)
+{
+	eloop_cancel_timeout(update_channel_utilization, hapd, NULL);
+}

+ 23 - 0
EVSE/GPL/hostapd-2.6/src/ap/bss_load.d

@@ -0,0 +1,23 @@
+../src/ap/bss_load.o: ../src/ap/bss_load.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/eloop.h \
+ ../src/ap/hostapd.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/vlan.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ ../src/ap/bss_load.h ../src/ap/ap_drv_ops.h ../src/ap/beacon.h

+ 17 - 0
EVSE/GPL/hostapd-2.6/src/ap/bss_load.h

@@ -0,0 +1,17 @@
+/*
+ * BSS load update
+ * Copyright (c) 2014, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BSS_LOAD_UPDATE_H
+#define BSS_LOAD_UPDATE_H
+
+
+int bss_load_update_init(struct hostapd_data *hapd);
+void bss_load_update_deinit(struct hostapd_data *hapd);
+
+
+#endif /* BSS_LOAD_UPDATE_H */

+ 641 - 0
EVSE/GPL/hostapd-2.6/src/ap/ctrl_iface_ap.c

@@ -0,0 +1,641 @@
+/*
+ * Control interface for shared AP commands
+ * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/sae.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "fst/fst_ctrl_iface.h"
+#include "hostapd.h"
+#include "ieee802_1x.h"
+#include "wpa_auth.h"
+#include "ieee802_11.h"
+#include "sta_info.h"
+#include "wps_hostapd.h"
+#include "p2p_hostapd.h"
+#include "ctrl_iface_ap.h"
+#include "ap_drv_ops.h"
+#include "mbo_ap.h"
+#include "taxonomy.h"
+
+
+static int hostapd_get_sta_tx_rx(struct hostapd_data *hapd,
+				 struct sta_info *sta,
+				 char *buf, size_t buflen)
+{
+	struct hostap_sta_driver_data data;
+	int ret;
+
+	if (hostapd_drv_read_sta_data(hapd, &data, sta->addr) < 0)
+		return 0;
+
+	ret = os_snprintf(buf, buflen, "rx_packets=%lu\ntx_packets=%lu\n"
+			  "rx_bytes=%llu\ntx_bytes=%llu\ninactive_msec=%lu\n",
+			  data.rx_packets, data.tx_packets,
+			  data.rx_bytes, data.tx_bytes, data.inactive_msec);
+	if (os_snprintf_error(buflen, ret))
+		return 0;
+	return ret;
+}
+
+
+static int hostapd_get_sta_conn_time(struct sta_info *sta,
+				     char *buf, size_t buflen)
+{
+	struct os_reltime age;
+	int ret;
+
+	if (!sta->connected_time.sec)
+		return 0;
+
+	os_reltime_age(&sta->connected_time, &age);
+
+	ret = os_snprintf(buf, buflen, "connected_time=%u\n",
+			  (unsigned int) age.sec);
+	if (os_snprintf_error(buflen, ret))
+		return 0;
+	return ret;
+}
+
+
+static const char * timeout_next_str(int val)
+{
+	switch (val) {
+	case STA_NULLFUNC:
+		return "NULLFUNC POLL";
+	case STA_DISASSOC:
+		return "DISASSOC";
+	case STA_DEAUTH:
+		return "DEAUTH";
+	case STA_REMOVE:
+		return "REMOVE";
+	case STA_DISASSOC_FROM_CLI:
+		return "DISASSOC_FROM_CLI";
+	}
+
+	return "?";
+}
+
+
+static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
+				      struct sta_info *sta,
+				      char *buf, size_t buflen)
+{
+	int len, res, ret, i;
+
+	if (!sta)
+		return 0;
+
+	len = 0;
+	ret = os_snprintf(buf + len, buflen - len, MACSTR "\nflags=",
+			  MAC2STR(sta->addr));
+	if (os_snprintf_error(buflen - len, ret))
+		return len;
+	len += ret;
+
+	ret = ap_sta_flags_txt(sta->flags, buf + len, buflen - len);
+	if (ret < 0)
+		return len;
+	len += ret;
+
+	ret = os_snprintf(buf + len, buflen - len, "\naid=%d\ncapability=0x%x\n"
+			  "listen_interval=%d\nsupported_rates=",
+			  sta->aid, sta->capability, sta->listen_interval);
+	if (os_snprintf_error(buflen - len, ret))
+		return len;
+	len += ret;
+
+	for (i = 0; i < sta->supported_rates_len; i++) {
+		ret = os_snprintf(buf + len, buflen - len, "%02x%s",
+				  sta->supported_rates[i],
+				  i + 1 < sta->supported_rates_len ? " " : "");
+		if (os_snprintf_error(buflen - len, ret))
+			return len;
+		len += ret;
+	}
+
+	ret = os_snprintf(buf + len, buflen - len, "\ntimeout_next=%s\n",
+			  timeout_next_str(sta->timeout_next));
+	if (os_snprintf_error(buflen - len, ret))
+		return len;
+	len += ret;
+
+	res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len);
+	if (res >= 0)
+		len += res;
+	res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len);
+	if (res >= 0)
+		len += res;
+	res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len);
+	if (res >= 0)
+		len += res;
+	res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len,
+				      buflen - len);
+	if (res >= 0)
+		len += res;
+	res = hostapd_p2p_get_mib_sta(hapd, sta, buf + len, buflen - len);
+	if (res >= 0)
+		len += res;
+
+	len += hostapd_get_sta_tx_rx(hapd, sta, buf + len, buflen - len);
+	len += hostapd_get_sta_conn_time(sta, buf + len, buflen - len);
+
+#ifdef CONFIG_SAE
+	if (sta->sae && sta->sae->state == SAE_ACCEPTED) {
+		res = os_snprintf(buf + len, buflen - len, "sae_group=%d\n",
+				  sta->sae->group);
+		if (!os_snprintf_error(buflen - len, res))
+			len += res;
+	}
+#endif /* CONFIG_SAE */
+
+	if (sta->vlan_id > 0) {
+		res = os_snprintf(buf + len, buflen - len, "vlan_id=%d\n",
+				  sta->vlan_id);
+		if (!os_snprintf_error(buflen - len, res))
+			len += res;
+	}
+
+	res = mbo_ap_get_info(sta, buf + len, buflen - len);
+	if (res >= 0)
+		len += res;
+
+	if (sta->supp_op_classes &&
+	    buflen - len > (unsigned) (17 + 2 * sta->supp_op_classes[0])) {
+		len += os_snprintf(buf + len, buflen - len, "supp_op_classes=");
+		len += wpa_snprintf_hex(buf + len, buflen - len,
+					sta->supp_op_classes + 1,
+					sta->supp_op_classes[0]);
+		len += os_snprintf(buf + len, buflen - len, "\n");
+	}
+
+	return len;
+}
+
+
+int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
+				 char *buf, size_t buflen)
+{
+	return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen);
+}
+
+
+int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
+			   char *buf, size_t buflen)
+{
+	u8 addr[ETH_ALEN];
+	int ret;
+	const char *pos;
+	struct sta_info *sta;
+
+	if (hwaddr_aton(txtaddr, addr)) {
+		ret = os_snprintf(buf, buflen, "FAIL\n");
+		if (os_snprintf_error(buflen, ret))
+			return 0;
+		return ret;
+	}
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta == NULL)
+		return -1;
+
+	pos = os_strchr(txtaddr, ' ');
+	if (pos) {
+		pos++;
+
+#ifdef HOSTAPD_DUMP_STATE
+		if (os_strcmp(pos, "eapol") == 0) {
+			if (sta->eapol_sm == NULL)
+				return -1;
+			return eapol_auth_dump_state(sta->eapol_sm, buf,
+						     buflen);
+		}
+#endif /* HOSTAPD_DUMP_STATE */
+
+		return -1;
+	}
+
+	ret = hostapd_ctrl_iface_sta_mib(hapd, sta, buf, buflen);
+	ret += fst_ctrl_iface_mb_info(addr, buf + ret, buflen - ret);
+
+	return ret;
+}
+
+
+int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
+				char *buf, size_t buflen)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+	int ret;
+
+	if (hwaddr_aton(txtaddr, addr) ||
+	    (sta = ap_get_sta(hapd, addr)) == NULL) {
+		ret = os_snprintf(buf, buflen, "FAIL\n");
+		if (os_snprintf_error(buflen, ret))
+			return 0;
+		return ret;
+	}
+
+	if (!sta->next)
+		return 0;
+
+	return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
+}
+
+
+#ifdef CONFIG_P2P_MANAGER
+static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
+				  u8 minor_reason_code, const u8 *addr)
+{
+	struct ieee80211_mgmt *mgmt;
+	int ret;
+	u8 *pos;
+
+	if (!hapd->drv_priv || !hapd->driver->send_frame)
+		return -1;
+
+	mgmt = os_zalloc(sizeof(*mgmt) + 100);
+	if (mgmt == NULL)
+		return -1;
+
+	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype);
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "P2P: Disconnect STA " MACSTR
+		" with minor reason code %u (stype=%u (%s))",
+		MAC2STR(addr), minor_reason_code, stype,
+		fc2str(le_to_host16(mgmt->frame_control)));
+
+	os_memcpy(mgmt->da, addr, ETH_ALEN);
+	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
+	if (stype == WLAN_FC_STYPE_DEAUTH) {
+		mgmt->u.deauth.reason_code =
+			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+		pos = (u8 *) (&mgmt->u.deauth.reason_code + 1);
+	} else {
+		mgmt->u.disassoc.reason_code =
+			host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+		pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1);
+	}
+
+	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
+	*pos++ = 4 + 3 + 1;
+	WPA_PUT_BE32(pos, P2P_IE_VENDOR_TYPE);
+	pos += 4;
+
+	*pos++ = P2P_ATTR_MINOR_REASON_CODE;
+	WPA_PUT_LE16(pos, 1);
+	pos += 2;
+	*pos++ = minor_reason_code;
+
+	ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt,
+				       pos - (u8 *) mgmt, 1);
+	os_free(mgmt);
+
+	return ret < 0 ? -1 : 0;
+}
+#endif /* CONFIG_P2P_MANAGER */
+
+
+int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
+				      const char *txtaddr)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+	const char *pos;
+	u16 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
+
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s",
+		txtaddr);
+
+	if (hwaddr_aton(txtaddr, addr))
+		return -1;
+
+	pos = os_strstr(txtaddr, " reason=");
+	if (pos)
+		reason = atoi(pos + 8);
+
+	pos = os_strstr(txtaddr, " test=");
+	if (pos) {
+		struct ieee80211_mgmt mgmt;
+		int encrypt;
+		if (!hapd->drv_priv || !hapd->driver->send_frame)
+			return -1;
+		pos += 6;
+		encrypt = atoi(pos);
+		os_memset(&mgmt, 0, sizeof(mgmt));
+		mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+						  WLAN_FC_STYPE_DEAUTH);
+		os_memcpy(mgmt.da, addr, ETH_ALEN);
+		os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
+		os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
+		mgmt.u.deauth.reason_code = host_to_le16(reason);
+		if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
+					     IEEE80211_HDRLEN +
+					     sizeof(mgmt.u.deauth),
+					     encrypt) < 0)
+			return -1;
+		return 0;
+	}
+
+#ifdef CONFIG_P2P_MANAGER
+	pos = os_strstr(txtaddr, " p2p=");
+	if (pos) {
+		return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH,
+					      atoi(pos + 5), addr);
+	}
+#endif /* CONFIG_P2P_MANAGER */
+
+	if (os_strstr(txtaddr, " tx=0"))
+		hostapd_drv_sta_remove(hapd, addr);
+	else
+		hostapd_drv_sta_deauth(hapd, addr, reason);
+	sta = ap_get_sta(hapd, addr);
+	if (sta)
+		ap_sta_deauthenticate(hapd, sta, reason);
+	else if (addr[0] == 0xff)
+		hostapd_free_stas(hapd);
+
+	return 0;
+}
+
+
+int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
+				    const char *txtaddr)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+	const char *pos;
+	u16 reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
+
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s",
+		txtaddr);
+
+	if (hwaddr_aton(txtaddr, addr))
+		return -1;
+
+	pos = os_strstr(txtaddr, " reason=");
+	if (pos)
+		reason = atoi(pos + 8);
+
+	pos = os_strstr(txtaddr, " test=");
+	if (pos) {
+		struct ieee80211_mgmt mgmt;
+		int encrypt;
+		if (!hapd->drv_priv || !hapd->driver->send_frame)
+			return -1;
+		pos += 6;
+		encrypt = atoi(pos);
+		os_memset(&mgmt, 0, sizeof(mgmt));
+		mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+						  WLAN_FC_STYPE_DISASSOC);
+		os_memcpy(mgmt.da, addr, ETH_ALEN);
+		os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN);
+		os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN);
+		mgmt.u.disassoc.reason_code = host_to_le16(reason);
+		if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
+					     IEEE80211_HDRLEN +
+					     sizeof(mgmt.u.deauth),
+					     encrypt) < 0)
+			return -1;
+		return 0;
+	}
+
+#ifdef CONFIG_P2P_MANAGER
+	pos = os_strstr(txtaddr, " p2p=");
+	if (pos) {
+		return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC,
+					      atoi(pos + 5), addr);
+	}
+#endif /* CONFIG_P2P_MANAGER */
+
+	if (os_strstr(txtaddr, " tx=0"))
+		hostapd_drv_sta_remove(hapd, addr);
+	else
+		hostapd_drv_sta_disassoc(hapd, addr, reason);
+	sta = ap_get_sta(hapd, addr);
+	if (sta)
+		ap_sta_disassociate(hapd, sta, reason);
+	else if (addr[0] == 0xff)
+		hostapd_free_stas(hapd);
+
+	return 0;
+}
+
+
+#ifdef CONFIG_TAXONOMY
+int hostapd_ctrl_iface_signature(struct hostapd_data *hapd,
+				 const char *txtaddr,
+				 char *buf, size_t buflen)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE SIGNATURE %s", txtaddr);
+
+	if (hwaddr_aton(txtaddr, addr))
+		return -1;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta)
+		return -1;
+
+	return retrieve_sta_taxonomy(hapd, sta, buf, buflen);
+}
+#endif /* CONFIG_TAXONOMY */
+
+
+int hostapd_ctrl_iface_poll_sta(struct hostapd_data *hapd,
+				const char *txtaddr)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "CTRL_IFACE POLL_STA %s", txtaddr);
+
+	if (hwaddr_aton(txtaddr, addr))
+		return -1;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta)
+		return -1;
+
+	hostapd_drv_poll_client(hapd, hapd->own_addr, addr,
+				sta->flags & WLAN_STA_WMM);
+	return 0;
+}
+
+
+int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
+			      size_t buflen)
+{
+	struct hostapd_iface *iface = hapd->iface;
+	int len = 0, ret;
+	size_t i;
+
+	ret = os_snprintf(buf + len, buflen - len,
+			  "state=%s\n"
+			  "phy=%s\n"
+			  "freq=%d\n"
+			  "num_sta_non_erp=%d\n"
+			  "num_sta_no_short_slot_time=%d\n"
+			  "num_sta_no_short_preamble=%d\n"
+			  "olbc=%d\n"
+			  "num_sta_ht_no_gf=%d\n"
+			  "num_sta_no_ht=%d\n"
+			  "num_sta_ht_20_mhz=%d\n"
+			  "num_sta_ht40_intolerant=%d\n"
+			  "olbc_ht=%d\n"
+			  "ht_op_mode=0x%x\n",
+			  hostapd_state_text(iface->state),
+			  iface->phy,
+			  iface->freq,
+			  iface->num_sta_non_erp,
+			  iface->num_sta_no_short_slot_time,
+			  iface->num_sta_no_short_preamble,
+			  iface->olbc,
+			  iface->num_sta_ht_no_gf,
+			  iface->num_sta_no_ht,
+			  iface->num_sta_ht_20mhz,
+			  iface->num_sta_ht40_intolerant,
+			  iface->olbc_ht,
+			  iface->ht_op_mode);
+	if (os_snprintf_error(buflen - len, ret))
+		return len;
+	len += ret;
+
+	if (!iface->cac_started || !iface->dfs_cac_ms) {
+		ret = os_snprintf(buf + len, buflen - len,
+				  "cac_time_seconds=%d\n"
+				  "cac_time_left_seconds=N/A\n",
+				  iface->dfs_cac_ms / 1000);
+	} else {
+		/* CAC started and CAC time set - calculate remaining time */
+		struct os_reltime now;
+		unsigned int left_time;
+
+		os_reltime_age(&iface->dfs_cac_start, &now);
+		left_time = iface->dfs_cac_ms / 1000 - now.sec;
+		ret = os_snprintf(buf + len, buflen - len,
+				  "cac_time_seconds=%u\n"
+				  "cac_time_left_seconds=%u\n",
+				  iface->dfs_cac_ms / 1000,
+				  left_time);
+	}
+	if (os_snprintf_error(buflen - len, ret))
+		return len;
+	len += ret;
+
+	ret = os_snprintf(buf + len, buflen - len,
+			  "channel=%u\n"
+			  "secondary_channel=%d\n"
+			  "ieee80211n=%d\n"
+			  "ieee80211ac=%d\n",
+			  iface->conf->channel,
+			  iface->conf->ieee80211n && !hapd->conf->disable_11n ?
+			  iface->conf->secondary_channel : 0,
+			  iface->conf->ieee80211n && !hapd->conf->disable_11n,
+			  iface->conf->ieee80211ac &&
+			  !hapd->conf->disable_11ac);
+	if (os_snprintf_error(buflen - len, ret))
+		return len;
+	len += ret;
+	if (iface->conf->ieee80211ac && !hapd->conf->disable_11ac) {
+		ret = os_snprintf(buf + len, buflen - len,
+				  "vht_oper_chwidth=%d\n"
+				  "vht_oper_centr_freq_seg0_idx=%d\n"
+				  "vht_oper_centr_freq_seg1_idx=%d\n",
+				  iface->conf->vht_oper_chwidth,
+				  iface->conf->vht_oper_centr_freq_seg0_idx,
+				  iface->conf->vht_oper_centr_freq_seg1_idx);
+		if (os_snprintf_error(buflen - len, ret))
+			return len;
+		len += ret;
+	}
+
+	for (i = 0; i < iface->num_bss; i++) {
+		struct hostapd_data *bss = iface->bss[i];
+		ret = os_snprintf(buf + len, buflen - len,
+				  "bss[%d]=%s\n"
+				  "bssid[%d]=" MACSTR "\n"
+				  "ssid[%d]=%s\n"
+				  "num_sta[%d]=%d\n",
+				  (int) i, bss->conf->iface,
+				  (int) i, MAC2STR(bss->own_addr),
+				  (int) i,
+				  wpa_ssid_txt(bss->conf->ssid.ssid,
+					       bss->conf->ssid.ssid_len),
+				  (int) i, bss->num_sta);
+		if (os_snprintf_error(buflen - len, ret))
+			return len;
+		len += ret;
+	}
+
+	return len;
+}
+
+
+int hostapd_parse_csa_settings(const char *pos,
+			       struct csa_settings *settings)
+{
+	char *end;
+
+	os_memset(settings, 0, sizeof(*settings));
+	settings->cs_count = strtol(pos, &end, 10);
+	if (pos == end) {
+		wpa_printf(MSG_ERROR, "chanswitch: invalid cs_count provided");
+		return -1;
+	}
+
+	settings->freq_params.freq = atoi(end);
+	if (settings->freq_params.freq == 0) {
+		wpa_printf(MSG_ERROR, "chanswitch: invalid freq provided");
+		return -1;
+	}
+
+#define SET_CSA_SETTING(str) \
+	do { \
+		const char *pos2 = os_strstr(pos, " " #str "="); \
+		if (pos2) { \
+			pos2 += sizeof(" " #str "=") - 1; \
+			settings->freq_params.str = atoi(pos2); \
+		} \
+	} while (0)
+
+	SET_CSA_SETTING(center_freq1);
+	SET_CSA_SETTING(center_freq2);
+	SET_CSA_SETTING(bandwidth);
+	SET_CSA_SETTING(sec_channel_offset);
+	settings->freq_params.ht_enabled = !!os_strstr(pos, " ht");
+	settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
+	settings->block_tx = !!os_strstr(pos, " blocktx");
+#undef SET_CSA_SETTING
+
+	return 0;
+}
+
+
+int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd)
+{
+	return hostapd_drv_stop_ap(hapd);
+}
+
+
+int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf,
+				  size_t len)
+{
+	return wpa_auth_pmksa_list(hapd->wpa_auth, buf, len);
+}
+
+
+void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd)
+{
+	wpa_auth_pmksa_flush(hapd->wpa_auth);
+}

+ 32 - 0
EVSE/GPL/hostapd-2.6/src/ap/ctrl_iface_ap.d

@@ -0,0 +1,32 @@
+../src/ap/ctrl_iface_ap.o: ../src/ap/ctrl_iface_ap.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/sae.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eapol_auth/eapol_auth_sm.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst_ctrl_iface.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst_ctrl_aux.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ ../src/ap/hostapd.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/vlan.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ ../src/ap/ieee802_1x.h ../src/ap/wpa_auth.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/eapol_common.h \
+ ../src/ap/ieee802_11.h ../src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/wps_hostapd.h ../src/ap/p2p_hostapd.h \
+ ../src/ap/ctrl_iface_ap.h ../src/ap/ap_drv_ops.h ../src/ap/mbo_ap.h \
+ ../src/ap/taxonomy.h

+ 36 - 0
EVSE/GPL/hostapd-2.6/src/ap/ctrl_iface_ap.h

@@ -0,0 +1,36 @@
+/*
+ * Control interface for shared AP commands
+ * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef CTRL_IFACE_AP_H
+#define CTRL_IFACE_AP_H
+
+int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd,
+				 char *buf, size_t buflen);
+int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
+			   char *buf, size_t buflen);
+int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
+				char *buf, size_t buflen);
+int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
+				      const char *txtaddr);
+int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
+				    const char *txtaddr);
+int hostapd_ctrl_iface_signature(struct hostapd_data *hapd,
+				 const char *txtaddr,
+				 char *buf, size_t buflen);
+int hostapd_ctrl_iface_poll_sta(struct hostapd_data *hapd,
+				const char *txtaddr);
+int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
+			      size_t buflen);
+int hostapd_parse_csa_settings(const char *pos,
+			       struct csa_settings *settings);
+int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd);
+int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf,
+				  size_t len);
+void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd);
+
+#endif /* CTRL_IFACE_AP_H */

+ 1068 - 0
EVSE/GPL/hostapd-2.6/src/ap/dfs.c

@@ -0,0 +1,1068 @@
+/*
+ * DFS - Dynamic Frequency Selection
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2013-2015, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/hw_features_common.h"
+#include "common/wpa_ctrl.h"
+#include "hostapd.h"
+#include "ap_drv_ops.h"
+#include "drivers/driver.h"
+#include "dfs.h"
+
+
+static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
+{
+	int n_chans = 1;
+
+	*seg1 = 0;
+
+	if (iface->conf->ieee80211n && iface->conf->secondary_channel)
+		n_chans = 2;
+
+	if (iface->conf->ieee80211ac) {
+		switch (iface->conf->vht_oper_chwidth) {
+		case VHT_CHANWIDTH_USE_HT:
+			break;
+		case VHT_CHANWIDTH_80MHZ:
+			n_chans = 4;
+			break;
+		case VHT_CHANWIDTH_160MHZ:
+			n_chans = 8;
+			break;
+		case VHT_CHANWIDTH_80P80MHZ:
+			n_chans = 4;
+			*seg1 = 4;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return n_chans;
+}
+
+
+static int dfs_channel_available(struct hostapd_channel_data *chan,
+				 int skip_radar)
+{
+	/*
+	 * When radar detection happens, CSA is performed. However, there's no
+	 * time for CAC, so radar channels must be skipped when finding a new
+	 * channel for CSA, unless they are available for immediate use.
+	 */
+	if (skip_radar && (chan->flag & HOSTAPD_CHAN_RADAR) &&
+	    ((chan->flag & HOSTAPD_CHAN_DFS_MASK) !=
+	     HOSTAPD_CHAN_DFS_AVAILABLE))
+		return 0;
+
+	if (chan->flag & HOSTAPD_CHAN_DISABLED)
+		return 0;
+	if ((chan->flag & HOSTAPD_CHAN_RADAR) &&
+	    ((chan->flag & HOSTAPD_CHAN_DFS_MASK) ==
+	     HOSTAPD_CHAN_DFS_UNAVAILABLE))
+		return 0;
+	return 1;
+}
+
+
+static int dfs_is_chan_allowed(struct hostapd_channel_data *chan, int n_chans)
+{
+	/*
+	 * The tables contain first valid channel number based on channel width.
+	 * We will also choose this first channel as the control one.
+	 */
+	int allowed_40[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
+			     184, 192 };
+	/*
+	 * VHT80, valid channels based on center frequency:
+	 * 42, 58, 106, 122, 138, 155
+	 */
+	int allowed_80[] = { 36, 52, 100, 116, 132, 149 };
+	/*
+	 * VHT160 valid channels based on center frequency:
+	 * 50, 114
+	 */
+	int allowed_160[] = { 36, 100 };
+	int *allowed = allowed_40;
+	unsigned int i, allowed_no = 0;
+
+	switch (n_chans) {
+	case 2:
+		allowed = allowed_40;
+		allowed_no = ARRAY_SIZE(allowed_40);
+		break;
+	case 4:
+		allowed = allowed_80;
+		allowed_no = ARRAY_SIZE(allowed_80);
+		break;
+	case 8:
+		allowed = allowed_160;
+		allowed_no = ARRAY_SIZE(allowed_160);
+		break;
+	default:
+		wpa_printf(MSG_DEBUG, "Unknown width for %d channels", n_chans);
+		break;
+	}
+
+	for (i = 0; i < allowed_no; i++) {
+		if (chan->chan == allowed[i])
+			return 1;
+	}
+
+	return 0;
+}
+
+
+static struct hostapd_channel_data *
+dfs_get_chan_data(struct hostapd_hw_modes *mode, int freq, int first_chan_idx)
+{
+	int i;
+
+	for (i = first_chan_idx; i < mode->num_channels; i++) {
+		if (mode->channels[i].freq == freq)
+			return &mode->channels[i];
+	}
+
+	return NULL;
+}
+
+
+static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
+				    int first_chan_idx, int num_chans,
+				    int skip_radar)
+{
+	struct hostapd_channel_data *first_chan, *chan;
+	int i;
+
+	if (first_chan_idx + num_chans > mode->num_channels)
+		return 0;
+
+	first_chan = &mode->channels[first_chan_idx];
+
+	for (i = 0; i < num_chans; i++) {
+		chan = dfs_get_chan_data(mode, first_chan->freq + i * 20,
+					 first_chan_idx);
+		if (!chan)
+			return 0;
+
+		if (!dfs_channel_available(chan, skip_radar))
+			return 0;
+	}
+
+	return 1;
+}
+
+
+static int is_in_chanlist(struct hostapd_iface *iface,
+			  struct hostapd_channel_data *chan)
+{
+	if (!iface->conf->acs_ch_list.num)
+		return 1;
+
+	return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
+}
+
+
+/*
+ * The function assumes HT40+ operation.
+ * Make sure to adjust the following variables after calling this:
+ *  - hapd->secondary_channel
+ *  - hapd->vht_oper_centr_freq_seg0_idx
+ *  - hapd->vht_oper_centr_freq_seg1_idx
+ */
+static int dfs_find_channel(struct hostapd_iface *iface,
+			    struct hostapd_channel_data **ret_chan,
+			    int idx, int skip_radar)
+{
+	struct hostapd_hw_modes *mode;
+	struct hostapd_channel_data *chan;
+	int i, channel_idx = 0, n_chans, n_chans1;
+
+	mode = iface->current_mode;
+	n_chans = dfs_get_used_n_chans(iface, &n_chans1);
+
+	wpa_printf(MSG_DEBUG, "DFS new chan checking %d channels", n_chans);
+	for (i = 0; i < mode->num_channels; i++) {
+		chan = &mode->channels[i];
+
+		/* Skip HT40/VHT incompatible channels */
+		if (iface->conf->ieee80211n &&
+		    iface->conf->secondary_channel &&
+		    !dfs_is_chan_allowed(chan, n_chans))
+			continue;
+
+		/* Skip incompatible chandefs */
+		if (!dfs_chan_range_available(mode, i, n_chans, skip_radar))
+			continue;
+
+		if (!is_in_chanlist(iface, chan))
+			continue;
+
+		if (ret_chan && idx == channel_idx) {
+			wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan);
+			*ret_chan = chan;
+			return idx;
+		}
+		wpa_printf(MSG_DEBUG, "Adding channel: %d", chan->chan);
+		channel_idx++;
+	}
+	return channel_idx;
+}
+
+
+static void dfs_adjust_vht_center_freq(struct hostapd_iface *iface,
+				       struct hostapd_channel_data *chan,
+				       int secondary_channel,
+				       u8 *vht_oper_centr_freq_seg0_idx,
+				       u8 *vht_oper_centr_freq_seg1_idx)
+{
+	if (!iface->conf->ieee80211ac)
+		return;
+
+	if (!chan)
+		return;
+
+	*vht_oper_centr_freq_seg1_idx = 0;
+
+	switch (iface->conf->vht_oper_chwidth) {
+	case VHT_CHANWIDTH_USE_HT:
+		if (secondary_channel == 1)
+			*vht_oper_centr_freq_seg0_idx = chan->chan + 2;
+		else if (secondary_channel == -1)
+			*vht_oper_centr_freq_seg0_idx = chan->chan - 2;
+		else
+			*vht_oper_centr_freq_seg0_idx = chan->chan;
+		break;
+	case VHT_CHANWIDTH_80MHZ:
+		*vht_oper_centr_freq_seg0_idx = chan->chan + 6;
+		break;
+	case VHT_CHANWIDTH_160MHZ:
+		*vht_oper_centr_freq_seg0_idx = chan->chan + 14;
+		break;
+	default:
+		wpa_printf(MSG_INFO, "DFS only VHT20/40/80/160 is supported now");
+		*vht_oper_centr_freq_seg0_idx = 0;
+		break;
+	}
+
+	wpa_printf(MSG_DEBUG, "DFS adjusting VHT center frequency: %d, %d",
+		   *vht_oper_centr_freq_seg0_idx,
+		   *vht_oper_centr_freq_seg1_idx);
+}
+
+
+/* Return start channel idx we will use for mode->channels[idx] */
+static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start)
+{
+	struct hostapd_hw_modes *mode;
+	struct hostapd_channel_data *chan;
+	int channel_no = iface->conf->channel;
+	int res = -1, i;
+	int chan_seg1 = -1;
+
+	*seg1_start = -1;
+
+	/* HT40- */
+	if (iface->conf->ieee80211n && iface->conf->secondary_channel == -1)
+		channel_no -= 4;
+
+	/* VHT */
+	if (iface->conf->ieee80211ac) {
+		switch (iface->conf->vht_oper_chwidth) {
+		case VHT_CHANWIDTH_USE_HT:
+			break;
+		case VHT_CHANWIDTH_80MHZ:
+			channel_no =
+				iface->conf->vht_oper_centr_freq_seg0_idx - 6;
+			break;
+		case VHT_CHANWIDTH_160MHZ:
+			channel_no =
+				iface->conf->vht_oper_centr_freq_seg0_idx - 14;
+			break;
+		case VHT_CHANWIDTH_80P80MHZ:
+			channel_no =
+				iface->conf->vht_oper_centr_freq_seg0_idx - 6;
+			chan_seg1 =
+				iface->conf->vht_oper_centr_freq_seg1_idx - 6;
+			break;
+		default:
+			wpa_printf(MSG_INFO,
+				   "DFS only VHT20/40/80/160/80+80 is supported now");
+			channel_no = -1;
+			break;
+		}
+	}
+
+	/* Get idx */
+	mode = iface->current_mode;
+	for (i = 0; i < mode->num_channels; i++) {
+		chan = &mode->channels[i];
+		if (chan->chan == channel_no) {
+			res = i;
+			break;
+		}
+	}
+
+	if (res != -1 && chan_seg1 > -1) {
+		int found = 0;
+
+		/* Get idx for seg1 */
+		mode = iface->current_mode;
+		for (i = 0; i < mode->num_channels; i++) {
+			chan = &mode->channels[i];
+			if (chan->chan == chan_seg1) {
+				*seg1_start = i;
+				found = 1;
+				break;
+			}
+		}
+		if (!found)
+			res = -1;
+	}
+
+	if (res == -1) {
+		wpa_printf(MSG_DEBUG,
+			   "DFS chan_idx seems wrong; num-ch: %d ch-no: %d conf-ch-no: %d 11n: %d sec-ch: %d vht-oper-width: %d",
+			   mode->num_channels, channel_no, iface->conf->channel,
+			   iface->conf->ieee80211n,
+			   iface->conf->secondary_channel,
+			   iface->conf->vht_oper_chwidth);
+
+		for (i = 0; i < mode->num_channels; i++) {
+			wpa_printf(MSG_DEBUG, "Available channel: %d",
+				   mode->channels[i].chan);
+		}
+	}
+
+	return res;
+}
+
+
+/* At least one channel have radar flag */
+static int dfs_check_chans_radar(struct hostapd_iface *iface,
+				 int start_chan_idx, int n_chans)
+{
+	struct hostapd_channel_data *channel;
+	struct hostapd_hw_modes *mode;
+	int i, res = 0;
+
+	mode = iface->current_mode;
+
+	for (i = 0; i < n_chans; i++) {
+		channel = &mode->channels[start_chan_idx + i];
+		if (channel->flag & HOSTAPD_CHAN_RADAR)
+			res++;
+	}
+
+	return res;
+}
+
+
+/* All channels available */
+static int dfs_check_chans_available(struct hostapd_iface *iface,
+				     int start_chan_idx, int n_chans)
+{
+	struct hostapd_channel_data *channel;
+	struct hostapd_hw_modes *mode;
+	int i;
+
+	mode = iface->current_mode;
+
+	for (i = 0; i < n_chans; i++) {
+		channel = &mode->channels[start_chan_idx + i];
+
+		if (channel->flag & HOSTAPD_CHAN_DISABLED)
+			break;
+
+		if (!(channel->flag & HOSTAPD_CHAN_RADAR))
+			continue;
+
+		if ((channel->flag & HOSTAPD_CHAN_DFS_MASK) !=
+		    HOSTAPD_CHAN_DFS_AVAILABLE)
+			break;
+	}
+
+	return i == n_chans;
+}
+
+
+/* At least one channel unavailable */
+static int dfs_check_chans_unavailable(struct hostapd_iface *iface,
+				       int start_chan_idx,
+				       int n_chans)
+{
+	struct hostapd_channel_data *channel;
+	struct hostapd_hw_modes *mode;
+	int i, res = 0;
+
+	mode = iface->current_mode;
+
+	for (i = 0; i < n_chans; i++) {
+		channel = &mode->channels[start_chan_idx + i];
+		if (channel->flag & HOSTAPD_CHAN_DISABLED)
+			res++;
+		if ((channel->flag & HOSTAPD_CHAN_DFS_MASK) ==
+		    HOSTAPD_CHAN_DFS_UNAVAILABLE)
+			res++;
+	}
+
+	return res;
+}
+
+
+static struct hostapd_channel_data *
+dfs_get_valid_channel(struct hostapd_iface *iface,
+		      int *secondary_channel,
+		      u8 *vht_oper_centr_freq_seg0_idx,
+		      u8 *vht_oper_centr_freq_seg1_idx,
+		      int skip_radar)
+{
+	struct hostapd_hw_modes *mode;
+	struct hostapd_channel_data *chan = NULL;
+	int num_available_chandefs;
+	int chan_idx;
+	u32 _rand;
+
+	wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
+	*secondary_channel = 0;
+	*vht_oper_centr_freq_seg0_idx = 0;
+	*vht_oper_centr_freq_seg1_idx = 0;
+
+	if (iface->current_mode == NULL)
+		return NULL;
+
+	mode = iface->current_mode;
+	if (mode->mode != HOSTAPD_MODE_IEEE80211A)
+		return NULL;
+
+	/* Get the count first */
+	num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar);
+	if (num_available_chandefs == 0)
+		return NULL;
+
+	if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
+		return NULL;
+	chan_idx = _rand % num_available_chandefs;
+	dfs_find_channel(iface, &chan, chan_idx, skip_radar);
+
+	/* dfs_find_channel() calculations assume HT40+ */
+	if (iface->conf->secondary_channel)
+		*secondary_channel = 1;
+	else
+		*secondary_channel = 0;
+
+	dfs_adjust_vht_center_freq(iface, chan,
+				   *secondary_channel,
+				   vht_oper_centr_freq_seg0_idx,
+				   vht_oper_centr_freq_seg1_idx);
+
+	return chan;
+}
+
+
+static int set_dfs_state_freq(struct hostapd_iface *iface, int freq, u32 state)
+{
+	struct hostapd_hw_modes *mode;
+	struct hostapd_channel_data *chan = NULL;
+	int i;
+
+	mode = iface->current_mode;
+	if (mode == NULL)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "set_dfs_state 0x%X for %d MHz", state, freq);
+	for (i = 0; i < iface->current_mode->num_channels; i++) {
+		chan = &iface->current_mode->channels[i];
+		if (chan->freq == freq) {
+			if (chan->flag & HOSTAPD_CHAN_RADAR) {
+				chan->flag &= ~HOSTAPD_CHAN_DFS_MASK;
+				chan->flag |= state;
+				return 1; /* Channel found */
+			}
+		}
+	}
+	wpa_printf(MSG_WARNING, "Can't set DFS state for freq %d MHz", freq);
+	return 0;
+}
+
+
+static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled,
+			 int chan_offset, int chan_width, int cf1,
+			 int cf2, u32 state)
+{
+	int n_chans = 1, i;
+	struct hostapd_hw_modes *mode;
+	int frequency = freq;
+	int ret = 0;
+
+	mode = iface->current_mode;
+	if (mode == NULL)
+		return 0;
+
+	if (mode->mode != HOSTAPD_MODE_IEEE80211A) {
+		wpa_printf(MSG_WARNING, "current_mode != IEEE80211A");
+		return 0;
+	}
+
+	/* Seems cf1 and chan_width is enough here */
+	switch (chan_width) {
+	case CHAN_WIDTH_20_NOHT:
+	case CHAN_WIDTH_20:
+		n_chans = 1;
+		if (frequency == 0)
+			frequency = cf1;
+		break;
+	case CHAN_WIDTH_40:
+		n_chans = 2;
+		frequency = cf1 - 10;
+		break;
+	case CHAN_WIDTH_80:
+		n_chans = 4;
+		frequency = cf1 - 30;
+		break;
+	case CHAN_WIDTH_160:
+		n_chans = 8;
+		frequency = cf1 - 70;
+		break;
+	default:
+		wpa_printf(MSG_INFO, "DFS chan_width %d not supported",
+			   chan_width);
+		break;
+	}
+
+	wpa_printf(MSG_DEBUG, "DFS freq: %dMHz, n_chans: %d", frequency,
+		   n_chans);
+	for (i = 0; i < n_chans; i++) {
+		ret += set_dfs_state_freq(iface, frequency, state);
+		frequency = frequency + 20;
+	}
+
+	return ret;
+}
+
+
+static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq,
+				       int chan_width, int cf1, int cf2)
+{
+	int start_chan_idx, start_chan_idx1;
+	struct hostapd_hw_modes *mode;
+	struct hostapd_channel_data *chan;
+	int n_chans, n_chans1, i, j, frequency = freq, radar_n_chans = 1;
+	u8 radar_chan;
+	int res = 0;
+
+	/* Our configuration */
+	mode = iface->current_mode;
+	start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1);
+	n_chans = dfs_get_used_n_chans(iface, &n_chans1);
+
+	/* Check we are on DFS channel(s) */
+	if (!dfs_check_chans_radar(iface, start_chan_idx, n_chans))
+		return 0;
+
+	/* Reported via radar event */
+	switch (chan_width) {
+	case CHAN_WIDTH_20_NOHT:
+	case CHAN_WIDTH_20:
+		radar_n_chans = 1;
+		if (frequency == 0)
+			frequency = cf1;
+		break;
+	case CHAN_WIDTH_40:
+		radar_n_chans = 2;
+		frequency = cf1 - 10;
+		break;
+	case CHAN_WIDTH_80:
+		radar_n_chans = 4;
+		frequency = cf1 - 30;
+		break;
+	case CHAN_WIDTH_160:
+		radar_n_chans = 8;
+		frequency = cf1 - 70;
+		break;
+	default:
+		wpa_printf(MSG_INFO, "DFS chan_width %d not supported",
+			   chan_width);
+		break;
+	}
+
+	ieee80211_freq_to_chan(frequency, &radar_chan);
+
+	for (i = 0; i < n_chans; i++) {
+		chan = &mode->channels[start_chan_idx + i];
+		if (!(chan->flag & HOSTAPD_CHAN_RADAR))
+			continue;
+		for (j = 0; j < radar_n_chans; j++) {
+			wpa_printf(MSG_DEBUG, "checking our: %d, radar: %d",
+				   chan->chan, radar_chan + j * 4);
+			if (chan->chan == radar_chan + j * 4)
+				res++;
+		}
+	}
+
+	wpa_printf(MSG_DEBUG, "overlapped: %d", res);
+
+	return res;
+}
+
+
+static unsigned int dfs_get_cac_time(struct hostapd_iface *iface,
+				     int start_chan_idx, int n_chans)
+{
+	struct hostapd_channel_data *channel;
+	struct hostapd_hw_modes *mode;
+	int i;
+	unsigned int cac_time_ms = 0;
+
+	mode = iface->current_mode;
+
+	for (i = 0; i < n_chans; i++) {
+		channel = &mode->channels[start_chan_idx + i];
+		if (!(channel->flag & HOSTAPD_CHAN_RADAR))
+			continue;
+		if (channel->dfs_cac_ms > cac_time_ms)
+			cac_time_ms = channel->dfs_cac_ms;
+	}
+
+	return cac_time_ms;
+}
+
+
+/*
+ * Main DFS handler
+ * 1 - continue channel/ap setup
+ * 0 - channel/ap setup will be continued after CAC
+ * -1 - hit critical error
+ */
+int hostapd_handle_dfs(struct hostapd_iface *iface)
+{
+	struct hostapd_channel_data *channel;
+	int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1;
+	int skip_radar = 0;
+
+	if (!iface->current_mode) {
+		/*
+		 * This can happen with drivers that do not provide mode
+		 * information and as such, cannot really use hostapd for DFS.
+		 */
+		wpa_printf(MSG_DEBUG,
+			   "DFS: No current_mode information - assume no need to perform DFS operations by hostapd");
+		return 1;
+	}
+
+	iface->cac_started = 0;
+
+	do {
+		/* Get start (first) channel for current configuration */
+		start_chan_idx = dfs_get_start_chan_idx(iface,
+							&start_chan_idx1);
+		if (start_chan_idx == -1)
+			return -1;
+
+		/* Get number of used channels, depend on width */
+		n_chans = dfs_get_used_n_chans(iface, &n_chans1);
+
+		/* Setup CAC time */
+		iface->dfs_cac_ms = dfs_get_cac_time(iface, start_chan_idx,
+						     n_chans);
+
+		/* Check if any of configured channels require DFS */
+		res = dfs_check_chans_radar(iface, start_chan_idx, n_chans);
+		wpa_printf(MSG_DEBUG,
+			   "DFS %d channels required radar detection",
+			   res);
+		if (!res)
+			return 1;
+
+		/* Check if all channels are DFS available */
+		res = dfs_check_chans_available(iface, start_chan_idx, n_chans);
+		wpa_printf(MSG_DEBUG,
+			   "DFS all channels available, (SKIP CAC): %s",
+			   res ? "yes" : "no");
+		if (res)
+			return 1;
+
+		/* Check if any of configured channels is unavailable */
+		res = dfs_check_chans_unavailable(iface, start_chan_idx,
+						  n_chans);
+		wpa_printf(MSG_DEBUG, "DFS %d chans unavailable - choose other channel: %s",
+			   res, res ? "yes": "no");
+		if (res) {
+			int sec = 0;
+			u8 cf1 = 0, cf2 = 0;
+
+			channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2,
+							skip_radar);
+			if (!channel) {
+				wpa_printf(MSG_ERROR, "could not get valid channel");
+				hostapd_set_state(iface, HAPD_IFACE_DFS);
+				return 0;
+			}
+
+			iface->freq = channel->freq;
+			iface->conf->channel = channel->chan;
+			iface->conf->secondary_channel = sec;
+			iface->conf->vht_oper_centr_freq_seg0_idx = cf1;
+			iface->conf->vht_oper_centr_freq_seg1_idx = cf2;
+		}
+	} while (res);
+
+	/* Finally start CAC */
+	hostapd_set_state(iface, HAPD_IFACE_DFS);
+	wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq);
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
+		"freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds",
+		iface->freq,
+		iface->conf->channel, iface->conf->secondary_channel,
+		iface->conf->vht_oper_chwidth,
+		iface->conf->vht_oper_centr_freq_seg0_idx,
+		iface->conf->vht_oper_centr_freq_seg1_idx,
+		iface->dfs_cac_ms / 1000);
+
+	res = hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
+				    iface->freq,
+				    iface->conf->channel,
+				    iface->conf->ieee80211n,
+				    iface->conf->ieee80211ac,
+				    iface->conf->secondary_channel,
+				    iface->conf->vht_oper_chwidth,
+				    iface->conf->vht_oper_centr_freq_seg0_idx,
+				    iface->conf->vht_oper_centr_freq_seg1_idx);
+
+	if (res) {
+		wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
+			     int ht_enabled, int chan_offset, int chan_width,
+			     int cf1, int cf2)
+{
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED
+		"success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
+		success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
+
+	if (success) {
+		/* Complete iface/ap configuration */
+		if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
+			/* Complete AP configuration for the first bring up. */
+			if (iface->state != HAPD_IFACE_ENABLED)
+				hostapd_setup_interface_complete(iface, 0);
+			else
+				iface->cac_started = 0;
+		} else {
+			set_dfs_state(iface, freq, ht_enabled, chan_offset,
+				      chan_width, cf1, cf2,
+				      HOSTAPD_CHAN_DFS_AVAILABLE);
+			iface->cac_started = 0;
+			hostapd_setup_interface_complete(iface, 0);
+		}
+	}
+
+	return 0;
+}
+
+
+static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
+{
+	struct hostapd_channel_data *channel;
+	int secondary_channel;
+	u8 vht_oper_centr_freq_seg0_idx = 0;
+	u8 vht_oper_centr_freq_seg1_idx = 0;
+	int skip_radar = 0;
+	int err = 1;
+
+	/* Radar detected during active CAC */
+	iface->cac_started = 0;
+	channel = dfs_get_valid_channel(iface, &secondary_channel,
+					&vht_oper_centr_freq_seg0_idx,
+					&vht_oper_centr_freq_seg1_idx,
+					skip_radar);
+
+	if (!channel) {
+		wpa_printf(MSG_ERROR, "No valid channel available");
+		return err;
+	}
+
+	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
+		   channel->chan);
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
+		"freq=%d chan=%d sec_chan=%d", channel->freq,
+		channel->chan, secondary_channel);
+
+	iface->freq = channel->freq;
+	iface->conf->channel = channel->chan;
+	iface->conf->secondary_channel = secondary_channel;
+	iface->conf->vht_oper_centr_freq_seg0_idx =
+		vht_oper_centr_freq_seg0_idx;
+	iface->conf->vht_oper_centr_freq_seg1_idx =
+		vht_oper_centr_freq_seg1_idx;
+	err = 0;
+
+	hostapd_setup_interface_complete(iface, err);
+	return err;
+}
+
+
+static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+{
+	struct hostapd_channel_data *channel;
+	int secondary_channel;
+	u8 vht_oper_centr_freq_seg0_idx;
+	u8 vht_oper_centr_freq_seg1_idx;
+	int skip_radar = 1;
+	struct csa_settings csa_settings;
+	unsigned int i;
+	int err = 1;
+
+	wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
+		   __func__, iface->cac_started ? "yes" : "no",
+		   hostapd_csa_in_progress(iface) ? "yes" : "no");
+
+	/* Check if CSA in progress */
+	if (hostapd_csa_in_progress(iface))
+		return 0;
+
+	/* Check if active CAC */
+	if (iface->cac_started)
+		return hostapd_dfs_start_channel_switch_cac(iface);
+
+	/* Perform channel switch/CSA */
+	channel = dfs_get_valid_channel(iface, &secondary_channel,
+					&vht_oper_centr_freq_seg0_idx,
+					&vht_oper_centr_freq_seg1_idx,
+					skip_radar);
+
+	if (!channel) {
+		/*
+		 * If there is no channel to switch immediately to, check if
+		 * there is another channel where we can switch even if it
+		 * requires to perform a CAC first.
+		 */
+		skip_radar = 0;
+		channel = dfs_get_valid_channel(iface, &secondary_channel,
+						&vht_oper_centr_freq_seg0_idx,
+						&vht_oper_centr_freq_seg1_idx,
+						skip_radar);
+		if (!channel) {
+			wpa_printf(MSG_INFO,
+				   "%s: no DFS channels left, waiting for NOP to finish",
+				   __func__);
+			return err;
+		}
+
+		iface->freq = channel->freq;
+		iface->conf->channel = channel->chan;
+		iface->conf->secondary_channel = secondary_channel;
+		iface->conf->vht_oper_centr_freq_seg0_idx =
+			vht_oper_centr_freq_seg0_idx;
+		iface->conf->vht_oper_centr_freq_seg1_idx =
+			vht_oper_centr_freq_seg1_idx;
+
+		hostapd_disable_iface(iface);
+		hostapd_enable_iface(iface);
+		return 0;
+	}
+
+	wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
+		   channel->chan);
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
+		"freq=%d chan=%d sec_chan=%d", channel->freq,
+		channel->chan, secondary_channel);
+
+	/* Setup CSA request */
+	os_memset(&csa_settings, 0, sizeof(csa_settings));
+	csa_settings.cs_count = 5;
+	csa_settings.block_tx = 1;
+	err = hostapd_set_freq_params(&csa_settings.freq_params,
+				      iface->conf->hw_mode,
+				      channel->freq,
+				      channel->chan,
+				      iface->conf->ieee80211n,
+				      iface->conf->ieee80211ac,
+				      secondary_channel,
+				      iface->conf->vht_oper_chwidth,
+				      vht_oper_centr_freq_seg0_idx,
+				      vht_oper_centr_freq_seg1_idx,
+				      iface->current_mode->vht_capab);
+
+	if (err) {
+		wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
+		hostapd_disable_iface(iface);
+		return err;
+	}
+
+	for (i = 0; i < iface->num_bss; i++) {
+		err = hostapd_switch_channel(iface->bss[i], &csa_settings);
+		if (err)
+			break;
+	}
+
+	if (err) {
+		wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
+			   err);
+		iface->freq = channel->freq;
+		iface->conf->channel = channel->chan;
+		iface->conf->secondary_channel = secondary_channel;
+		iface->conf->vht_oper_centr_freq_seg0_idx =
+			vht_oper_centr_freq_seg0_idx;
+		iface->conf->vht_oper_centr_freq_seg1_idx =
+			vht_oper_centr_freq_seg1_idx;
+
+		hostapd_disable_iface(iface);
+		hostapd_enable_iface(iface);
+		return 0;
+	}
+
+	/* Channel configuration will be updated once CSA completes and
+	 * ch_switch_notify event is received */
+
+	wpa_printf(MSG_DEBUG, "DFS waiting channel switch event");
+	return 0;
+}
+
+
+int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
+			       int ht_enabled, int chan_offset, int chan_width,
+			       int cf1, int cf2)
+{
+	int res;
+
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED
+		"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
+		freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
+
+	/* Proceed only if DFS is not offloaded to the driver */
+	if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
+		return 0;
+
+	if (!iface->conf->ieee80211h)
+		return 0;
+
+	/* mark radar frequency as invalid */
+	set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
+		      cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE);
+
+	/* Skip if reported radar event not overlapped our channels */
+	res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2);
+	if (!res)
+		return 0;
+
+	/* radar detected while operating, switch the channel. */
+	res = hostapd_dfs_start_channel_switch(iface);
+
+	return res;
+}
+
+
+int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+			     int ht_enabled, int chan_offset, int chan_width,
+			     int cf1, int cf2)
+{
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED
+		"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
+		freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
+
+	/* Proceed only if DFS is not offloaded to the driver */
+	if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
+		return 0;
+
+	/* TODO add correct implementation here */
+	set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
+		      cf1, cf2, HOSTAPD_CHAN_DFS_USABLE);
+
+	/* Handle cases where all channels were initially unavailable */
+	if (iface->state == HAPD_IFACE_DFS && !iface->cac_started)
+		hostapd_handle_dfs(iface);
+
+	return 0;
+}
+
+
+int hostapd_is_dfs_required(struct hostapd_iface *iface)
+{
+	int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
+
+	if (!iface->conf->ieee80211h || !iface->current_mode ||
+	    iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
+		return 0;
+
+	/* Get start (first) channel for current configuration */
+	start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1);
+	if (start_chan_idx == -1)
+		return -1;
+
+	/* Get number of used channels, depend on width */
+	n_chans = dfs_get_used_n_chans(iface, &n_chans1);
+
+	/* Check if any of configured channels require DFS */
+	res = dfs_check_chans_radar(iface, start_chan_idx, n_chans);
+	if (res)
+		return res;
+	if (start_chan_idx1 >= 0 && n_chans1 > 0)
+		res = dfs_check_chans_radar(iface, start_chan_idx1, n_chans1);
+	return res;
+}
+
+
+int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+			  int ht_enabled, int chan_offset, int chan_width,
+			  int cf1, int cf2)
+{
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
+		"freq=%d chan=%d chan_offset=%d width=%d seg0=%d "
+		"seg1=%d cac_time=%ds",
+		freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, 60);
+	iface->cac_started = 1;
+	return 0;
+}
+
+
+/*
+ * Main DFS handler for offloaded case.
+ * 2 - continue channel/AP setup for non-DFS channel
+ * 1 - continue channel/AP setup for DFS channel
+ * 0 - channel/AP setup will be continued after CAC
+ * -1 - hit critical error
+ */
+int hostapd_handle_dfs_offload(struct hostapd_iface *iface)
+{
+	wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d",
+		   __func__, iface->cac_started);
+
+	/*
+	 * If DFS has already been started, then we are being called from a
+	 * callback to continue AP/channel setup. Reset the CAC start flag and
+	 * return.
+	 */
+	if (iface->cac_started) {
+		wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d",
+			   __func__, iface->cac_started);
+		iface->cac_started = 0;
+		return 1;
+	}
+
+	if (ieee80211_is_dfs(iface->freq)) {
+		wpa_printf(MSG_DEBUG, "%s: freq %d MHz requires DFS",
+			   __func__, iface->freq);
+		return 0;
+	}
+
+	wpa_printf(MSG_DEBUG,
+		   "%s: freq %d MHz does not require DFS. Continue channel/AP setup",
+		   __func__, iface->freq);
+	return 2;
+}

+ 22 - 0
EVSE/GPL/hostapd-2.6/src/ap/dfs.d

@@ -0,0 +1,22 @@
+../src/ap/dfs.o: ../src/ap/dfs.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/hw_features_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_ctrl.h \
+ ../src/ap/hostapd.h ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/vlan.h ../src/ap/ap_drv_ops.h ../src/ap/dfs.h

+ 30 - 0
EVSE/GPL/hostapd-2.6/src/ap/dfs.h

@@ -0,0 +1,30 @@
+/*
+ * DFS - Dynamic Frequency Selection
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2013, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+#ifndef DFS_H
+#define DFS_H
+
+int hostapd_handle_dfs(struct hostapd_iface *iface);
+
+int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
+			     int ht_enabled, int chan_offset, int chan_width,
+			     int cf1, int cf2);
+int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
+			       int ht_enabled,
+			       int chan_offset, int chan_width,
+			       int cf1, int cf2);
+int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+			     int ht_enabled,
+			     int chan_offset, int chan_width, int cf1, int cf2);
+int hostapd_is_dfs_required(struct hostapd_iface *iface);
+int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+			  int ht_enabled, int chan_offset, int chan_width,
+			  int cf1, int cf2);
+int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
+
+#endif /* DFS_H */

+ 179 - 0
EVSE/GPL/hostapd-2.6/src/ap/dhcp_snoop.c

@@ -0,0 +1,179 @@
+/*
+ * DHCP snooping for Proxy ARP
+ * Copyright (c) 2014, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+
+#include "utils/common.h"
+#include "l2_packet/l2_packet.h"
+#include "hostapd.h"
+#include "sta_info.h"
+#include "ap_drv_ops.h"
+#include "x_snoop.h"
+#include "dhcp_snoop.h"
+
+struct bootp_pkt {
+	struct iphdr iph;
+	struct udphdr udph;
+	u8 op;
+	u8 htype;
+	u8 hlen;
+	u8 hops;
+	be32 xid;
+	be16 secs;
+	be16 flags;
+	be32 client_ip;
+	be32 your_ip;
+	be32 server_ip;
+	be32 relay_ip;
+	u8 hw_addr[16];
+	u8 serv_name[64];
+	u8 boot_file[128];
+	u8 exten[312];
+} STRUCT_PACKED;
+
+#define DHCPACK	5
+static const u8 ic_bootp_cookie[] = { 99, 130, 83, 99 };
+
+
+static const char * ipaddr_str(u32 addr)
+{
+	static char buf[17];
+
+	os_snprintf(buf, sizeof(buf), "%u.%u.%u.%u",
+		    (addr >> 24) & 0xff, (addr >> 16) & 0xff,
+		    (addr >> 8) & 0xff, addr & 0xff);
+	return buf;
+}
+
+
+static void handle_dhcp(void *ctx, const u8 *src_addr, const u8 *buf,
+			size_t len)
+{
+	struct hostapd_data *hapd = ctx;
+	const struct bootp_pkt *b;
+	struct sta_info *sta;
+	int exten_len;
+	const u8 *end, *pos;
+	int res, msgtype = 0, prefixlen = 32;
+	u32 subnet_mask = 0;
+	u16 tot_len;
+
+	exten_len = len - ETH_HLEN - (sizeof(*b) - sizeof(b->exten));
+	if (exten_len < 4)
+		return;
+
+	b = (const struct bootp_pkt *) &buf[ETH_HLEN];
+	tot_len = ntohs(b->iph.tot_len);
+	if (tot_len > (unsigned int) (len - ETH_HLEN))
+		return;
+
+	if (os_memcmp(b->exten, ic_bootp_cookie, ARRAY_SIZE(ic_bootp_cookie)))
+		return;
+
+	/* Parse DHCP options */
+	end = (const u8 *) b + tot_len;
+	pos = &b->exten[4];
+	while (pos < end && *pos != 0xff) {
+		const u8 *opt = pos++;
+
+		if (*opt == 0) /* padding */
+			continue;
+
+		pos += *pos + 1;
+		if (pos >= end)
+			break;
+
+		switch (*opt) {
+		case 1:  /* subnet mask */
+			if (opt[1] == 4)
+				subnet_mask = WPA_GET_BE32(&opt[2]);
+			if (subnet_mask == 0)
+				return;
+			while (!(subnet_mask & 0x1)) {
+				subnet_mask >>= 1;
+				prefixlen--;
+			}
+			break;
+		case 53: /* message type */
+			if (opt[1])
+				msgtype = opt[2];
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (msgtype == DHCPACK) {
+		if (b->your_ip == 0)
+			return;
+
+		/* DHCPACK for DHCPREQUEST */
+		sta = ap_get_sta(hapd, b->hw_addr);
+		if (!sta)
+			return;
+
+		wpa_printf(MSG_DEBUG, "dhcp_snoop: Found DHCPACK for " MACSTR
+			   " @ IPv4 address %s/%d",
+			   MAC2STR(sta->addr),
+			   ipaddr_str(be_to_host32(b->your_ip)),
+			   prefixlen);
+
+		if (sta->ipaddr == b->your_ip)
+			return;
+
+		if (sta->ipaddr != 0) {
+			wpa_printf(MSG_DEBUG,
+				   "dhcp_snoop: Removing IPv4 address %s from the ip neigh table",
+				   ipaddr_str(be_to_host32(sta->ipaddr)));
+			hostapd_drv_br_delete_ip_neigh(hapd, 4,
+						       (u8 *) &sta->ipaddr);
+		}
+
+		res = hostapd_drv_br_add_ip_neigh(hapd, 4, (u8 *) &b->your_ip,
+						  prefixlen, sta->addr);
+		if (res) {
+			wpa_printf(MSG_DEBUG,
+				   "dhcp_snoop: Adding ip neigh table failed: %d",
+				   res);
+			return;
+		}
+		sta->ipaddr = b->your_ip;
+	}
+
+	if (hapd->conf->disable_dgaf && is_broadcast_ether_addr(buf)) {
+		for (sta = hapd->sta_list; sta; sta = sta->next) {
+			if (!(sta->flags & WLAN_STA_AUTHORIZED))
+				continue;
+			x_snoop_mcast_to_ucast_convert_send(hapd, sta,
+							    (u8 *) buf, len);
+		}
+	}
+}
+
+
+int dhcp_snoop_init(struct hostapd_data *hapd)
+{
+	hapd->sock_dhcp = x_snoop_get_l2_packet(hapd, handle_dhcp,
+						L2_PACKET_FILTER_DHCP);
+	if (hapd->sock_dhcp == NULL) {
+		wpa_printf(MSG_DEBUG,
+			   "dhcp_snoop: Failed to initialize L2 packet processing for DHCP packet: %s",
+			   strerror(errno));
+		return -1;
+	}
+
+	return 0;
+}
+
+
+void dhcp_snoop_deinit(struct hostapd_data *hapd)
+{
+	l2_packet_deinit(hapd->sock_dhcp);
+}

+ 30 - 0
EVSE/GPL/hostapd-2.6/src/ap/dhcp_snoop.h

@@ -0,0 +1,30 @@
+/*
+ * DHCP snooping for Proxy ARP
+ * Copyright (c) 2014, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef DHCP_SNOOP_H
+#define DHCP_SNOOP_H
+
+#ifdef CONFIG_PROXYARP
+
+int dhcp_snoop_init(struct hostapd_data *hapd);
+void dhcp_snoop_deinit(struct hostapd_data *hapd);
+
+#else /* CONFIG_PROXYARP */
+
+static inline int dhcp_snoop_init(struct hostapd_data *hapd)
+{
+	return 0;
+}
+
+static inline void dhcp_snoop_deinit(struct hostapd_data *hapd)
+{
+}
+
+#endif /* CONFIG_PROXYARP */
+
+#endif /* DHCP_SNOOP_H */

+ 1403 - 0
EVSE/GPL/hostapd-2.6/src/ap/drv_callbacks.c

@@ -0,0 +1,1403 @@
+/*
+ * hostapd / Callback functions for driver wrappers
+ * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "radius/radius.h"
+#include "drivers/driver.h"
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "common/wpa_ctrl.h"
+#include "crypto/random.h"
+#include "p2p/p2p.h"
+#include "wps/wps.h"
+#include "fst/fst.h"
+#include "wnm_ap.h"
+#include "hostapd.h"
+#include "ieee802_11.h"
+#include "ieee802_11_auth.h"
+#include "sta_info.h"
+#include "accounting.h"
+#include "tkip_countermeasures.h"
+#include "ieee802_1x.h"
+#include "wpa_auth.h"
+#include "wps_hostapd.h"
+#include "ap_drv_ops.h"
+#include "ap_config.h"
+#include "hw_features.h"
+#include "dfs.h"
+#include "beacon.h"
+#include "mbo_ap.h"
+
+
+int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
+			const u8 *req_ies, size_t req_ies_len, int reassoc)
+{
+	struct sta_info *sta;
+	int new_assoc, res;
+	struct ieee802_11_elems elems;
+	const u8 *ie;
+	size_t ielen;
+#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
+	u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
+	u8 *p = buf;
+#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
+	u16 reason = WLAN_REASON_UNSPECIFIED;
+	u16 status = WLAN_STATUS_SUCCESS;
+	const u8 *p2p_dev_addr = NULL;
+
+	if (addr == NULL) {
+		/*
+		 * This could potentially happen with unexpected event from the
+		 * driver wrapper. This was seen at least in one case where the
+		 * driver ended up being set to station mode while hostapd was
+		 * running, so better make sure we stop processing such an
+		 * event here.
+		 */
+		wpa_printf(MSG_DEBUG,
+			   "hostapd_notif_assoc: Skip event with no address");
+		return -1;
+	}
+	random_add_randomness(addr, ETH_ALEN);
+
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+		       HOSTAPD_LEVEL_INFO, "associated");
+
+	ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0);
+	if (elems.wps_ie) {
+		ie = elems.wps_ie - 2;
+		ielen = elems.wps_ie_len + 2;
+		wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
+	} else if (elems.rsn_ie) {
+		ie = elems.rsn_ie - 2;
+		ielen = elems.rsn_ie_len + 2;
+		wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
+	} else if (elems.wpa_ie) {
+		ie = elems.wpa_ie - 2;
+		ielen = elems.wpa_ie_len + 2;
+		wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
+#ifdef CONFIG_HS20
+	} else if (elems.osen) {
+		ie = elems.osen - 2;
+		ielen = elems.osen_len + 2;
+		wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq");
+#endif /* CONFIG_HS20 */
+	} else {
+		ie = NULL;
+		ielen = 0;
+		wpa_printf(MSG_DEBUG,
+			   "STA did not include WPS/RSN/WPA IE in (Re)AssocReq");
+	}
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta) {
+		ap_sta_no_session_timeout(hapd, sta);
+		accounting_sta_stop(hapd, sta);
+
+		/*
+		 * Make sure that the previously registered inactivity timer
+		 * will not remove the STA immediately.
+		 */
+		sta->timeout_next = STA_NULLFUNC;
+	} else {
+		sta = ap_sta_add(hapd, addr);
+		if (sta == NULL) {
+			hostapd_drv_sta_disassoc(hapd, addr,
+						 WLAN_REASON_DISASSOC_AP_BUSY);
+			return -1;
+		}
+	}
+	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
+
+	/*
+	 * ACL configurations to the drivers (implementing AP SME and ACL
+	 * offload) without hostapd's knowledge, can result in a disconnection
+	 * though the driver accepts the connection. Skip the hostapd check for
+	 * ACL if the driver supports ACL offload to avoid potentially
+	 * conflicting ACL rules.
+	 */
+	if (hapd->iface->drv_max_acl_mac_addrs == 0 &&
+	    hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) {
+		wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect",
+			   MAC2STR(addr));
+		reason = WLAN_REASON_UNSPECIFIED;
+		goto fail;
+	}
+
+#ifdef CONFIG_P2P
+	if (elems.p2p) {
+		wpabuf_free(sta->p2p_ie);
+		sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
+							  P2P_IE_VENDOR_TYPE);
+		if (sta->p2p_ie)
+			p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
+	}
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_IEEE80211N
+#ifdef NEED_AP_MLME
+	if (elems.ht_capabilities &&
+	    (hapd->iface->conf->ht_capab &
+	     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
+		struct ieee80211_ht_capabilities *ht_cap =
+			(struct ieee80211_ht_capabilities *)
+			elems.ht_capabilities;
+
+		if (le_to_host16(ht_cap->ht_capabilities_info) &
+		    HT_CAP_INFO_40MHZ_INTOLERANT)
+			ht40_intolerant_add(hapd->iface, sta);
+	}
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_IEEE80211N */
+
+#ifdef CONFIG_INTERWORKING
+	if (elems.ext_capab && elems.ext_capab_len > 4) {
+		if (elems.ext_capab[4] & 0x01)
+			sta->qos_map_enabled = 1;
+	}
+#endif /* CONFIG_INTERWORKING */
+
+#ifdef CONFIG_HS20
+	wpabuf_free(sta->hs20_ie);
+	if (elems.hs20 && elems.hs20_len > 4) {
+		sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
+						 elems.hs20_len - 4);
+	} else
+		sta->hs20_ie = NULL;
+#endif /* CONFIG_HS20 */
+
+#ifdef CONFIG_FST
+	wpabuf_free(sta->mb_ies);
+	if (hapd->iface->fst)
+		sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
+	else
+		sta->mb_ies = NULL;
+#endif /* CONFIG_FST */
+
+	mbo_ap_check_sta_assoc(hapd, sta, &elems);
+
+	ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
+				    elems.supp_op_classes_len);
+
+	if (hapd->conf->wpa) {
+		if (ie == NULL || ielen == 0) {
+#ifdef CONFIG_WPS
+			if (hapd->conf->wps_state) {
+				wpa_printf(MSG_DEBUG,
+					   "STA did not include WPA/RSN IE in (Re)Association Request - possible WPS use");
+				sta->flags |= WLAN_STA_MAYBE_WPS;
+				goto skip_wpa_check;
+			}
+#endif /* CONFIG_WPS */
+
+			wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
+			return -1;
+		}
+#ifdef CONFIG_WPS
+		if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
+		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
+			struct wpabuf *wps;
+
+			sta->flags |= WLAN_STA_WPS;
+			wps = ieee802_11_vendor_ie_concat(ie, ielen,
+							  WPS_IE_VENDOR_TYPE);
+			if (wps) {
+				if (wps_is_20(wps)) {
+					wpa_printf(MSG_DEBUG,
+						   "WPS: STA supports WPS 2.0");
+					sta->flags |= WLAN_STA_WPS2;
+				}
+				wpabuf_free(wps);
+			}
+			goto skip_wpa_check;
+		}
+#endif /* CONFIG_WPS */
+
+		if (sta->wpa_sm == NULL)
+			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
+							sta->addr,
+							p2p_dev_addr);
+		if (sta->wpa_sm == NULL) {
+			wpa_printf(MSG_ERROR,
+				   "Failed to initialize WPA state machine");
+			return -1;
+		}
+		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
+					  ie, ielen,
+					  elems.mdie, elems.mdie_len);
+		if (res != WPA_IE_OK) {
+			wpa_printf(MSG_DEBUG,
+				   "WPA/RSN information element rejected? (res %u)",
+				   res);
+			wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
+			if (res == WPA_INVALID_GROUP) {
+				reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
+				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
+			} else if (res == WPA_INVALID_PAIRWISE) {
+				reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
+				status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
+			} else if (res == WPA_INVALID_AKMP) {
+				reason = WLAN_REASON_AKMP_NOT_VALID;
+				status = WLAN_STATUS_AKMP_NOT_VALID;
+			}
+#ifdef CONFIG_IEEE80211W
+			else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
+				reason = WLAN_REASON_INVALID_IE;
+				status = WLAN_STATUS_INVALID_IE;
+			} else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
+				reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
+				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
+			}
+#endif /* CONFIG_IEEE80211W */
+			else {
+				reason = WLAN_REASON_INVALID_IE;
+				status = WLAN_STATUS_INVALID_IE;
+			}
+			goto fail;
+		}
+#ifdef CONFIG_IEEE80211W
+		if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
+		    sta->sa_query_count > 0)
+			ap_check_sa_query_timeout(hapd, sta);
+		if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
+		    (sta->auth_alg != WLAN_AUTH_FT)) {
+			/*
+			 * STA has already been associated with MFP and SA
+			 * Query timeout has not been reached. Reject the
+			 * association attempt temporarily and start SA Query,
+			 * if one is not pending.
+			 */
+
+			if (sta->sa_query_count == 0)
+				ap_sta_start_sa_query(hapd, sta);
+
+			status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
+
+			p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
+
+			hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
+					  p - buf);
+			return 0;
+		}
+
+		if (wpa_auth_uses_mfp(sta->wpa_sm))
+			sta->flags |= WLAN_STA_MFP;
+		else
+			sta->flags &= ~WLAN_STA_MFP;
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_IEEE80211R
+		if (sta->auth_alg == WLAN_AUTH_FT) {
+			status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies,
+							 req_ies_len);
+			if (status != WLAN_STATUS_SUCCESS) {
+				if (status == WLAN_STATUS_INVALID_PMKID)
+					reason = WLAN_REASON_INVALID_IE;
+				if (status == WLAN_STATUS_INVALID_MDIE)
+					reason = WLAN_REASON_INVALID_IE;
+				if (status == WLAN_STATUS_INVALID_FTIE)
+					reason = WLAN_REASON_INVALID_IE;
+				goto fail;
+			}
+		}
+#endif /* CONFIG_IEEE80211R */
+	} else if (hapd->conf->wps_state) {
+#ifdef CONFIG_WPS
+		struct wpabuf *wps;
+
+		if (req_ies)
+			wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
+							  WPS_IE_VENDOR_TYPE);
+		else
+			wps = NULL;
+#ifdef CONFIG_WPS_STRICT
+		if (wps && wps_validate_assoc_req(wps) < 0) {
+			reason = WLAN_REASON_INVALID_IE;
+			status = WLAN_STATUS_INVALID_IE;
+			wpabuf_free(wps);
+			goto fail;
+		}
+#endif /* CONFIG_WPS_STRICT */
+		if (wps) {
+			sta->flags |= WLAN_STA_WPS;
+			if (wps_is_20(wps)) {
+				wpa_printf(MSG_DEBUG,
+					   "WPS: STA supports WPS 2.0");
+				sta->flags |= WLAN_STA_WPS2;
+			}
+		} else
+			sta->flags |= WLAN_STA_MAYBE_WPS;
+		wpabuf_free(wps);
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_HS20
+	} else if (hapd->conf->osen) {
+		if (elems.osen == NULL) {
+			hostapd_logger(
+				hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+				HOSTAPD_LEVEL_INFO,
+				"No HS 2.0 OSEN element in association request");
+			return WLAN_STATUS_INVALID_IE;
+		}
+
+		wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
+		if (sta->wpa_sm == NULL)
+			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
+							sta->addr, NULL);
+		if (sta->wpa_sm == NULL) {
+			wpa_printf(MSG_WARNING,
+				   "Failed to initialize WPA state machine");
+			return WLAN_STATUS_UNSPECIFIED_FAILURE;
+		}
+		if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
+				      elems.osen - 2, elems.osen_len + 2) < 0)
+			return WLAN_STATUS_INVALID_IE;
+#endif /* CONFIG_HS20 */
+	}
+
+#ifdef CONFIG_MBO
+	if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
+	    elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
+	    hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+		wpa_printf(MSG_INFO,
+			   "MBO: Reject WPA2 association without PMF");
+		return WLAN_STATUS_UNSPECIFIED_FAILURE;
+	}
+#endif /* CONFIG_MBO */
+
+#ifdef CONFIG_WPS
+skip_wpa_check:
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_IEEE80211R
+	p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
+					sta->auth_alg, req_ies, req_ies_len);
+
+	hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
+
+	if (sta->auth_alg == WLAN_AUTH_FT)
+		ap_sta_set_authorized(hapd, sta, 1);
+#else /* CONFIG_IEEE80211R */
+	/* Keep compiler silent about unused variables */
+	if (status) {
+	}
+#endif /* CONFIG_IEEE80211R */
+
+	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
+	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
+	sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
+
+	hostapd_set_sta_flags(hapd, sta);
+
+	if (reassoc && (sta->auth_alg == WLAN_AUTH_FT))
+		wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
+	else
+		wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
+
+	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
+
+	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
+
+#ifdef CONFIG_P2P
+	if (req_ies) {
+		p2p_group_notif_assoc(hapd->p2p_group, sta->addr,
+				      req_ies, req_ies_len);
+	}
+#endif /* CONFIG_P2P */
+
+	return 0;
+
+fail:
+#ifdef CONFIG_IEEE80211R
+	hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
+#endif /* CONFIG_IEEE80211R */
+	hostapd_drv_sta_disassoc(hapd, sta->addr, reason);
+	ap_free_sta(hapd, sta);
+	return -1;
+}
+
+
+void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
+{
+	struct sta_info *sta;
+
+	if (addr == NULL) {
+		/*
+		 * This could potentially happen with unexpected event from the
+		 * driver wrapper. This was seen at least in one case where the
+		 * driver ended up reporting a station mode event while hostapd
+		 * was running, so better make sure we stop processing such an
+		 * event here.
+		 */
+		wpa_printf(MSG_DEBUG,
+			   "hostapd_notif_disassoc: Skip event with no address");
+		return;
+	}
+
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+		       HOSTAPD_LEVEL_INFO, "disassociated");
+
+	sta = ap_get_sta(hapd, addr);
+	if (sta == NULL) {
+		wpa_printf(MSG_DEBUG,
+			   "Disassociation notification for unknown STA "
+			   MACSTR, MAC2STR(addr));
+		return;
+	}
+
+	ap_sta_set_authorized(hapd, sta, 0);
+	sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
+	wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
+	sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
+	ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
+	ap_free_sta(hapd, sta);
+}
+
+
+void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
+{
+	struct sta_info *sta = ap_get_sta(hapd, addr);
+
+	if (!sta || !hapd->conf->disassoc_low_ack)
+		return;
+
+	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
+		       HOSTAPD_LEVEL_INFO,
+		       "disconnected due to excessive missing ACKs");
+	hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
+	if (sta)
+		ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
+}
+
+
+void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
+			     int offset, int width, int cf1, int cf2)
+{
+#ifdef NEED_AP_MLME
+	int channel, chwidth, is_dfs;
+	u8 seg0_idx = 0, seg1_idx = 0;
+
+	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+		       HOSTAPD_LEVEL_INFO,
+		       "driver had channel switch: freq=%d, ht=%d, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
+		       freq, ht, offset, width, channel_width_to_string(width),
+		       cf1, cf2);
+
+	hapd->iface->freq = freq;
+
+	channel = hostapd_hw_get_channel(hapd, freq);
+	if (!channel) {
+		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_WARNING,
+			       "driver switched to bad channel!");
+		return;
+	}
+
+	switch (width) {
+	case CHAN_WIDTH_80:
+		chwidth = VHT_CHANWIDTH_80MHZ;
+		break;
+	case CHAN_WIDTH_80P80:
+		chwidth = VHT_CHANWIDTH_80P80MHZ;
+		break;
+	case CHAN_WIDTH_160:
+		chwidth = VHT_CHANWIDTH_160MHZ;
+		break;
+	case CHAN_WIDTH_20_NOHT:
+	case CHAN_WIDTH_20:
+	case CHAN_WIDTH_40:
+	default:
+		chwidth = VHT_CHANWIDTH_USE_HT;
+		break;
+	}
+
+	switch (hapd->iface->current_mode->mode) {
+	case HOSTAPD_MODE_IEEE80211A:
+		if (cf1 > 5000)
+			seg0_idx = (cf1 - 5000) / 5;
+		if (cf2 > 5000)
+			seg1_idx = (cf2 - 5000) / 5;
+		break;
+	default:
+		ieee80211_freq_to_chan(cf1, &seg0_idx);
+		ieee80211_freq_to_chan(cf2, &seg1_idx);
+		break;
+	}
+
+	hapd->iconf->channel = channel;
+	hapd->iconf->ieee80211n = ht;
+	if (!ht)
+		hapd->iconf->ieee80211ac = 0;
+	hapd->iconf->secondary_channel = offset;
+	hapd->iconf->vht_oper_chwidth = chwidth;
+	hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx;
+	hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx;
+
+	is_dfs = ieee80211_is_dfs(freq);
+
+	if (hapd->csa_in_progress &&
+	    freq == hapd->cs_freq_params.freq) {
+		hostapd_cleanup_cs_params(hapd);
+		ieee802_11_set_beacon(hapd);
+
+		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
+			"freq=%d dfs=%d", freq, is_dfs);
+	} else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
+		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
+			"freq=%d dfs=%d", freq, is_dfs);
+	}
+#endif /* NEED_AP_MLME */
+}
+
+
+void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
+					 const u8 *addr, int reason_code)
+{
+	switch (reason_code) {
+	case MAX_CLIENT_REACHED:
+		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_MAX_STA MACSTR,
+			MAC2STR(addr));
+		break;
+	case BLOCKED_CLIENT:
+		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_BLOCKED_STA MACSTR,
+			MAC2STR(addr));
+		break;
+	}
+}
+
+
+#ifdef CONFIG_ACS
+void hostapd_acs_channel_selected(struct hostapd_data *hapd,
+				  struct acs_selected_channels *acs_res)
+{
+	int ret, i;
+	int err = 0;
+
+	if (hapd->iconf->channel) {
+		wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
+			   hapd->iconf->channel);
+		return;
+	}
+
+	if (!hapd->iface->current_mode) {
+		for (i = 0; i < hapd->iface->num_hw_features; i++) {
+			struct hostapd_hw_modes *mode =
+				&hapd->iface->hw_features[i];
+
+			if (mode->mode == acs_res->hw_mode) {
+				hapd->iface->current_mode = mode;
+				break;
+			}
+		}
+		if (!hapd->iface->current_mode) {
+			hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+				       HOSTAPD_LEVEL_WARNING,
+				       "driver selected to bad hw_mode");
+			err = 1;
+			goto out;
+		}
+	}
+
+	hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel);
+
+	if (!acs_res->pri_channel) {
+		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_WARNING,
+			       "driver switched to bad channel");
+		err = 1;
+		goto out;
+	}
+
+	hapd->iconf->channel = acs_res->pri_channel;
+	hapd->iconf->acs = 1;
+
+	if (acs_res->sec_channel == 0)
+		hapd->iconf->secondary_channel = 0;
+	else if (acs_res->sec_channel < acs_res->pri_channel)
+		hapd->iconf->secondary_channel = -1;
+	else if (acs_res->sec_channel > acs_res->pri_channel)
+		hapd->iconf->secondary_channel = 1;
+	else {
+		wpa_printf(MSG_ERROR, "Invalid secondary channel!");
+		err = 1;
+		goto out;
+	}
+
+	if (hapd->iface->conf->ieee80211ac) {
+		/* set defaults for backwards compatibility */
+		hapd->iconf->vht_oper_centr_freq_seg1_idx = 0;
+		hapd->iconf->vht_oper_centr_freq_seg0_idx = 0;
+		hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
+		if (acs_res->ch_width == 80) {
+			hapd->iconf->vht_oper_centr_freq_seg0_idx =
+				acs_res->vht_seg0_center_ch;
+			hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
+		} else if (acs_res->ch_width == 160) {
+			if (acs_res->vht_seg1_center_ch == 0) {
+				hapd->iconf->vht_oper_centr_freq_seg0_idx =
+					acs_res->vht_seg0_center_ch;
+				hapd->iconf->vht_oper_chwidth =
+					VHT_CHANWIDTH_160MHZ;
+			} else {
+				hapd->iconf->vht_oper_centr_freq_seg0_idx =
+					acs_res->vht_seg0_center_ch;
+				hapd->iconf->vht_oper_centr_freq_seg1_idx =
+					acs_res->vht_seg1_center_ch;
+				hapd->iconf->vht_oper_chwidth =
+					VHT_CHANWIDTH_80P80MHZ;
+			}
+		}
+	}
+
+out:
+	ret = hostapd_acs_completed(hapd->iface, err);
+	if (ret) {
+		wpa_printf(MSG_ERROR,
+			   "ACS: Possibly channel configuration is invalid");
+	}
+}
+#endif /* CONFIG_ACS */
+
+
+int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
+			 const u8 *bssid, const u8 *ie, size_t ie_len,
+			 int ssi_signal)
+{
+	size_t i;
+	int ret = 0;
+
+	if (sa == NULL || ie == NULL)
+		return -1;
+
+	random_add_randomness(sa, ETH_ALEN);
+	for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) {
+		if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
+					    sa, da, bssid, ie, ie_len,
+					    ssi_signal) > 0) {
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+
+#ifdef HOSTAPD
+
+#ifdef CONFIG_IEEE80211R
+static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst,
+					  const u8 *bssid,
+					  u16 auth_transaction, u16 status,
+					  const u8 *ies, size_t ies_len)
+{
+	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta;
+
+	sta = ap_get_sta(hapd, dst);
+	if (sta == NULL)
+		return;
+
+	hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
+		       HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
+	sta->flags |= WLAN_STA_AUTH;
+
+	hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len);
+}
+#endif /* CONFIG_IEEE80211R */
+
+
+static void hostapd_notif_auth(struct hostapd_data *hapd,
+			       struct auth_info *rx_auth)
+{
+	struct sta_info *sta;
+	u16 status = WLAN_STATUS_SUCCESS;
+	u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
+	size_t resp_ies_len = 0;
+
+	sta = ap_get_sta(hapd, rx_auth->peer);
+	if (!sta) {
+		sta = ap_sta_add(hapd, rx_auth->peer);
+		if (sta == NULL) {
+			status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+			goto fail;
+		}
+	}
+	sta->flags &= ~WLAN_STA_PREAUTH;
+	ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
+#ifdef CONFIG_IEEE80211R
+	if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) {
+		sta->auth_alg = WLAN_AUTH_FT;
+		if (sta->wpa_sm == NULL)
+			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
+							sta->addr, NULL);
+		if (sta->wpa_sm == NULL) {
+			wpa_printf(MSG_DEBUG,
+				   "FT: Failed to initialize WPA state machine");
+			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			goto fail;
+		}
+		wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid,
+				    rx_auth->auth_transaction, rx_auth->ies,
+				    rx_auth->ies_len,
+				    hostapd_notify_auth_ft_finish, hapd);
+		return;
+	}
+#endif /* CONFIG_IEEE80211R */
+fail:
+	hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1,
+			 status, resp_ies, resp_ies_len);
+}
+
+
+static void hostapd_action_rx(struct hostapd_data *hapd,
+			      struct rx_mgmt *drv_mgmt)
+{
+	struct ieee80211_mgmt *mgmt;
+	struct sta_info *sta;
+	size_t plen __maybe_unused;
+	u16 fc;
+
+	if (drv_mgmt->frame_len < 24 + 1)
+		return;
+
+	plen = drv_mgmt->frame_len - 24 - 1;
+
+	mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame;
+	fc = le_to_host16(mgmt->frame_control);
+	if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION)
+		return; /* handled by the driver */
+
+	wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
+		   mgmt->u.action.category, (int) plen);
+
+	sta = ap_get_sta(hapd, mgmt->sa);
+	if (sta == NULL) {
+		wpa_printf(MSG_DEBUG, "%s: station not found", __func__);
+		return;
+	}
+#ifdef CONFIG_IEEE80211R
+	if (mgmt->u.action.category == WLAN_ACTION_FT) {
+		const u8 *payload = drv_mgmt->frame + 24 + 1;
+
+		wpa_ft_action_rx(sta->wpa_sm, payload, plen);
+	}
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211W
+	if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY && plen >= 4) {
+		ieee802_11_sa_query_action(
+			hapd, mgmt->sa,
+			mgmt->u.action.u.sa_query_resp.action,
+			mgmt->u.action.u.sa_query_resp.trans_id);
+	}
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_WNM
+	if (mgmt->u.action.category == WLAN_ACTION_WNM) {
+		ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len);
+	}
+#endif /* CONFIG_WNM */
+#ifdef CONFIG_FST
+	if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) {
+		fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len);
+		return;
+	}
+#endif /* CONFIG_FST */
+
+}
+
+
+#ifdef NEED_AP_MLME
+
+#define HAPD_BROADCAST ((struct hostapd_data *) -1)
+
+static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface,
+					    const u8 *bssid)
+{
+	size_t i;
+
+	if (bssid == NULL)
+		return NULL;
+	if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff &&
+	    bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff)
+		return HAPD_BROADCAST;
+
+	for (i = 0; i < iface->num_bss; i++) {
+		if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0)
+			return iface->bss[i];
+	}
+
+	return NULL;
+}
+
+
+static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd,
+					const u8 *bssid, const u8 *addr,
+					int wds)
+{
+	hapd = get_hapd_bssid(hapd->iface, bssid);
+	if (hapd == NULL || hapd == HAPD_BROADCAST)
+		return;
+
+	ieee802_11_rx_from_unknown(hapd, addr, wds);
+}
+
+
+static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
+{
+	struct hostapd_iface *iface = hapd->iface;
+	const struct ieee80211_hdr *hdr;
+	const u8 *bssid;
+	struct hostapd_frame_info fi;
+	int ret;
+
+#ifdef CONFIG_TESTING_OPTIONS
+	if (hapd->ext_mgmt_frame_handling) {
+		size_t hex_len = 2 * rx_mgmt->frame_len + 1;
+		char *hex = os_malloc(hex_len);
+
+		if (hex) {
+			wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame,
+					 rx_mgmt->frame_len);
+			wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex);
+			os_free(hex);
+		}
+		return 1;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+
+	hdr = (const struct ieee80211_hdr *) rx_mgmt->frame;
+	bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len);
+	if (bssid == NULL)
+		return 0;
+
+	hapd = get_hapd_bssid(iface, bssid);
+	if (hapd == NULL) {
+		u16 fc = le_to_host16(hdr->frame_control);
+
+		/*
+		 * Drop frames to unknown BSSIDs except for Beacon frames which
+		 * could be used to update neighbor information.
+		 */
+		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
+		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
+			hapd = iface->bss[0];
+		else
+			return 0;
+	}
+
+	os_memset(&fi, 0, sizeof(fi));
+	fi.datarate = rx_mgmt->datarate;
+	fi.ssi_signal = rx_mgmt->ssi_signal;
+
+	if (hapd == HAPD_BROADCAST) {
+		size_t i;
+
+		ret = 0;
+		for (i = 0; i < iface->num_bss; i++) {
+			/* if bss is set, driver will call this function for
+			 * each bss individually. */
+			if (rx_mgmt->drv_priv &&
+			    (iface->bss[i]->drv_priv != rx_mgmt->drv_priv))
+				continue;
+
+			if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
+					    rx_mgmt->frame_len, &fi) > 0)
+				ret = 1;
+		}
+	} else
+		ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len,
+				      &fi);
+
+	random_add_randomness(&fi, sizeof(fi));
+
+	return ret;
+}
+
+
+static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
+			       size_t len, u16 stype, int ok)
+{
+	struct ieee80211_hdr *hdr;
+	struct hostapd_data *orig_hapd = hapd;
+
+	hdr = (struct ieee80211_hdr *) buf;
+	hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
+	if (!hapd)
+		return;
+	if (hapd == HAPD_BROADCAST) {
+		if (stype != WLAN_FC_STYPE_ACTION || len <= 25 ||
+		    buf[24] != WLAN_ACTION_PUBLIC)
+			return;
+		hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2);
+		if (!hapd || hapd == HAPD_BROADCAST)
+			return;
+		/*
+		 * Allow processing of TX status for a Public Action frame that
+		 * used wildcard BBSID.
+		 */
+	}
+	ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
+}
+
+#endif /* NEED_AP_MLME */
+
+
+static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
+{
+	struct sta_info *sta = ap_get_sta(hapd, addr);
+
+	if (sta)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR
+		   " - adding a new STA", MAC2STR(addr));
+	sta = ap_sta_add(hapd, addr);
+	if (sta) {
+		hostapd_new_assoc_sta(hapd, sta, 0);
+	} else {
+		wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR,
+			   MAC2STR(addr));
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
+				   const u8 *data, size_t data_len)
+{
+	struct hostapd_iface *iface = hapd->iface;
+	struct sta_info *sta;
+	size_t j;
+
+	for (j = 0; j < iface->num_bss; j++) {
+		sta = ap_get_sta(iface->bss[j], src);
+		if (sta && sta->flags & WLAN_STA_ASSOC) {
+			hapd = iface->bss[j];
+			break;
+		}
+	}
+
+	ieee802_1x_receive(hapd, src, data, data_len);
+}
+
+#endif /* HOSTAPD */
+
+
+static struct hostapd_channel_data * hostapd_get_mode_channel(
+	struct hostapd_iface *iface, unsigned int freq)
+{
+	int i;
+	struct hostapd_channel_data *chan;
+
+	for (i = 0; i < iface->current_mode->num_channels; i++) {
+		chan = &iface->current_mode->channels[i];
+		if ((unsigned int) chan->freq == freq)
+			return chan;
+	}
+
+	return NULL;
+}
+
+
+static void hostapd_update_nf(struct hostapd_iface *iface,
+			      struct hostapd_channel_data *chan,
+			      struct freq_survey *survey)
+{
+	if (!iface->chans_surveyed) {
+		chan->min_nf = survey->nf;
+		iface->lowest_nf = survey->nf;
+	} else {
+		if (dl_list_empty(&chan->survey_list))
+			chan->min_nf = survey->nf;
+		else if (survey->nf < chan->min_nf)
+			chan->min_nf = survey->nf;
+		if (survey->nf < iface->lowest_nf)
+			iface->lowest_nf = survey->nf;
+	}
+}
+
+
+static void hostapd_single_channel_get_survey(struct hostapd_iface *iface,
+					      struct survey_results *survey_res)
+{
+	struct hostapd_channel_data *chan;
+	struct freq_survey *survey;
+	u64 divisor, dividend;
+
+	survey = dl_list_first(&survey_res->survey_list, struct freq_survey,
+			       list);
+	if (!survey || !survey->freq)
+		return;
+
+	chan = hostapd_get_mode_channel(iface, survey->freq);
+	if (!chan || chan->flag & HOSTAPD_CHAN_DISABLED)
+		return;
+
+	wpa_printf(MSG_DEBUG,
+		   "Single Channel Survey: (freq=%d channel_time=%ld channel_time_busy=%ld)",
+		   survey->freq,
+		   (unsigned long int) survey->channel_time,
+		   (unsigned long int) survey->channel_time_busy);
+
+	if (survey->channel_time > iface->last_channel_time &&
+	    survey->channel_time > survey->channel_time_busy) {
+		dividend = survey->channel_time_busy -
+			iface->last_channel_time_busy;
+		divisor = survey->channel_time - iface->last_channel_time;
+
+		iface->channel_utilization = dividend * 255 / divisor;
+		wpa_printf(MSG_DEBUG, "Channel Utilization: %d",
+			   iface->channel_utilization);
+	}
+	iface->last_channel_time = survey->channel_time;
+	iface->last_channel_time_busy = survey->channel_time_busy;
+}
+
+
+void hostapd_event_get_survey(struct hostapd_iface *iface,
+			      struct survey_results *survey_results)
+{
+	struct freq_survey *survey, *tmp;
+	struct hostapd_channel_data *chan;
+
+	if (dl_list_empty(&survey_results->survey_list)) {
+		wpa_printf(MSG_DEBUG, "No survey data received");
+		return;
+	}
+
+	if (survey_results->freq_filter) {
+		hostapd_single_channel_get_survey(iface, survey_results);
+		return;
+	}
+
+	dl_list_for_each_safe(survey, tmp, &survey_results->survey_list,
+			      struct freq_survey, list) {
+		chan = hostapd_get_mode_channel(iface, survey->freq);
+		if (!chan)
+			continue;
+		if (chan->flag & HOSTAPD_CHAN_DISABLED)
+			continue;
+
+		dl_list_del(&survey->list);
+		dl_list_add_tail(&chan->survey_list, &survey->list);
+
+		hostapd_update_nf(iface, chan, survey);
+
+		iface->chans_surveyed++;
+	}
+}
+
+
+#ifdef HOSTAPD
+#ifdef NEED_AP_MLME
+
+static void hostapd_event_iface_unavailable(struct hostapd_data *hapd)
+{
+	wpa_printf(MSG_DEBUG, "Interface %s is unavailable -- stopped",
+		   hapd->conf->iface);
+
+	if (hapd->csa_in_progress) {
+		wpa_printf(MSG_INFO, "CSA failed (%s was stopped)",
+			   hapd->conf->iface);
+		hostapd_switch_channel_fallback(hapd->iface,
+						&hapd->cs_freq_params);
+	}
+}
+
+
+static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd,
+					     struct dfs_event *radar)
+{
+	wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
+	hostapd_dfs_radar_detected(hapd->iface, radar->freq, radar->ht_enabled,
+				   radar->chan_offset, radar->chan_width,
+				   radar->cf1, radar->cf2);
+}
+
+
+static void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd,
+					   struct dfs_event *radar)
+{
+	wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
+	hostapd_dfs_complete_cac(hapd->iface, 1, radar->freq, radar->ht_enabled,
+				 radar->chan_offset, radar->chan_width,
+				 radar->cf1, radar->cf2);
+}
+
+
+static void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd,
+					  struct dfs_event *radar)
+{
+	wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
+	hostapd_dfs_complete_cac(hapd->iface, 0, radar->freq, radar->ht_enabled,
+				 radar->chan_offset, radar->chan_width,
+				 radar->cf1, radar->cf2);
+}
+
+
+static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd,
+					   struct dfs_event *radar)
+{
+	wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
+	hostapd_dfs_nop_finished(hapd->iface, radar->freq, radar->ht_enabled,
+				 radar->chan_offset, radar->chan_width,
+				 radar->cf1, radar->cf2);
+}
+
+
+static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
+					  struct dfs_event *radar)
+{
+	wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq);
+	hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled,
+			      radar->chan_offset, radar->chan_width,
+			      radar->cf1, radar->cf2);
+}
+
+#endif /* NEED_AP_MLME */
+
+
+void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
+			  union wpa_event_data *data)
+{
+	struct hostapd_data *hapd = ctx;
+#ifndef CONFIG_NO_STDOUT_DEBUG
+	int level = MSG_DEBUG;
+
+	if (event == EVENT_RX_MGMT && data->rx_mgmt.frame &&
+	    data->rx_mgmt.frame_len >= 24) {
+		const struct ieee80211_hdr *hdr;
+		u16 fc;
+
+		hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
+		fc = le_to_host16(hdr->frame_control);
+		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
+		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
+			level = MSG_EXCESSIVE;
+		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
+		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ)
+			level = MSG_EXCESSIVE;
+	}
+
+	wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received",
+		event_to_string(event), event);
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+	switch (event) {
+	case EVENT_MICHAEL_MIC_FAILURE:
+		michael_mic_failure(hapd, data->michael_mic_failure.src, 1);
+		break;
+	case EVENT_SCAN_RESULTS:
+		if (hapd->iface->scan_cb)
+			hapd->iface->scan_cb(hapd->iface);
+		break;
+	case EVENT_WPS_BUTTON_PUSHED:
+		hostapd_wps_button_pushed(hapd, NULL);
+		break;
+#ifdef NEED_AP_MLME
+	case EVENT_TX_STATUS:
+		switch (data->tx_status.type) {
+		case WLAN_FC_TYPE_MGMT:
+			hostapd_mgmt_tx_cb(hapd, data->tx_status.data,
+					   data->tx_status.data_len,
+					   data->tx_status.stype,
+					   data->tx_status.ack);
+			break;
+		case WLAN_FC_TYPE_DATA:
+			hostapd_tx_status(hapd, data->tx_status.dst,
+					  data->tx_status.data,
+					  data->tx_status.data_len,
+					  data->tx_status.ack);
+			break;
+		}
+		break;
+	case EVENT_EAPOL_TX_STATUS:
+		hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst,
+					data->eapol_tx_status.data,
+					data->eapol_tx_status.data_len,
+					data->eapol_tx_status.ack);
+		break;
+	case EVENT_DRIVER_CLIENT_POLL_OK:
+		hostapd_client_poll_ok(hapd, data->client_poll.addr);
+		break;
+	case EVENT_RX_FROM_UNKNOWN:
+		hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid,
+					    data->rx_from_unknown.addr,
+					    data->rx_from_unknown.wds);
+		break;
+#endif /* NEED_AP_MLME */
+	case EVENT_RX_MGMT:
+		if (!data->rx_mgmt.frame)
+			break;
+#ifdef NEED_AP_MLME
+		if (hostapd_mgmt_rx(hapd, &data->rx_mgmt) > 0)
+			break;
+#endif /* NEED_AP_MLME */
+		hostapd_action_rx(hapd, &data->rx_mgmt);
+		break;
+	case EVENT_RX_PROBE_REQ:
+		if (data->rx_probe_req.sa == NULL ||
+		    data->rx_probe_req.ie == NULL)
+			break;
+		hostapd_probe_req_rx(hapd, data->rx_probe_req.sa,
+				     data->rx_probe_req.da,
+				     data->rx_probe_req.bssid,
+				     data->rx_probe_req.ie,
+				     data->rx_probe_req.ie_len,
+				     data->rx_probe_req.ssi_signal);
+		break;
+	case EVENT_NEW_STA:
+		hostapd_event_new_sta(hapd, data->new_sta.addr);
+		break;
+	case EVENT_EAPOL_RX:
+		hostapd_event_eapol_rx(hapd, data->eapol_rx.src,
+				       data->eapol_rx.data,
+				       data->eapol_rx.data_len);
+		break;
+	case EVENT_ASSOC:
+		if (!data)
+			return;
+		hostapd_notif_assoc(hapd, data->assoc_info.addr,
+				    data->assoc_info.req_ies,
+				    data->assoc_info.req_ies_len,
+				    data->assoc_info.reassoc);
+		break;
+	case EVENT_DISASSOC:
+		if (data)
+			hostapd_notif_disassoc(hapd, data->disassoc_info.addr);
+		break;
+	case EVENT_DEAUTH:
+		if (data)
+			hostapd_notif_disassoc(hapd, data->deauth_info.addr);
+		break;
+	case EVENT_STATION_LOW_ACK:
+		if (!data)
+			break;
+		hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
+		break;
+	case EVENT_AUTH:
+		hostapd_notif_auth(hapd, &data->auth);
+		break;
+	case EVENT_CH_SWITCH:
+		if (!data)
+			break;
+		hostapd_event_ch_switch(hapd, data->ch_switch.freq,
+					data->ch_switch.ht_enabled,
+					data->ch_switch.ch_offset,
+					data->ch_switch.ch_width,
+					data->ch_switch.cf1,
+					data->ch_switch.cf2);
+		break;
+	case EVENT_CONNECT_FAILED_REASON:
+		if (!data)
+			break;
+		hostapd_event_connect_failed_reason(
+			hapd, data->connect_failed_reason.addr,
+			data->connect_failed_reason.code);
+		break;
+	case EVENT_SURVEY:
+		hostapd_event_get_survey(hapd->iface, &data->survey_results);
+		break;
+#ifdef NEED_AP_MLME
+	case EVENT_INTERFACE_UNAVAILABLE:
+		hostapd_event_iface_unavailable(hapd);
+		break;
+	case EVENT_DFS_RADAR_DETECTED:
+		if (!data)
+			break;
+		hostapd_event_dfs_radar_detected(hapd, &data->dfs_event);
+		break;
+	case EVENT_DFS_CAC_FINISHED:
+		if (!data)
+			break;
+		hostapd_event_dfs_cac_finished(hapd, &data->dfs_event);
+		break;
+	case EVENT_DFS_CAC_ABORTED:
+		if (!data)
+			break;
+		hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event);
+		break;
+	case EVENT_DFS_NOP_FINISHED:
+		if (!data)
+			break;
+		hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
+		break;
+	case EVENT_CHANNEL_LIST_CHANGED:
+		/* channel list changed (regulatory?), update channel list */
+		/* TODO: check this. hostapd_get_hw_features() initializes
+		 * too much stuff. */
+		/* hostapd_get_hw_features(hapd->iface); */
+		hostapd_channel_list_updated(
+			hapd->iface, data->channel_list_changed.initiator);
+		break;
+	case EVENT_DFS_CAC_STARTED:
+		if (!data)
+			break;
+		hostapd_event_dfs_cac_started(hapd, &data->dfs_event);
+		break;
+#endif /* NEED_AP_MLME */
+	case EVENT_INTERFACE_ENABLED:
+		wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
+		if (hapd->disabled && hapd->started) {
+			hapd->disabled = 0;
+			/*
+			 * Try to re-enable interface if the driver stopped it
+			 * when the interface got disabled.
+			 */
+			wpa_auth_reconfig_group_keys(hapd->wpa_auth);
+			hapd->reenable_beacon = 1;
+			ieee802_11_set_beacon(hapd);
+		}
+		break;
+	case EVENT_INTERFACE_DISABLED:
+		hostapd_free_stas(hapd);
+		wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED);
+		hapd->disabled = 1;
+		break;
+#ifdef CONFIG_ACS
+	case EVENT_ACS_CHANNEL_SELECTED:
+		hostapd_acs_channel_selected(hapd,
+					     &data->acs_selected_channels);
+		break;
+#endif /* CONFIG_ACS */
+	default:
+		wpa_printf(MSG_DEBUG, "Unknown event %d", event);
+		break;
+	}
+}
+
+
+void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
+				 union wpa_event_data *data)
+{
+	struct hapd_interfaces *interfaces = ctx;
+	struct hostapd_data *hapd;
+
+	if (event != EVENT_INTERFACE_STATUS)
+		return;
+
+	hapd = hostapd_get_iface(interfaces, data->interface_status.ifname);
+	if (hapd && hapd->driver && hapd->driver->get_ifindex &&
+	    hapd->drv_priv) {
+		unsigned int ifindex;
+
+		ifindex = hapd->driver->get_ifindex(hapd->drv_priv);
+		if (ifindex != data->interface_status.ifindex) {
+			wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
+				"interface status ifindex %d mismatch (%d)",
+				ifindex, data->interface_status.ifindex);
+			return;
+		}
+	}
+	if (hapd)
+		wpa_supplicant_event(hapd, event, data);
+}
+
+#endif /* HOSTAPD */

+ 32 - 0
EVSE/GPL/hostapd-2.6/src/ap/drv_callbacks.d

@@ -0,0 +1,32 @@
+../src/ap/drv_callbacks.o: ../src/ap/drv_callbacks.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/eloop.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_ctrl.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/crypto/random.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/p2p/p2p.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/wnm_ap.h ../src/ap/hostapd.h ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ ../src/ap/vlan.h ../src/ap/ieee802_11.h ../src/ap/ieee802_11_auth.h \
+ ../src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/accounting.h ../src/ap/tkip_countermeasures.h \
+ ../src/ap/ieee802_1x.h ../src/ap/wpa_auth.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/eapol_common.h \
+ ../src/ap/wps_hostapd.h ../src/ap/ap_drv_ops.h ../src/ap/hw_features.h \
+ ../src/ap/dfs.h ../src/ap/beacon.h ../src/ap/mbo_ap.h

+ 282 - 0
EVSE/GPL/hostapd-2.6/src/ap/eap_user_db.c

@@ -0,0 +1,282 @@
+/*
+ * hostapd / EAP user database
+ * Copyright (c) 2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+#ifdef CONFIG_SQLITE
+#include <sqlite3.h>
+#endif /* CONFIG_SQLITE */
+
+#include "common.h"
+#include "eap_common/eap_wsc_common.h"
+#include "eap_server/eap_methods.h"
+#include "eap_server/eap.h"
+#include "ap_config.h"
+#include "hostapd.h"
+
+#ifdef CONFIG_SQLITE
+
+static void set_user_methods(struct hostapd_eap_user *user, const char *methods)
+{
+	char *buf, *start;
+	int num_methods;
+
+	buf = os_strdup(methods);
+	if (buf == NULL)
+		return;
+
+	os_memset(&user->methods, 0, sizeof(user->methods));
+	num_methods = 0;
+	start = buf;
+	while (*start) {
+		char *pos3 = os_strchr(start, ',');
+		if (pos3)
+			*pos3++ = '\0';
+		user->methods[num_methods].method =
+			eap_server_get_type(start,
+					    &user->methods[num_methods].vendor);
+		if (user->methods[num_methods].vendor == EAP_VENDOR_IETF &&
+		    user->methods[num_methods].method == EAP_TYPE_NONE) {
+			if (os_strcmp(start, "TTLS-PAP") == 0) {
+				user->ttls_auth |= EAP_TTLS_AUTH_PAP;
+				goto skip_eap;
+			}
+			if (os_strcmp(start, "TTLS-CHAP") == 0) {
+				user->ttls_auth |= EAP_TTLS_AUTH_CHAP;
+				goto skip_eap;
+			}
+			if (os_strcmp(start, "TTLS-MSCHAP") == 0) {
+				user->ttls_auth |= EAP_TTLS_AUTH_MSCHAP;
+				goto skip_eap;
+			}
+			if (os_strcmp(start, "TTLS-MSCHAPV2") == 0) {
+				user->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2;
+				goto skip_eap;
+			}
+			wpa_printf(MSG_INFO, "DB: Unsupported EAP type '%s'",
+				   start);
+			os_free(buf);
+			return;
+		}
+
+		num_methods++;
+		if (num_methods >= EAP_MAX_METHODS)
+			break;
+	skip_eap:
+		if (pos3 == NULL)
+			break;
+		start = pos3;
+	}
+
+	os_free(buf);
+}
+
+
+static int get_user_cb(void *ctx, int argc, char *argv[], char *col[])
+{
+	struct hostapd_eap_user *user = ctx;
+	int i;
+
+	for (i = 0; i < argc; i++) {
+		if (os_strcmp(col[i], "password") == 0 && argv[i]) {
+			bin_clear_free(user->password, user->password_len);
+			user->password_len = os_strlen(argv[i]);
+			user->password = (u8 *) os_strdup(argv[i]);
+			user->next = (void *) 1;
+		} else if (os_strcmp(col[i], "methods") == 0 && argv[i]) {
+			set_user_methods(user, argv[i]);
+		} else if (os_strcmp(col[i], "remediation") == 0 && argv[i]) {
+			user->remediation = strlen(argv[i]) > 0;
+		}
+	}
+
+	return 0;
+}
+
+
+static int get_wildcard_cb(void *ctx, int argc, char *argv[], char *col[])
+{
+	struct hostapd_eap_user *user = ctx;
+	int i, id = -1, methods = -1;
+	size_t len;
+
+	for (i = 0; i < argc; i++) {
+		if (os_strcmp(col[i], "identity") == 0 && argv[i])
+			id = i;
+		else if (os_strcmp(col[i], "methods") == 0 && argv[i])
+			methods = i;
+	}
+
+	if (id < 0 || methods < 0)
+		return 0;
+
+	len = os_strlen(argv[id]);
+	if (len <= user->identity_len &&
+	    os_memcmp(argv[id], user->identity, len) == 0 &&
+	    (user->password == NULL || len > user->password_len)) {
+		bin_clear_free(user->password, user->password_len);
+		user->password_len = os_strlen(argv[id]);
+		user->password = (u8 *) os_strdup(argv[id]);
+		user->next = (void *) 1;
+		set_user_methods(user, argv[methods]);
+	}
+
+	return 0;
+}
+
+
+static const struct hostapd_eap_user *
+eap_user_sqlite_get(struct hostapd_data *hapd, const u8 *identity,
+		    size_t identity_len, int phase2)
+{
+	sqlite3 *db;
+	struct hostapd_eap_user *user = NULL;
+	char id_str[256], cmd[300];
+	size_t i;
+
+	if (identity_len >= sizeof(id_str)) {
+		wpa_printf(MSG_DEBUG, "%s: identity len too big: %d >= %d",
+			   __func__, (int) identity_len,
+			   (int) (sizeof(id_str)));
+		return NULL;
+	}
+	os_memcpy(id_str, identity, identity_len);
+	id_str[identity_len] = '\0';
+	for (i = 0; i < identity_len; i++) {
+		if (id_str[i] >= 'a' && id_str[i] <= 'z')
+			continue;
+		if (id_str[i] >= 'A' && id_str[i] <= 'Z')
+			continue;
+		if (id_str[i] >= '0' && id_str[i] <= '9')
+			continue;
+		if (id_str[i] == '-' || id_str[i] == '_' || id_str[i] == '.' ||
+		    id_str[i] == ',' || id_str[i] == '@' || id_str[i] == '\\' ||
+		    id_str[i] == '!' || id_str[i] == '#' || id_str[i] == '%' ||
+		    id_str[i] == '=' || id_str[i] == ' ')
+			continue;
+		wpa_printf(MSG_INFO, "DB: Unsupported character in identity");
+		return NULL;
+	}
+
+	bin_clear_free(hapd->tmp_eap_user.identity,
+		       hapd->tmp_eap_user.identity_len);
+	bin_clear_free(hapd->tmp_eap_user.password,
+		       hapd->tmp_eap_user.password_len);
+	os_memset(&hapd->tmp_eap_user, 0, sizeof(hapd->tmp_eap_user));
+	hapd->tmp_eap_user.phase2 = phase2;
+	hapd->tmp_eap_user.identity = os_zalloc(identity_len + 1);
+	if (hapd->tmp_eap_user.identity == NULL)
+		return NULL;
+	os_memcpy(hapd->tmp_eap_user.identity, identity, identity_len);
+
+	if (sqlite3_open(hapd->conf->eap_user_sqlite, &db)) {
+		wpa_printf(MSG_INFO, "DB: Failed to open database %s: %s",
+			   hapd->conf->eap_user_sqlite, sqlite3_errmsg(db));
+		sqlite3_close(db);
+		return NULL;
+	}
+
+	os_snprintf(cmd, sizeof(cmd),
+		    "SELECT * FROM users WHERE identity='%s' AND phase2=%d;",
+		    id_str, phase2);
+	wpa_printf(MSG_DEBUG, "DB: %s", cmd);
+	if (sqlite3_exec(db, cmd, get_user_cb, &hapd->tmp_eap_user, NULL) !=
+	    SQLITE_OK) {
+		wpa_printf(MSG_DEBUG,
+			   "DB: Failed to complete SQL operation: %s  db: %s",
+			   sqlite3_errmsg(db), hapd->conf->eap_user_sqlite);
+	} else if (hapd->tmp_eap_user.next)
+		user = &hapd->tmp_eap_user;
+
+	if (user == NULL && !phase2) {
+		os_snprintf(cmd, sizeof(cmd),
+			    "SELECT identity,methods FROM wildcards;");
+		wpa_printf(MSG_DEBUG, "DB: %s", cmd);
+		if (sqlite3_exec(db, cmd, get_wildcard_cb, &hapd->tmp_eap_user,
+				 NULL) != SQLITE_OK) {
+			wpa_printf(MSG_DEBUG,
+				   "DB: Failed to complete SQL operation: %s  db: %s",
+				   sqlite3_errmsg(db),
+				   hapd->conf->eap_user_sqlite);
+		} else if (hapd->tmp_eap_user.next) {
+			user = &hapd->tmp_eap_user;
+			os_free(user->identity);
+			user->identity = user->password;
+			user->identity_len = user->password_len;
+			user->password = NULL;
+			user->password_len = 0;
+		}
+	}
+
+	sqlite3_close(db);
+
+	return user;
+}
+
+#endif /* CONFIG_SQLITE */
+
+
+const struct hostapd_eap_user *
+hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
+		     size_t identity_len, int phase2)
+{
+	const struct hostapd_bss_config *conf = hapd->conf;
+	struct hostapd_eap_user *user = conf->eap_user;
+
+#ifdef CONFIG_WPS
+	if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN &&
+	    os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) {
+		static struct hostapd_eap_user wsc_enrollee;
+		os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee));
+		wsc_enrollee.methods[0].method = eap_server_get_type(
+			"WSC", &wsc_enrollee.methods[0].vendor);
+		return &wsc_enrollee;
+	}
+
+	if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN &&
+	    os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) {
+		static struct hostapd_eap_user wsc_registrar;
+		os_memset(&wsc_registrar, 0, sizeof(wsc_registrar));
+		wsc_registrar.methods[0].method = eap_server_get_type(
+			"WSC", &wsc_registrar.methods[0].vendor);
+		wsc_registrar.password = (u8 *) conf->ap_pin;
+		wsc_registrar.password_len = conf->ap_pin ?
+			os_strlen(conf->ap_pin) : 0;
+		return &wsc_registrar;
+	}
+#endif /* CONFIG_WPS */
+
+	while (user) {
+		if (!phase2 && user->identity == NULL) {
+			/* Wildcard match */
+			break;
+		}
+
+		if (user->phase2 == !!phase2 && user->wildcard_prefix &&
+		    identity_len >= user->identity_len &&
+		    os_memcmp(user->identity, identity, user->identity_len) ==
+		    0) {
+			/* Wildcard prefix match */
+			break;
+		}
+
+		if (user->phase2 == !!phase2 &&
+		    user->identity_len == identity_len &&
+		    os_memcmp(user->identity, identity, identity_len) == 0)
+			break;
+		user = user->next;
+	}
+
+#ifdef CONFIG_SQLITE
+	if (user == NULL && conf->eap_user_sqlite) {
+		return eap_user_sqlite_get(hapd, identity, identity_len,
+					   phase2);
+	}
+#endif /* CONFIG_SQLITE */
+
+	return user;
+}

+ 26 - 0
EVSE/GPL/hostapd-2.6/src/ap/eap_user_db.d

@@ -0,0 +1,26 @@
+../src/ap/eap_user_db.o: ../src/ap/eap_user_db.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_common/eap_wsc_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap_methods.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_common/eap_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/eap.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/vlan.h ../src/ap/hostapd.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h

+ 1507 - 0
EVSE/GPL/hostapd-2.6/src/ap/gas_serv.c

@@ -0,0 +1,1507 @@
+/*
+ * Generic advertisement service (GAS) server
+ * Copyright (c) 2011-2014, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "common/ieee802_11_defs.h"
+#include "common/gas.h"
+#include "utils/eloop.h"
+#include "hostapd.h"
+#include "ap_config.h"
+#include "ap_drv_ops.h"
+#include "sta_info.h"
+#include "gas_serv.h"
+
+
+static void convert_to_protected_dual(struct wpabuf *msg)
+{
+	u8 *categ = wpabuf_mhead_u8(msg);
+	*categ = WLAN_ACTION_PROTECTED_DUAL;
+}
+
+
+static struct gas_dialog_info *
+gas_dialog_create(struct hostapd_data *hapd, const u8 *addr, u8 dialog_token)
+{
+	struct sta_info *sta;
+	struct gas_dialog_info *dia = NULL;
+	int i, j;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta) {
+		/*
+		 * We need a STA entry to be able to maintain state for
+		 * the GAS query.
+		 */
+		wpa_printf(MSG_DEBUG, "ANQP: Add a temporary STA entry for "
+			   "GAS query");
+		sta = ap_sta_add(hapd, addr);
+		if (!sta) {
+			wpa_printf(MSG_DEBUG, "Failed to add STA " MACSTR
+				   " for GAS query", MAC2STR(addr));
+			return NULL;
+		}
+		sta->flags |= WLAN_STA_GAS;
+		/*
+		 * The default inactivity is 300 seconds. We don't need
+		 * it to be that long.
+		 */
+		ap_sta_session_timeout(hapd, sta, 5);
+	} else {
+		ap_sta_replenish_timeout(hapd, sta, 5);
+	}
+
+	if (sta->gas_dialog == NULL) {
+		sta->gas_dialog = os_calloc(GAS_DIALOG_MAX,
+					    sizeof(struct gas_dialog_info));
+		if (sta->gas_dialog == NULL)
+			return NULL;
+	}
+
+	for (i = sta->gas_dialog_next, j = 0; j < GAS_DIALOG_MAX; i++, j++) {
+		if (i == GAS_DIALOG_MAX)
+			i = 0;
+		if (sta->gas_dialog[i].valid)
+			continue;
+		dia = &sta->gas_dialog[i];
+		dia->valid = 1;
+		dia->dialog_token = dialog_token;
+		sta->gas_dialog_next = (++i == GAS_DIALOG_MAX) ? 0 : i;
+		return dia;
+	}
+
+	wpa_msg(hapd->msg_ctx, MSG_ERROR, "ANQP: Could not create dialog for "
+		MACSTR " dialog_token %u. Consider increasing "
+		"GAS_DIALOG_MAX.", MAC2STR(addr), dialog_token);
+
+	return NULL;
+}
+
+
+struct gas_dialog_info *
+gas_serv_dialog_find(struct hostapd_data *hapd, const u8 *addr,
+		     u8 dialog_token)
+{
+	struct sta_info *sta;
+	int i;
+
+	sta = ap_get_sta(hapd, addr);
+	if (!sta) {
+		wpa_printf(MSG_DEBUG, "ANQP: could not find STA " MACSTR,
+			   MAC2STR(addr));
+		return NULL;
+	}
+	for (i = 0; sta->gas_dialog && i < GAS_DIALOG_MAX; i++) {
+		if (sta->gas_dialog[i].dialog_token != dialog_token ||
+		    !sta->gas_dialog[i].valid)
+			continue;
+		ap_sta_replenish_timeout(hapd, sta, 5);
+		return &sta->gas_dialog[i];
+	}
+	wpa_printf(MSG_DEBUG, "ANQP: Could not find dialog for "
+		   MACSTR " dialog_token %u", MAC2STR(addr), dialog_token);
+	return NULL;
+}
+
+
+void gas_serv_dialog_clear(struct gas_dialog_info *dia)
+{
+	wpabuf_free(dia->sd_resp);
+	os_memset(dia, 0, sizeof(*dia));
+}
+
+
+static void gas_serv_free_dialogs(struct hostapd_data *hapd,
+				  const u8 *sta_addr)
+{
+	struct sta_info *sta;
+	int i;
+
+	sta = ap_get_sta(hapd, sta_addr);
+	if (sta == NULL || sta->gas_dialog == NULL)
+		return;
+
+	for (i = 0; i < GAS_DIALOG_MAX; i++) {
+		if (sta->gas_dialog[i].valid)
+			return;
+	}
+
+	os_free(sta->gas_dialog);
+	sta->gas_dialog = NULL;
+}
+
+
+#ifdef CONFIG_HS20
+static void anqp_add_hs_capab_list(struct hostapd_data *hapd,
+				   struct wpabuf *buf)
+{
+	u8 *len;
+
+	len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
+	wpabuf_put_be24(buf, OUI_WFA);
+	wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
+	wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
+	wpabuf_put_u8(buf, 0); /* Reserved */
+	wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
+	if (hapd->conf->hs20_oper_friendly_name)
+		wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
+	if (hapd->conf->hs20_wan_metrics)
+		wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS);
+	if (hapd->conf->hs20_connection_capability)
+		wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY);
+	if (hapd->conf->nai_realm_data)
+		wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
+	if (hapd->conf->hs20_operating_class)
+		wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
+	if (hapd->conf->hs20_osu_providers_count)
+		wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
+	if (hapd->conf->hs20_icons_count)
+		wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST);
+	gas_anqp_set_element_len(buf, len);
+}
+#endif /* CONFIG_HS20 */
+
+
+static struct anqp_element * get_anqp_elem(struct hostapd_data *hapd,
+					   u16 infoid)
+{
+	struct anqp_element *elem;
+
+	dl_list_for_each(elem, &hapd->conf->anqp_elem, struct anqp_element,
+			 list) {
+		if (elem->infoid == infoid)
+			return elem;
+	}
+
+	return NULL;
+}
+
+
+static void anqp_add_elem(struct hostapd_data *hapd, struct wpabuf *buf,
+			  u16 infoid)
+{
+	struct anqp_element *elem;
+
+	elem = get_anqp_elem(hapd, infoid);
+	if (!elem)
+		return;
+	if (wpabuf_tailroom(buf) < 2 + 2 + wpabuf_len(elem->payload)) {
+		wpa_printf(MSG_DEBUG, "ANQP: No room for InfoID %u payload",
+			   infoid);
+		return;
+	}
+
+	wpabuf_put_le16(buf, infoid);
+	wpabuf_put_le16(buf, wpabuf_len(elem->payload));
+	wpabuf_put_buf(buf, elem->payload);
+}
+
+
+static int anqp_add_override(struct hostapd_data *hapd, struct wpabuf *buf,
+			     u16 infoid)
+{
+	if (get_anqp_elem(hapd, infoid)) {
+		anqp_add_elem(hapd, buf, infoid);
+		return 1;
+	}
+
+	return 0;
+}
+
+
+static void anqp_add_capab_list(struct hostapd_data *hapd,
+				struct wpabuf *buf)
+{
+	u8 *len;
+	u16 id;
+
+	if (anqp_add_override(hapd, buf, ANQP_CAPABILITY_LIST))
+		return;
+
+	len = gas_anqp_add_element(buf, ANQP_CAPABILITY_LIST);
+	wpabuf_put_le16(buf, ANQP_CAPABILITY_LIST);
+	if (hapd->conf->venue_name || get_anqp_elem(hapd, ANQP_VENUE_NAME))
+		wpabuf_put_le16(buf, ANQP_VENUE_NAME);
+	if (get_anqp_elem(hapd, ANQP_EMERGENCY_CALL_NUMBER))
+		wpabuf_put_le16(buf, ANQP_EMERGENCY_CALL_NUMBER);
+	if (hapd->conf->network_auth_type ||
+	    get_anqp_elem(hapd, ANQP_NETWORK_AUTH_TYPE))
+		wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
+	if (hapd->conf->roaming_consortium ||
+	    get_anqp_elem(hapd, ANQP_ROAMING_CONSORTIUM))
+		wpabuf_put_le16(buf, ANQP_ROAMING_CONSORTIUM);
+	if (hapd->conf->ipaddr_type_configured ||
+	    get_anqp_elem(hapd, ANQP_IP_ADDR_TYPE_AVAILABILITY))
+		wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
+	if (hapd->conf->nai_realm_data ||
+	    get_anqp_elem(hapd, ANQP_NAI_REALM))
+		wpabuf_put_le16(buf, ANQP_NAI_REALM);
+	if (hapd->conf->anqp_3gpp_cell_net ||
+	    get_anqp_elem(hapd, ANQP_3GPP_CELLULAR_NETWORK))
+		wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
+	if (get_anqp_elem(hapd, ANQP_AP_GEOSPATIAL_LOCATION))
+		wpabuf_put_le16(buf, ANQP_AP_GEOSPATIAL_LOCATION);
+	if (get_anqp_elem(hapd, ANQP_AP_CIVIC_LOCATION))
+		wpabuf_put_le16(buf, ANQP_AP_CIVIC_LOCATION);
+	if (get_anqp_elem(hapd, ANQP_AP_LOCATION_PUBLIC_URI))
+		wpabuf_put_le16(buf, ANQP_AP_LOCATION_PUBLIC_URI);
+	if (hapd->conf->domain_name || get_anqp_elem(hapd, ANQP_DOMAIN_NAME))
+		wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
+	if (get_anqp_elem(hapd, ANQP_EMERGENCY_ALERT_URI))
+		wpabuf_put_le16(buf, ANQP_EMERGENCY_ALERT_URI);
+	if (get_anqp_elem(hapd, ANQP_EMERGENCY_NAI))
+		wpabuf_put_le16(buf, ANQP_EMERGENCY_NAI);
+	if (get_anqp_elem(hapd, ANQP_NEIGHBOR_REPORT))
+		wpabuf_put_le16(buf, ANQP_NEIGHBOR_REPORT);
+	for (id = 273; id < 277; id++) {
+		if (get_anqp_elem(hapd, id))
+			wpabuf_put_le16(buf, id);
+	}
+	if (get_anqp_elem(hapd, ANQP_VENUE_URL))
+		wpabuf_put_le16(buf, ANQP_VENUE_URL);
+	if (get_anqp_elem(hapd, ANQP_ADVICE_OF_CHARGE))
+		wpabuf_put_le16(buf, ANQP_ADVICE_OF_CHARGE);
+	if (get_anqp_elem(hapd, ANQP_LOCAL_CONTENT))
+		wpabuf_put_le16(buf, ANQP_LOCAL_CONTENT);
+#ifdef CONFIG_HS20
+	anqp_add_hs_capab_list(hapd, buf);
+#endif /* CONFIG_HS20 */
+	gas_anqp_set_element_len(buf, len);
+}
+
+
+static void anqp_add_venue_name(struct hostapd_data *hapd, struct wpabuf *buf)
+{
+	if (anqp_add_override(hapd, buf, ANQP_VENUE_NAME))
+		return;
+
+	if (hapd->conf->venue_name) {
+		u8 *len;
+		unsigned int i;
+		len = gas_anqp_add_element(buf, ANQP_VENUE_NAME);
+		wpabuf_put_u8(buf, hapd->conf->venue_group);
+		wpabuf_put_u8(buf, hapd->conf->venue_type);
+		for (i = 0; i < hapd->conf->venue_name_count; i++) {
+			struct hostapd_lang_string *vn;
+			vn = &hapd->conf->venue_name[i];
+			wpabuf_put_u8(buf, 3 + vn->name_len);
+			wpabuf_put_data(buf, vn->lang, 3);
+			wpabuf_put_data(buf, vn->name, vn->name_len);
+		}
+		gas_anqp_set_element_len(buf, len);
+	}
+}
+
+
+static void anqp_add_network_auth_type(struct hostapd_data *hapd,
+				       struct wpabuf *buf)
+{
+	if (anqp_add_override(hapd, buf, ANQP_NETWORK_AUTH_TYPE))
+		return;
+
+	if (hapd->conf->network_auth_type) {
+		wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
+		wpabuf_put_le16(buf, hapd->conf->network_auth_type_len);
+		wpabuf_put_data(buf, hapd->conf->network_auth_type,
+				hapd->conf->network_auth_type_len);
+	}
+}
+
+
+static void anqp_add_roaming_consortium(struct hostapd_data *hapd,
+					struct wpabuf *buf)
+{
+	unsigned int i;
+	u8 *len;
+
+	if (anqp_add_override(hapd, buf, ANQP_ROAMING_CONSORTIUM))
+		return;
+
+	len = gas_anqp_add_element(buf, ANQP_ROAMING_CONSORTIUM);
+	for (i = 0; i < hapd->conf->roaming_consortium_count; i++) {
+		struct hostapd_roaming_consortium *rc;
+		rc = &hapd->conf->roaming_consortium[i];
+		wpabuf_put_u8(buf, rc->len);
+		wpabuf_put_data(buf, rc->oi, rc->len);
+	}
+	gas_anqp_set_element_len(buf, len);
+}
+
+
+static void anqp_add_ip_addr_type_availability(struct hostapd_data *hapd,
+					       struct wpabuf *buf)
+{
+	if (anqp_add_override(hapd, buf, ANQP_IP_ADDR_TYPE_AVAILABILITY))
+		return;
+
+	if (hapd->conf->ipaddr_type_configured) {
+		wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
+		wpabuf_put_le16(buf, 1);
+		wpabuf_put_u8(buf, hapd->conf->ipaddr_type_availability);
+	}
+}
+
+
+static void anqp_add_nai_realm_eap(struct wpabuf *buf,
+				   struct hostapd_nai_realm_data *realm)
+{
+	unsigned int i, j;
+
+	wpabuf_put_u8(buf, realm->eap_method_count);
+
+	for (i = 0; i < realm->eap_method_count; i++) {
+		struct hostapd_nai_realm_eap *eap = &realm->eap_method[i];
+		wpabuf_put_u8(buf, 2 + (3 * eap->num_auths));
+		wpabuf_put_u8(buf, eap->eap_method);
+		wpabuf_put_u8(buf, eap->num_auths);
+		for (j = 0; j < eap->num_auths; j++) {
+			wpabuf_put_u8(buf, eap->auth_id[j]);
+			wpabuf_put_u8(buf, 1);
+			wpabuf_put_u8(buf, eap->auth_val[j]);
+		}
+	}
+}
+
+
+static void anqp_add_nai_realm_data(struct wpabuf *buf,
+				    struct hostapd_nai_realm_data *realm,
+				    unsigned int realm_idx)
+{
+	u8 *realm_data_len;
+
+	wpa_printf(MSG_DEBUG, "realm=%s, len=%d", realm->realm[realm_idx],
+		   (int) os_strlen(realm->realm[realm_idx]));
+	realm_data_len = wpabuf_put(buf, 2);
+	wpabuf_put_u8(buf, realm->encoding);
+	wpabuf_put_u8(buf, os_strlen(realm->realm[realm_idx]));
+	wpabuf_put_str(buf, realm->realm[realm_idx]);
+	anqp_add_nai_realm_eap(buf, realm);
+	gas_anqp_set_element_len(buf, realm_data_len);
+}
+
+
+static int hs20_add_nai_home_realm_matches(struct hostapd_data *hapd,
+					   struct wpabuf *buf,
+					   const u8 *home_realm,
+					   size_t home_realm_len)
+{
+	unsigned int i, j, k;
+	u8 num_realms, num_matching = 0, encoding, realm_len, *realm_list_len;
+	struct hostapd_nai_realm_data *realm;
+	const u8 *pos, *realm_name, *end;
+	struct {
+		unsigned int realm_data_idx;
+		unsigned int realm_idx;
+	} matches[10];
+
+	pos = home_realm;
+	end = pos + home_realm_len;
+	if (end - pos < 1) {
+		wpa_hexdump(MSG_DEBUG, "Too short NAI Home Realm Query",
+			    home_realm, home_realm_len);
+		return -1;
+	}
+	num_realms = *pos++;
+
+	for (i = 0; i < num_realms && num_matching < 10; i++) {
+		if (end - pos < 2) {
+			wpa_hexdump(MSG_DEBUG,
+				    "Truncated NAI Home Realm Query",
+				    home_realm, home_realm_len);
+			return -1;
+		}
+		encoding = *pos++;
+		realm_len = *pos++;
+		if (realm_len > end - pos) {
+			wpa_hexdump(MSG_DEBUG,
+				    "Truncated NAI Home Realm Query",
+				    home_realm, home_realm_len);
+			return -1;
+		}
+		realm_name = pos;
+		for (j = 0; j < hapd->conf->nai_realm_count &&
+			     num_matching < 10; j++) {
+			const u8 *rpos, *rend;
+			realm = &hapd->conf->nai_realm_data[j];
+			if (encoding != realm->encoding)
+				continue;
+
+			rpos = realm_name;
+			while (rpos < realm_name + realm_len &&
+			       num_matching < 10) {
+				for (rend = rpos;
+				     rend < realm_name + realm_len; rend++) {
+					if (*rend == ';')
+						break;
+				}
+				for (k = 0; k < MAX_NAI_REALMS &&
+					     realm->realm[k] &&
+					     num_matching < 10; k++) {
+					if ((int) os_strlen(realm->realm[k]) !=
+					    rend - rpos ||
+					    os_strncmp((char *) rpos,
+						       realm->realm[k],
+						       rend - rpos) != 0)
+						continue;
+					matches[num_matching].realm_data_idx =
+						j;
+					matches[num_matching].realm_idx = k;
+					num_matching++;
+				}
+				rpos = rend + 1;
+			}
+		}
+		pos += realm_len;
+	}
+
+	realm_list_len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
+	wpabuf_put_le16(buf, num_matching);
+
+	/*
+	 * There are two ways to format. 1. each realm in a NAI Realm Data unit
+	 * 2. all realms that share the same EAP methods in a NAI Realm Data
+	 * unit. The first format is likely to be bigger in size than the
+	 * second, but may be easier to parse and process by the receiver.
+	 */
+	for (i = 0; i < num_matching; i++) {
+		wpa_printf(MSG_DEBUG, "realm_idx %d, realm_data_idx %d",
+			   matches[i].realm_data_idx, matches[i].realm_idx);
+		realm = &hapd->conf->nai_realm_data[matches[i].realm_data_idx];
+		anqp_add_nai_realm_data(buf, realm, matches[i].realm_idx);
+	}
+	gas_anqp_set_element_len(buf, realm_list_len);
+	return 0;
+}
+
+
+static void anqp_add_nai_realm(struct hostapd_data *hapd, struct wpabuf *buf,
+			       const u8 *home_realm, size_t home_realm_len,
+			       int nai_realm, int nai_home_realm)
+{
+	if (nai_realm && !nai_home_realm &&
+	    anqp_add_override(hapd, buf, ANQP_NAI_REALM))
+		return;
+
+	if (nai_realm && hapd->conf->nai_realm_data) {
+		u8 *len;
+		unsigned int i, j;
+		len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
+		wpabuf_put_le16(buf, hapd->conf->nai_realm_count);
+		for (i = 0; i < hapd->conf->nai_realm_count; i++) {
+			u8 *realm_data_len, *realm_len;
+			struct hostapd_nai_realm_data *realm;
+
+			realm = &hapd->conf->nai_realm_data[i];
+			realm_data_len = wpabuf_put(buf, 2);
+			wpabuf_put_u8(buf, realm->encoding);
+			realm_len = wpabuf_put(buf, 1);
+			for (j = 0; realm->realm[j]; j++) {
+				if (j > 0)
+					wpabuf_put_u8(buf, ';');
+				wpabuf_put_str(buf, realm->realm[j]);
+			}
+			*realm_len = (u8 *) wpabuf_put(buf, 0) - realm_len - 1;
+			anqp_add_nai_realm_eap(buf, realm);
+			gas_anqp_set_element_len(buf, realm_data_len);
+		}
+		gas_anqp_set_element_len(buf, len);
+	} else if (nai_home_realm && hapd->conf->nai_realm_data && home_realm) {
+		hs20_add_nai_home_realm_matches(hapd, buf, home_realm,
+						home_realm_len);
+	}
+}
+
+
+static void anqp_add_3gpp_cellular_network(struct hostapd_data *hapd,
+					   struct wpabuf *buf)
+{
+	if (anqp_add_override(hapd, buf, ANQP_3GPP_CELLULAR_NETWORK))
+		return;
+
+	if (hapd->conf->anqp_3gpp_cell_net) {
+		wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
+		wpabuf_put_le16(buf,
+				hapd->conf->anqp_3gpp_cell_net_len);
+		wpabuf_put_data(buf, hapd->conf->anqp_3gpp_cell_net,
+				hapd->conf->anqp_3gpp_cell_net_len);
+	}
+}
+
+
+static void anqp_add_domain_name(struct hostapd_data *hapd, struct wpabuf *buf)
+{
+	if (anqp_add_override(hapd, buf, ANQP_DOMAIN_NAME))
+		return;
+
+	if (hapd->conf->domain_name) {
+		wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
+		wpabuf_put_le16(buf, hapd->conf->domain_name_len);
+		wpabuf_put_data(buf, hapd->conf->domain_name,
+				hapd->conf->domain_name_len);
+	}
+}
+
+
+#ifdef CONFIG_HS20
+
+static void anqp_add_operator_friendly_name(struct hostapd_data *hapd,
+					    struct wpabuf *buf)
+{
+	if (hapd->conf->hs20_oper_friendly_name) {
+		u8 *len;
+		unsigned int i;
+		len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
+		wpabuf_put_be24(buf, OUI_WFA);
+		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
+		wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
+		wpabuf_put_u8(buf, 0); /* Reserved */
+		for (i = 0; i < hapd->conf->hs20_oper_friendly_name_count; i++)
+		{
+			struct hostapd_lang_string *vn;
+			vn = &hapd->conf->hs20_oper_friendly_name[i];
+			wpabuf_put_u8(buf, 3 + vn->name_len);
+			wpabuf_put_data(buf, vn->lang, 3);
+			wpabuf_put_data(buf, vn->name, vn->name_len);
+		}
+		gas_anqp_set_element_len(buf, len);
+	}
+}
+
+
+static void anqp_add_wan_metrics(struct hostapd_data *hapd,
+				 struct wpabuf *buf)
+{
+	if (hapd->conf->hs20_wan_metrics) {
+		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
+		wpabuf_put_be24(buf, OUI_WFA);
+		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
+		wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS);
+		wpabuf_put_u8(buf, 0); /* Reserved */
+		wpabuf_put_data(buf, hapd->conf->hs20_wan_metrics, 13);
+		gas_anqp_set_element_len(buf, len);
+	}
+}
+
+
+static void anqp_add_connection_capability(struct hostapd_data *hapd,
+					   struct wpabuf *buf)
+{
+	if (hapd->conf->hs20_connection_capability) {
+		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
+		wpabuf_put_be24(buf, OUI_WFA);
+		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
+		wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY);
+		wpabuf_put_u8(buf, 0); /* Reserved */
+		wpabuf_put_data(buf, hapd->conf->hs20_connection_capability,
+				hapd->conf->hs20_connection_capability_len);
+		gas_anqp_set_element_len(buf, len);
+	}
+}
+
+
+static void anqp_add_operating_class(struct hostapd_data *hapd,
+				     struct wpabuf *buf)
+{
+	if (hapd->conf->hs20_operating_class) {
+		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
+		wpabuf_put_be24(buf, OUI_WFA);
+		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
+		wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
+		wpabuf_put_u8(buf, 0); /* Reserved */
+		wpabuf_put_data(buf, hapd->conf->hs20_operating_class,
+				hapd->conf->hs20_operating_class_len);
+		gas_anqp_set_element_len(buf, len);
+	}
+}
+
+
+static void anqp_add_osu_provider(struct wpabuf *buf,
+				  struct hostapd_bss_config *bss,
+				  struct hs20_osu_provider *p)
+{
+	u8 *len, *len2, *count;
+	unsigned int i;
+
+	len = wpabuf_put(buf, 2); /* OSU Provider Length to be filled */
+
+	/* OSU Friendly Name Duples */
+	len2 = wpabuf_put(buf, 2);
+	for (i = 0; i < p->friendly_name_count; i++) {
+		struct hostapd_lang_string *s = &p->friendly_name[i];
+		wpabuf_put_u8(buf, 3 + s->name_len);
+		wpabuf_put_data(buf, s->lang, 3);
+		wpabuf_put_data(buf, s->name, s->name_len);
+	}
+	WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
+
+	/* OSU Server URI */
+	if (p->server_uri) {
+		wpabuf_put_u8(buf, os_strlen(p->server_uri));
+		wpabuf_put_str(buf, p->server_uri);
+	} else
+		wpabuf_put_u8(buf, 0);
+
+	/* OSU Method List */
+	count = wpabuf_put(buf, 1);
+	for (i = 0; p->method_list[i] >= 0; i++)
+		wpabuf_put_u8(buf, p->method_list[i]);
+	*count = i;
+
+	/* Icons Available */
+	len2 = wpabuf_put(buf, 2);
+	for (i = 0; i < p->icons_count; i++) {
+		size_t j;
+		struct hs20_icon *icon = NULL;
+
+		for (j = 0; j < bss->hs20_icons_count && !icon; j++) {
+			if (os_strcmp(p->icons[i], bss->hs20_icons[j].name) ==
+			    0)
+				icon = &bss->hs20_icons[j];
+		}
+		if (!icon)
+			continue; /* icon info not found */
+
+		wpabuf_put_le16(buf, icon->width);
+		wpabuf_put_le16(buf, icon->height);
+		wpabuf_put_data(buf, icon->language, 3);
+		wpabuf_put_u8(buf, os_strlen(icon->type));
+		wpabuf_put_str(buf, icon->type);
+		wpabuf_put_u8(buf, os_strlen(icon->name));
+		wpabuf_put_str(buf, icon->name);
+	}
+	WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
+
+	/* OSU_NAI */
+	if (p->osu_nai) {
+		wpabuf_put_u8(buf, os_strlen(p->osu_nai));
+		wpabuf_put_str(buf, p->osu_nai);
+	} else
+		wpabuf_put_u8(buf, 0);
+
+	/* OSU Service Description Duples */
+	len2 = wpabuf_put(buf, 2);
+	for (i = 0; i < p->service_desc_count; i++) {
+		struct hostapd_lang_string *s = &p->service_desc[i];
+		wpabuf_put_u8(buf, 3 + s->name_len);
+		wpabuf_put_data(buf, s->lang, 3);
+		wpabuf_put_data(buf, s->name, s->name_len);
+	}
+	WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);
+
+	WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
+}
+
+
+static void anqp_add_osu_providers_list(struct hostapd_data *hapd,
+					struct wpabuf *buf)
+{
+	if (hapd->conf->hs20_osu_providers_count) {
+		size_t i;
+		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
+		wpabuf_put_be24(buf, OUI_WFA);
+		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
+		wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
+		wpabuf_put_u8(buf, 0); /* Reserved */
+
+		/* OSU SSID */
+		wpabuf_put_u8(buf, hapd->conf->osu_ssid_len);
+		wpabuf_put_data(buf, hapd->conf->osu_ssid,
+				hapd->conf->osu_ssid_len);
+
+		/* Number of OSU Providers */
+		wpabuf_put_u8(buf, hapd->conf->hs20_osu_providers_count);
+
+		for (i = 0; i < hapd->conf->hs20_osu_providers_count; i++) {
+			anqp_add_osu_provider(
+				buf, hapd->conf,
+				&hapd->conf->hs20_osu_providers[i]);
+		}
+
+		gas_anqp_set_element_len(buf, len);
+	}
+}
+
+
+static void anqp_add_icon_binary_file(struct hostapd_data *hapd,
+				      struct wpabuf *buf,
+				      const u8 *name, size_t name_len)
+{
+	struct hs20_icon *icon;
+	size_t i;
+	u8 *len;
+
+	wpa_hexdump_ascii(MSG_DEBUG, "HS 2.0: Requested Icon Filename",
+			  name, name_len);
+	for (i = 0; i < hapd->conf->hs20_icons_count; i++) {
+		icon = &hapd->conf->hs20_icons[i];
+		if (name_len == os_strlen(icon->name) &&
+		    os_memcmp(name, icon->name, name_len) == 0)
+			break;
+	}
+
+	if (i < hapd->conf->hs20_icons_count)
+		icon = &hapd->conf->hs20_icons[i];
+	else
+		icon = NULL;
+
+	len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
+	wpabuf_put_be24(buf, OUI_WFA);
+	wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
+	wpabuf_put_u8(buf, HS20_STYPE_ICON_BINARY_FILE);
+	wpabuf_put_u8(buf, 0); /* Reserved */
+
+	if (icon) {
+		char *data;
+		size_t data_len;
+
+		data = os_readfile(icon->file, &data_len);
+		if (data == NULL || data_len > 65535) {
+			wpabuf_put_u8(buf, 2); /* Download Status:
+						* Unspecified file error */
+			wpabuf_put_u8(buf, 0);
+			wpabuf_put_le16(buf, 0);
+		} else {
+			wpabuf_put_u8(buf, 0); /* Download Status: Success */
+			wpabuf_put_u8(buf, os_strlen(icon->type));
+			wpabuf_put_str(buf, icon->type);
+			wpabuf_put_le16(buf, data_len);
+			wpabuf_put_data(buf, data, data_len);
+		}
+		os_free(data);
+	} else {
+		wpabuf_put_u8(buf, 1); /* Download Status: File not found */
+		wpabuf_put_u8(buf, 0);
+		wpabuf_put_le16(buf, 0);
+	}
+
+	gas_anqp_set_element_len(buf, len);
+}
+
+#endif /* CONFIG_HS20 */
+
+
+static size_t anqp_get_required_len(struct hostapd_data *hapd,
+				    const u16 *infoid,
+				    unsigned int num_infoid)
+{
+	size_t len = 0;
+	unsigned int i;
+
+	for (i = 0; i < num_infoid; i++) {
+		struct anqp_element *elem = get_anqp_elem(hapd, infoid[i]);
+
+		if (elem)
+			len += 2 + 2 + wpabuf_len(elem->payload);
+	}
+
+	return len;
+}
+
+
+static struct wpabuf *
+gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
+				unsigned int request,
+				const u8 *home_realm, size_t home_realm_len,
+				const u8 *icon_name, size_t icon_name_len,
+				const u16 *extra_req,
+				unsigned int num_extra_req)
+{
+	struct wpabuf *buf;
+	size_t len;
+	unsigned int i;
+
+	len = 1400;
+	if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM))
+		len += 1000;
+	if (request & ANQP_REQ_ICON_REQUEST)
+		len += 65536;
+	len += anqp_get_required_len(hapd, extra_req, num_extra_req);
+
+	buf = wpabuf_alloc(len);
+	if (buf == NULL)
+		return NULL;
+
+	if (request & ANQP_REQ_CAPABILITY_LIST)
+		anqp_add_capab_list(hapd, buf);
+	if (request & ANQP_REQ_VENUE_NAME)
+		anqp_add_venue_name(hapd, buf);
+	if (request & ANQP_REQ_EMERGENCY_CALL_NUMBER)
+		anqp_add_elem(hapd, buf, ANQP_EMERGENCY_CALL_NUMBER);
+	if (request & ANQP_REQ_NETWORK_AUTH_TYPE)
+		anqp_add_network_auth_type(hapd, buf);
+	if (request & ANQP_REQ_ROAMING_CONSORTIUM)
+		anqp_add_roaming_consortium(hapd, buf);
+	if (request & ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY)
+		anqp_add_ip_addr_type_availability(hapd, buf);
+	if (request & (ANQP_REQ_NAI_REALM | ANQP_REQ_NAI_HOME_REALM))
+		anqp_add_nai_realm(hapd, buf, home_realm, home_realm_len,
+				   request & ANQP_REQ_NAI_REALM,
+				   request & ANQP_REQ_NAI_HOME_REALM);
+	if (request & ANQP_REQ_3GPP_CELLULAR_NETWORK)
+		anqp_add_3gpp_cellular_network(hapd, buf);
+	if (request & ANQP_REQ_AP_GEOSPATIAL_LOCATION)
+		anqp_add_elem(hapd, buf, ANQP_AP_GEOSPATIAL_LOCATION);
+	if (request & ANQP_REQ_AP_CIVIC_LOCATION)
+		anqp_add_elem(hapd, buf, ANQP_AP_CIVIC_LOCATION);
+	if (request & ANQP_REQ_AP_LOCATION_PUBLIC_URI)
+		anqp_add_elem(hapd, buf, ANQP_AP_LOCATION_PUBLIC_URI);
+	if (request & ANQP_REQ_DOMAIN_NAME)
+		anqp_add_domain_name(hapd, buf);
+	if (request & ANQP_REQ_EMERGENCY_ALERT_URI)
+		anqp_add_elem(hapd, buf, ANQP_EMERGENCY_ALERT_URI);
+	if (request & ANQP_REQ_TDLS_CAPABILITY)
+		anqp_add_elem(hapd, buf, ANQP_TDLS_CAPABILITY);
+	if (request & ANQP_REQ_EMERGENCY_NAI)
+		anqp_add_elem(hapd, buf, ANQP_EMERGENCY_NAI);
+
+	for (i = 0; i < num_extra_req; i++)
+		anqp_add_elem(hapd, buf, extra_req[i]);
+
+#ifdef CONFIG_HS20
+	if (request & ANQP_REQ_HS_CAPABILITY_LIST)
+		anqp_add_hs_capab_list(hapd, buf);
+	if (request & ANQP_REQ_OPERATOR_FRIENDLY_NAME)
+		anqp_add_operator_friendly_name(hapd, buf);
+	if (request & ANQP_REQ_WAN_METRICS)
+		anqp_add_wan_metrics(hapd, buf);
+	if (request & ANQP_REQ_CONNECTION_CAPABILITY)
+		anqp_add_connection_capability(hapd, buf);
+	if (request & ANQP_REQ_OPERATING_CLASS)
+		anqp_add_operating_class(hapd, buf);
+	if (request & ANQP_REQ_OSU_PROVIDERS_LIST)
+		anqp_add_osu_providers_list(hapd, buf);
+	if (request & ANQP_REQ_ICON_REQUEST)
+		anqp_add_icon_binary_file(hapd, buf, icon_name, icon_name_len);
+#endif /* CONFIG_HS20 */
+
+	return buf;
+}
+
+
+#define ANQP_MAX_EXTRA_REQ 20
+
+struct anqp_query_info {
+	unsigned int request;
+	const u8 *home_realm_query;
+	size_t home_realm_query_len;
+	const u8 *icon_name;
+	size_t icon_name_len;
+	int p2p_sd;
+	u16 extra_req[ANQP_MAX_EXTRA_REQ];
+	unsigned int num_extra_req;
+};
+
+
+static void set_anqp_req(unsigned int bit, const char *name, int local,
+			 struct anqp_query_info *qi)
+{
+	qi->request |= bit;
+	if (local) {
+		wpa_printf(MSG_DEBUG, "ANQP: %s (local)", name);
+	} else {
+		wpa_printf(MSG_DEBUG, "ANQP: %s not available", name);
+	}
+}
+
+
+static void rx_anqp_query_list_id(struct hostapd_data *hapd, u16 info_id,
+				  struct anqp_query_info *qi)
+{
+	switch (info_id) {
+	case ANQP_CAPABILITY_LIST:
+		set_anqp_req(ANQP_REQ_CAPABILITY_LIST, "Capability List", 1,
+			     qi);
+		break;
+	case ANQP_VENUE_NAME:
+		set_anqp_req(ANQP_REQ_VENUE_NAME, "Venue Name",
+			     hapd->conf->venue_name != NULL, qi);
+		break;
+	case ANQP_EMERGENCY_CALL_NUMBER:
+		set_anqp_req(ANQP_REQ_EMERGENCY_CALL_NUMBER,
+			     "Emergency Call Number",
+			     get_anqp_elem(hapd, info_id) != NULL, qi);
+		break;
+	case ANQP_NETWORK_AUTH_TYPE:
+		set_anqp_req(ANQP_REQ_NETWORK_AUTH_TYPE, "Network Auth Type",
+			     hapd->conf->network_auth_type != NULL, qi);
+		break;
+	case ANQP_ROAMING_CONSORTIUM:
+		set_anqp_req(ANQP_REQ_ROAMING_CONSORTIUM, "Roaming Consortium",
+			     hapd->conf->roaming_consortium != NULL, qi);
+		break;
+	case ANQP_IP_ADDR_TYPE_AVAILABILITY:
+		set_anqp_req(ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY,
+			     "IP Addr Type Availability",
+			     hapd->conf->ipaddr_type_configured, qi);
+		break;
+	case ANQP_NAI_REALM:
+		set_anqp_req(ANQP_REQ_NAI_REALM, "NAI Realm",
+			     hapd->conf->nai_realm_data != NULL, qi);
+		break;
+	case ANQP_3GPP_CELLULAR_NETWORK:
+		set_anqp_req(ANQP_REQ_3GPP_CELLULAR_NETWORK,
+			     "3GPP Cellular Network",
+			     hapd->conf->anqp_3gpp_cell_net != NULL, qi);
+		break;
+	case ANQP_AP_GEOSPATIAL_LOCATION:
+		set_anqp_req(ANQP_REQ_AP_GEOSPATIAL_LOCATION,
+			     "AP Geospatial Location",
+			     get_anqp_elem(hapd, info_id) != NULL, qi);
+		break;
+	case ANQP_AP_CIVIC_LOCATION:
+		set_anqp_req(ANQP_REQ_AP_CIVIC_LOCATION,
+			     "AP Civic Location",
+			     get_anqp_elem(hapd, info_id) != NULL, qi);
+		break;
+	case ANQP_AP_LOCATION_PUBLIC_URI:
+		set_anqp_req(ANQP_REQ_AP_LOCATION_PUBLIC_URI,
+			     "AP Location Public URI",
+			     get_anqp_elem(hapd, info_id) != NULL, qi);
+		break;
+	case ANQP_DOMAIN_NAME:
+		set_anqp_req(ANQP_REQ_DOMAIN_NAME, "Domain Name",
+			     hapd->conf->domain_name != NULL, qi);
+		break;
+	case ANQP_EMERGENCY_ALERT_URI:
+		set_anqp_req(ANQP_REQ_EMERGENCY_ALERT_URI,
+			     "Emergency Alert URI",
+			     get_anqp_elem(hapd, info_id) != NULL, qi);
+		break;
+	case ANQP_TDLS_CAPABILITY:
+		set_anqp_req(ANQP_REQ_TDLS_CAPABILITY,
+			     "TDLS Capability",
+			     get_anqp_elem(hapd, info_id) != NULL, qi);
+		break;
+	case ANQP_EMERGENCY_NAI:
+		set_anqp_req(ANQP_REQ_EMERGENCY_NAI,
+			     "Emergency NAI",
+			     get_anqp_elem(hapd, info_id) != NULL, qi);
+		break;
+	default:
+		if (!get_anqp_elem(hapd, info_id)) {
+			wpa_printf(MSG_DEBUG, "ANQP: Unsupported Info Id %u",
+				   info_id);
+			break;
+		}
+		if (qi->num_extra_req == ANQP_MAX_EXTRA_REQ) {
+			wpa_printf(MSG_DEBUG,
+				   "ANQP: No more room for extra requests - ignore Info Id %u",
+				   info_id);
+			break;
+		}
+		wpa_printf(MSG_DEBUG, "ANQP: Info Id %u (local)", info_id);
+		qi->extra_req[qi->num_extra_req] = info_id;
+		qi->num_extra_req++;
+		break;
+	}
+}
+
+
+static void rx_anqp_query_list(struct hostapd_data *hapd,
+			       const u8 *pos, const u8 *end,
+			       struct anqp_query_info *qi)
+{
+	wpa_printf(MSG_DEBUG, "ANQP: %u Info IDs requested in Query list",
+		   (unsigned int) (end - pos) / 2);
+
+	while (end - pos >= 2) {
+		rx_anqp_query_list_id(hapd, WPA_GET_LE16(pos), qi);
+		pos += 2;
+	}
+}
+
+
+#ifdef CONFIG_HS20
+
+static void rx_anqp_hs_query_list(struct hostapd_data *hapd, u8 subtype,
+				  struct anqp_query_info *qi)
+{
+	switch (subtype) {
+	case HS20_STYPE_CAPABILITY_LIST:
+		set_anqp_req(ANQP_REQ_HS_CAPABILITY_LIST, "HS Capability List",
+			     1, qi);
+		break;
+	case HS20_STYPE_OPERATOR_FRIENDLY_NAME:
+		set_anqp_req(ANQP_REQ_OPERATOR_FRIENDLY_NAME,
+			     "Operator Friendly Name",
+			     hapd->conf->hs20_oper_friendly_name != NULL, qi);
+		break;
+	case HS20_STYPE_WAN_METRICS:
+		set_anqp_req(ANQP_REQ_WAN_METRICS, "WAN Metrics",
+			     hapd->conf->hs20_wan_metrics != NULL, qi);
+		break;
+	case HS20_STYPE_CONNECTION_CAPABILITY:
+		set_anqp_req(ANQP_REQ_CONNECTION_CAPABILITY,
+			     "Connection Capability",
+			     hapd->conf->hs20_connection_capability != NULL,
+			     qi);
+		break;
+	case HS20_STYPE_OPERATING_CLASS:
+		set_anqp_req(ANQP_REQ_OPERATING_CLASS, "Operating Class",
+			     hapd->conf->hs20_operating_class != NULL, qi);
+		break;
+	case HS20_STYPE_OSU_PROVIDERS_LIST:
+		set_anqp_req(ANQP_REQ_OSU_PROVIDERS_LIST, "OSU Providers list",
+			     hapd->conf->hs20_osu_providers_count, qi);
+		break;
+	default:
+		wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 subtype %u",
+			   subtype);
+		break;
+	}
+}
+
+
+static void rx_anqp_hs_nai_home_realm(struct hostapd_data *hapd,
+				      const u8 *pos, const u8 *end,
+				      struct anqp_query_info *qi)
+{
+	qi->request |= ANQP_REQ_NAI_HOME_REALM;
+	qi->home_realm_query = pos;
+	qi->home_realm_query_len = end - pos;
+	if (hapd->conf->nai_realm_data != NULL) {
+		wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 NAI Home Realm Query "
+			   "(local)");
+	} else {
+		wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 NAI Home Realm Query not "
+			   "available");
+	}
+}
+
+
+static void rx_anqp_hs_icon_request(struct hostapd_data *hapd,
+				    const u8 *pos, const u8 *end,
+				    struct anqp_query_info *qi)
+{
+	qi->request |= ANQP_REQ_ICON_REQUEST;
+	qi->icon_name = pos;
+	qi->icon_name_len = end - pos;
+	if (hapd->conf->hs20_icons_count) {
+		wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Icon Request Query "
+			   "(local)");
+	} else {
+		wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Icon Request Query not "
+			   "available");
+	}
+}
+
+
+static void rx_anqp_vendor_specific(struct hostapd_data *hapd,
+				    const u8 *pos, const u8 *end,
+				    struct anqp_query_info *qi)
+{
+	u32 oui;
+	u8 subtype;
+
+	if (end - pos < 4) {
+		wpa_printf(MSG_DEBUG, "ANQP: Too short vendor specific ANQP "
+			   "Query element");
+		return;
+	}
+
+	oui = WPA_GET_BE24(pos);
+	pos += 3;
+	if (oui != OUI_WFA) {
+		wpa_printf(MSG_DEBUG, "ANQP: Unsupported vendor OUI %06x",
+			   oui);
+		return;
+	}
+
+#ifdef CONFIG_P2P
+	if (*pos == P2P_OUI_TYPE) {
+		/*
+		 * This is for P2P SD and will be taken care of by the P2P
+		 * implementation. This query needs to be ignored in the generic
+		 * GAS server to avoid duplicated response.
+		 */
+		wpa_printf(MSG_DEBUG,
+			   "ANQP: Ignore WFA vendor type %u (P2P SD) in generic GAS server",
+			   *pos);
+		qi->p2p_sd = 1;
+		return;
+	}
+#endif /* CONFIG_P2P */
+
+	if (*pos != HS20_ANQP_OUI_TYPE) {
+		wpa_printf(MSG_DEBUG, "ANQP: Unsupported WFA vendor type %u",
+			   *pos);
+		return;
+	}
+	pos++;
+
+	if (end - pos <= 1)
+		return;
+
+	subtype = *pos++;
+	pos++; /* Reserved */
+	switch (subtype) {
+	case HS20_STYPE_QUERY_LIST:
+		wpa_printf(MSG_DEBUG, "ANQP: HS 2.0 Query List");
+		while (pos < end) {
+			rx_anqp_hs_query_list(hapd, *pos, qi);
+			pos++;
+		}
+		break;
+	case HS20_STYPE_NAI_HOME_REALM_QUERY:
+		rx_anqp_hs_nai_home_realm(hapd, pos, end, qi);
+		break;
+	case HS20_STYPE_ICON_REQUEST:
+		rx_anqp_hs_icon_request(hapd, pos, end, qi);
+		break;
+	default:
+		wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 query subtype "
+			   "%u", subtype);
+		break;
+	}
+}
+
+#endif /* CONFIG_HS20 */
+
+
+static void gas_serv_req_local_processing(struct hostapd_data *hapd,
+					  const u8 *sa, u8 dialog_token,
+					  struct anqp_query_info *qi, int prot,
+					  int std_addr3)
+{
+	struct wpabuf *buf, *tx_buf;
+
+	buf = gas_serv_build_gas_resp_payload(hapd, qi->request,
+					      qi->home_realm_query,
+					      qi->home_realm_query_len,
+					      qi->icon_name, qi->icon_name_len,
+					      qi->extra_req, qi->num_extra_req);
+	wpa_hexdump_buf(MSG_MSGDUMP, "ANQP: Locally generated ANQP responses",
+			buf);
+	if (!buf)
+		return;
+#ifdef CONFIG_P2P
+	if (wpabuf_len(buf) == 0 && qi->p2p_sd) {
+		wpa_printf(MSG_DEBUG,
+			   "ANQP: Do not send response to P2P SD from generic GAS service (P2P SD implementation will process this)");
+		wpabuf_free(buf);
+		return;
+	}
+#endif /* CONFIG_P2P */
+
+	if (wpabuf_len(buf) > hapd->gas_frag_limit ||
+	    hapd->conf->gas_comeback_delay) {
+		struct gas_dialog_info *di;
+		u16 comeback_delay = 1;
+
+		if (hapd->conf->gas_comeback_delay) {
+			/* Testing - allow overriding of the delay value */
+			comeback_delay = hapd->conf->gas_comeback_delay;
+		}
+
+		wpa_printf(MSG_DEBUG, "ANQP: Too long response to fit in "
+			   "initial response - use GAS comeback");
+		di = gas_dialog_create(hapd, sa, dialog_token);
+		if (!di) {
+			wpa_printf(MSG_INFO, "ANQP: Could not create dialog "
+				   "for " MACSTR " (dialog token %u)",
+				   MAC2STR(sa), dialog_token);
+			wpabuf_free(buf);
+			tx_buf = gas_anqp_build_initial_resp_buf(
+				dialog_token, WLAN_STATUS_UNSPECIFIED_FAILURE,
+				0, NULL);
+		} else {
+			di->prot = prot;
+			di->sd_resp = buf;
+			di->sd_resp_pos = 0;
+			tx_buf = gas_anqp_build_initial_resp_buf(
+				dialog_token, WLAN_STATUS_SUCCESS,
+				comeback_delay, NULL);
+		}
+	} else {
+		wpa_printf(MSG_DEBUG, "ANQP: Initial response (no comeback)");
+		tx_buf = gas_anqp_build_initial_resp_buf(
+			dialog_token, WLAN_STATUS_SUCCESS, 0, buf);
+		wpabuf_free(buf);
+	}
+	if (!tx_buf)
+		return;
+	if (prot)
+		convert_to_protected_dual(tx_buf);
+	if (std_addr3)
+		hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
+					wpabuf_head(tx_buf),
+					wpabuf_len(tx_buf));
+	else
+		hostapd_drv_send_action_addr3_ap(hapd, hapd->iface->freq, 0, sa,
+						 wpabuf_head(tx_buf),
+						 wpabuf_len(tx_buf));
+	wpabuf_free(tx_buf);
+}
+
+
+static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd,
+					const u8 *sa,
+					const u8 *data, size_t len, int prot,
+					int std_addr3)
+{
+	const u8 *pos = data;
+	const u8 *end = data + len;
+	const u8 *next;
+	u8 dialog_token;
+	u16 slen;
+	struct anqp_query_info qi;
+	const u8 *adv_proto;
+
+	if (len < 1 + 2)
+		return;
+
+	os_memset(&qi, 0, sizeof(qi));
+
+	dialog_token = *pos++;
+	wpa_msg(hapd->msg_ctx, MSG_DEBUG,
+		"GAS: GAS Initial Request from " MACSTR " (dialog token %u) ",
+		MAC2STR(sa), dialog_token);
+
+	if (*pos != WLAN_EID_ADV_PROTO) {
+		wpa_msg(hapd->msg_ctx, MSG_DEBUG,
+			"GAS: Unexpected IE in GAS Initial Request: %u", *pos);
+		return;
+	}
+	adv_proto = pos++;
+
+	slen = *pos++;
+	if (slen > end - pos || slen < 2) {
+		wpa_msg(hapd->msg_ctx, MSG_DEBUG,
+			"GAS: Invalid IE in GAS Initial Request");
+		return;
+	}
+	next = pos + slen;
+	pos++; /* skip QueryRespLenLimit and PAME-BI */
+
+	if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
+		struct wpabuf *buf;
+		wpa_msg(hapd->msg_ctx, MSG_DEBUG,
+			"GAS: Unsupported GAS advertisement protocol id %u",
+			*pos);
+		if (sa[0] & 0x01)
+			return; /* Invalid source address - drop silently */
+		buf = gas_build_initial_resp(
+			dialog_token, WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED,
+			0, 2 + slen + 2);
+		if (buf == NULL)
+			return;
+		wpabuf_put_data(buf, adv_proto, 2 + slen);
+		wpabuf_put_le16(buf, 0); /* Query Response Length */
+		if (prot)
+			convert_to_protected_dual(buf);
+		if (std_addr3)
+			hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
+						wpabuf_head(buf),
+						wpabuf_len(buf));
+		else
+			hostapd_drv_send_action_addr3_ap(hapd,
+							 hapd->iface->freq, 0,
+							 sa, wpabuf_head(buf),
+							 wpabuf_len(buf));
+		wpabuf_free(buf);
+		return;
+	}
+
+	pos = next;
+	/* Query Request */
+	if (end - pos < 2)
+		return;
+	slen = WPA_GET_LE16(pos);
+	pos += 2;
+	if (slen > end - pos)
+		return;
+	end = pos + slen;
+
+	/* ANQP Query Request */
+	while (pos < end) {
+		u16 info_id, elen;
+
+		if (end - pos < 4)
+			return;
+
+		info_id = WPA_GET_LE16(pos);
+		pos += 2;
+		elen = WPA_GET_LE16(pos);
+		pos += 2;
+
+		if (elen > end - pos) {
+			wpa_printf(MSG_DEBUG, "ANQP: Invalid Query Request");
+			return;
+		}
+
+		switch (info_id) {
+		case ANQP_QUERY_LIST:
+			rx_anqp_query_list(hapd, pos, pos + elen, &qi);
+			break;
+#ifdef CONFIG_HS20
+		case ANQP_VENDOR_SPECIFIC:
+			rx_anqp_vendor_specific(hapd, pos, pos + elen, &qi);
+			break;
+#endif /* CONFIG_HS20 */
+		default:
+			wpa_printf(MSG_DEBUG, "ANQP: Unsupported Query "
+				   "Request element %u", info_id);
+			break;
+		}
+
+		pos += elen;
+	}
+
+	gas_serv_req_local_processing(hapd, sa, dialog_token, &qi, prot,
+				      std_addr3);
+}
+
+
+static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd,
+					 const u8 *sa,
+					 const u8 *data, size_t len, int prot,
+					 int std_addr3)
+{
+	struct gas_dialog_info *dialog;
+	struct wpabuf *buf, *tx_buf;
+	u8 dialog_token;
+	size_t frag_len;
+	int more = 0;
+
+	wpa_hexdump(MSG_DEBUG, "GAS: RX GAS Comeback Request", data, len);
+	if (len < 1)
+		return;
+	dialog_token = *data;
+	wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Dialog Token: %u",
+		dialog_token);
+
+	dialog = gas_serv_dialog_find(hapd, sa, dialog_token);
+	if (!dialog) {
+		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: No pending SD "
+			"response fragment for " MACSTR " dialog token %u",
+			MAC2STR(sa), dialog_token);
+
+		if (sa[0] & 0x01)
+			return; /* Invalid source address - drop silently */
+		tx_buf = gas_anqp_build_comeback_resp_buf(
+			dialog_token, WLAN_STATUS_NO_OUTSTANDING_GAS_REQ, 0, 0,
+			0, NULL);
+		if (tx_buf == NULL)
+			return;
+		goto send_resp;
+	}
+
+	frag_len = wpabuf_len(dialog->sd_resp) - dialog->sd_resp_pos;
+	if (frag_len > hapd->gas_frag_limit) {
+		frag_len = hapd->gas_frag_limit;
+		more = 1;
+	}
+	wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: resp frag_len %u",
+		(unsigned int) frag_len);
+	buf = wpabuf_alloc_copy(wpabuf_head_u8(dialog->sd_resp) +
+				dialog->sd_resp_pos, frag_len);
+	if (buf == NULL) {
+		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Failed to allocate "
+			"buffer");
+		gas_serv_dialog_clear(dialog);
+		return;
+	}
+	tx_buf = gas_anqp_build_comeback_resp_buf(dialog_token,
+						  WLAN_STATUS_SUCCESS,
+						  dialog->sd_frag_id,
+						  more, 0, buf);
+	wpabuf_free(buf);
+	if (tx_buf == NULL) {
+		gas_serv_dialog_clear(dialog);
+		return;
+	}
+	wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: Tx GAS Comeback Response "
+		"(frag_id %d more=%d frag_len=%d)",
+		dialog->sd_frag_id, more, (int) frag_len);
+	dialog->sd_frag_id++;
+	dialog->sd_resp_pos += frag_len;
+
+	if (more) {
+		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: %d more bytes remain "
+			"to be sent",
+			(int) (wpabuf_len(dialog->sd_resp) -
+			       dialog->sd_resp_pos));
+	} else {
+		wpa_msg(hapd->msg_ctx, MSG_DEBUG, "GAS: All fragments of "
+			"SD response sent");
+		gas_serv_dialog_clear(dialog);
+		gas_serv_free_dialogs(hapd, sa);
+	}
+
+send_resp:
+	if (prot)
+		convert_to_protected_dual(tx_buf);
+	if (std_addr3)
+		hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa,
+					wpabuf_head(tx_buf),
+					wpabuf_len(tx_buf));
+	else
+		hostapd_drv_send_action_addr3_ap(hapd, hapd->iface->freq, 0, sa,
+						 wpabuf_head(tx_buf),
+						 wpabuf_len(tx_buf));
+	wpabuf_free(tx_buf);
+}
+
+
+static void gas_serv_rx_public_action(void *ctx, const u8 *buf, size_t len,
+				      int freq)
+{
+	struct hostapd_data *hapd = ctx;
+	const struct ieee80211_mgmt *mgmt;
+	const u8 *sa, *data;
+	int prot, std_addr3;
+
+	mgmt = (const struct ieee80211_mgmt *) buf;
+	if (len < IEEE80211_HDRLEN + 2)
+		return;
+	if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
+	    mgmt->u.action.category != WLAN_ACTION_PROTECTED_DUAL)
+		return;
+	/*
+	 * Note: Public Action and Protected Dual of Public Action frames share
+	 * the same payload structure, so it is fine to use definitions of
+	 * Public Action frames to process both.
+	 */
+	prot = mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL;
+	sa = mgmt->sa;
+	if (hapd->conf->gas_address3 == 1)
+		std_addr3 = 1;
+	else if (hapd->conf->gas_address3 == 2)
+		std_addr3 = 0;
+	else
+		std_addr3 = is_broadcast_ether_addr(mgmt->bssid);
+	len -= IEEE80211_HDRLEN + 1;
+	data = buf + IEEE80211_HDRLEN + 1;
+	switch (data[0]) {
+	case WLAN_PA_GAS_INITIAL_REQ:
+		gas_serv_rx_gas_initial_req(hapd, sa, data + 1, len - 1, prot,
+					    std_addr3);
+		break;
+	case WLAN_PA_GAS_COMEBACK_REQ:
+		gas_serv_rx_gas_comeback_req(hapd, sa, data + 1, len - 1, prot,
+					     std_addr3);
+		break;
+	}
+}
+
+
+int gas_serv_init(struct hostapd_data *hapd)
+{
+	hapd->public_action_cb2 = gas_serv_rx_public_action;
+	hapd->public_action_cb2_ctx = hapd;
+	hapd->gas_frag_limit = 1400;
+	if (hapd->conf->gas_frag_limit > 0)
+		hapd->gas_frag_limit = hapd->conf->gas_frag_limit;
+	return 0;
+}
+
+
+void gas_serv_deinit(struct hostapd_data *hapd)
+{
+}

+ 83 - 0
EVSE/GPL/hostapd-2.6/src/ap/gas_serv.h

@@ -0,0 +1,83 @@
+/*
+ * Generic advertisement service (GAS) server
+ * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef GAS_SERV_H
+#define GAS_SERV_H
+
+/* First 16 ANQP InfoIDs can be included in the optimized bitmap */
+#define ANQP_REQ_CAPABILITY_LIST \
+	(1 << (ANQP_CAPABILITY_LIST - ANQP_QUERY_LIST))
+#define ANQP_REQ_VENUE_NAME \
+	(1 << (ANQP_VENUE_NAME - ANQP_QUERY_LIST))
+#define ANQP_REQ_EMERGENCY_CALL_NUMBER \
+	(1 << (ANQP_EMERGENCY_CALL_NUMBER - ANQP_QUERY_LIST))
+#define ANQP_REQ_NETWORK_AUTH_TYPE \
+	(1 << (ANQP_NETWORK_AUTH_TYPE - ANQP_QUERY_LIST))
+#define ANQP_REQ_ROAMING_CONSORTIUM \
+	(1 << (ANQP_ROAMING_CONSORTIUM - ANQP_QUERY_LIST))
+#define ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY \
+	(1 << (ANQP_IP_ADDR_TYPE_AVAILABILITY - ANQP_QUERY_LIST))
+#define ANQP_REQ_NAI_REALM \
+	(1 << (ANQP_NAI_REALM - ANQP_QUERY_LIST))
+#define ANQP_REQ_3GPP_CELLULAR_NETWORK \
+	(1 << (ANQP_3GPP_CELLULAR_NETWORK - ANQP_QUERY_LIST))
+#define ANQP_REQ_AP_GEOSPATIAL_LOCATION \
+	(1 << (ANQP_AP_GEOSPATIAL_LOCATION - ANQP_QUERY_LIST))
+#define ANQP_REQ_AP_CIVIC_LOCATION \
+	(1 << (ANQP_AP_CIVIC_LOCATION - ANQP_QUERY_LIST))
+#define ANQP_REQ_AP_LOCATION_PUBLIC_URI \
+	(1 << (ANQP_AP_LOCATION_PUBLIC_URI - ANQP_QUERY_LIST))
+#define ANQP_REQ_DOMAIN_NAME \
+	(1 << (ANQP_DOMAIN_NAME - ANQP_QUERY_LIST))
+#define ANQP_REQ_EMERGENCY_ALERT_URI \
+	(1 << (ANQP_EMERGENCY_ALERT_URI - ANQP_QUERY_LIST))
+#define ANQP_REQ_TDLS_CAPABILITY \
+	(1 << (ANQP_TDLS_CAPABILITY - ANQP_QUERY_LIST))
+#define ANQP_REQ_EMERGENCY_NAI \
+	(1 << (ANQP_EMERGENCY_NAI - ANQP_QUERY_LIST))
+/*
+ * First 16 Hotspot 2.0 vendor specific ANQP-elements can be included in the
+ * optimized bitmap.
+ */
+#define ANQP_REQ_HS_CAPABILITY_LIST \
+	(0x10000 << HS20_STYPE_CAPABILITY_LIST)
+#define ANQP_REQ_OPERATOR_FRIENDLY_NAME \
+	(0x10000 << HS20_STYPE_OPERATOR_FRIENDLY_NAME)
+#define ANQP_REQ_WAN_METRICS \
+	(0x10000 << HS20_STYPE_WAN_METRICS)
+#define ANQP_REQ_CONNECTION_CAPABILITY \
+	(0x10000 << HS20_STYPE_CONNECTION_CAPABILITY)
+#define ANQP_REQ_NAI_HOME_REALM \
+	(0x10000 << HS20_STYPE_NAI_HOME_REALM_QUERY)
+#define ANQP_REQ_OPERATING_CLASS \
+	(0x10000 << HS20_STYPE_OPERATING_CLASS)
+#define ANQP_REQ_OSU_PROVIDERS_LIST \
+	(0x10000 << HS20_STYPE_OSU_PROVIDERS_LIST)
+#define ANQP_REQ_ICON_REQUEST \
+	(0x10000 << HS20_STYPE_ICON_REQUEST)
+
+struct gas_dialog_info {
+	u8 valid;
+	struct wpabuf *sd_resp; /* Fragmented response */
+	u8 dialog_token;
+	size_t sd_resp_pos; /* Offset in sd_resp */
+	u8 sd_frag_id;
+	int prot; /* whether Protected Dual of Public Action frame is used */
+};
+
+struct hostapd_data;
+
+struct gas_dialog_info *
+gas_serv_dialog_find(struct hostapd_data *hapd, const u8 *addr,
+		     u8 dialog_token);
+void gas_serv_dialog_clear(struct gas_dialog_info *dialog);
+
+int gas_serv_init(struct hostapd_data *hapd);
+void gas_serv_deinit(struct hostapd_data *hapd);
+
+#endif /* GAS_SERV_H */

+ 3284 - 0
EVSE/GPL/hostapd-2.6/src/ap/hostapd.c

@@ -0,0 +1,3284 @@
+/*
+ * hostapd / Initialization and configuration
+ * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
+#include "common/wpa_ctrl.h"
+#include "common/hw_features_common.h"
+#include "radius/radius_client.h"
+#include "radius/radius_das.h"
+#include "eap_server/tncs.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "eapol_auth/eapol_auth_sm_i.h"
+#include "fst/fst.h"
+#include "hostapd.h"
+#include "authsrv.h"
+#include "sta_info.h"
+#include "accounting.h"
+#include "ap_list.h"
+#include "beacon.h"
+#include "iapp.h"
+#include "ieee802_1x.h"
+#include "ieee802_11_auth.h"
+#include "vlan_init.h"
+#include "wpa_auth.h"
+#include "wps_hostapd.h"
+#include "hw_features.h"
+#include "wpa_auth_glue.h"
+#include "ap_drv_ops.h"
+#include "ap_config.h"
+#include "p2p_hostapd.h"
+#include "gas_serv.h"
+#include "dfs.h"
+#include "ieee802_11.h"
+#include "bss_load.h"
+#include "x_snoop.h"
+#include "dhcp_snoop.h"
+#include "ndisc_snoop.h"
+#include "neighbor_db.h"
+#include "rrm.h"
+
+
+static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason);
+static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd);
+static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd);
+static int setup_interface2(struct hostapd_iface *iface);
+static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
+
+
+int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+			       int (*cb)(struct hostapd_iface *iface,
+					 void *ctx), void *ctx)
+{
+	size_t i;
+	int ret;
+
+	for (i = 0; i < interfaces->count; i++) {
+		ret = cb(interfaces->iface[i], ctx);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+
+static void hostapd_reload_bss(struct hostapd_data *hapd)
+{
+	struct hostapd_ssid *ssid;
+
+#ifndef CONFIG_NO_RADIUS
+	radius_client_reconfig(hapd->radius, hapd->conf->radius);
+#endif /* CONFIG_NO_RADIUS */
+
+	ssid = &hapd->conf->ssid;
+	if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next &&
+	    ssid->wpa_passphrase_set && ssid->wpa_passphrase) {
+		/*
+		 * Force PSK to be derived again since SSID or passphrase may
+		 * have changed.
+		 */
+		hostapd_config_clear_wpa_psk(&hapd->conf->ssid.wpa_psk);
+	}
+	if (hostapd_setup_wpa_psk(hapd->conf)) {
+		wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK "
+			   "after reloading configuration");
+	}
+
+	if (hapd->conf->ieee802_1x || hapd->conf->wpa)
+		hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1);
+	else
+		hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0);
+
+	if ((hapd->conf->wpa || hapd->conf->osen) && hapd->wpa_auth == NULL) {
+		hostapd_setup_wpa(hapd);
+		if (hapd->wpa_auth)
+			wpa_init_keys(hapd->wpa_auth);
+	} else if (hapd->conf->wpa) {
+		const u8 *wpa_ie;
+		size_t wpa_ie_len;
+		hostapd_reconfig_wpa(hapd);
+		wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
+		if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len))
+			wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
+				   "the kernel driver.");
+	} else if (hapd->wpa_auth) {
+		wpa_deinit(hapd->wpa_auth);
+		hapd->wpa_auth = NULL;
+		hostapd_set_privacy(hapd, 0);
+		hostapd_setup_encryption(hapd->conf->iface, hapd);
+		hostapd_set_generic_elem(hapd, (u8 *) "", 0);
+	}
+
+	ieee802_11_set_beacon(hapd);
+	hostapd_update_wps(hapd);
+
+	if (hapd->conf->ssid.ssid_set &&
+	    hostapd_set_ssid(hapd, hapd->conf->ssid.ssid,
+			     hapd->conf->ssid.ssid_len)) {
+		wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
+		/* try to continue */
+	}
+	wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface);
+}
+
+
+static void hostapd_clear_old(struct hostapd_iface *iface)
+{
+	size_t j;
+
+	/*
+	 * Deauthenticate all stations since the new configuration may not
+	 * allow them to use the BSS anymore.
+	 */
+	for (j = 0; j < iface->num_bss; j++) {
+		hostapd_flush_old_stations(iface->bss[j],
+					   WLAN_REASON_PREV_AUTH_NOT_VALID);
+		hostapd_broadcast_wep_clear(iface->bss[j]);
+
+#ifndef CONFIG_NO_RADIUS
+		/* TODO: update dynamic data based on changed configuration
+		 * items (e.g., open/close sockets, etc.) */
+		radius_client_flush(iface->bss[j]->radius, 0);
+#endif /* CONFIG_NO_RADIUS */
+	}
+}
+
+
+int hostapd_reload_config(struct hostapd_iface *iface)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+	struct hostapd_config *newconf, *oldconf;
+	size_t j;
+
+	if (iface->config_fname == NULL) {
+		/* Only in-memory config in use - assume it has been updated */
+		hostapd_clear_old(iface);
+		for (j = 0; j < iface->num_bss; j++)
+			hostapd_reload_bss(iface->bss[j]);
+		return 0;
+	}
+
+	if (iface->interfaces == NULL ||
+	    iface->interfaces->config_read_cb == NULL)
+		return -1;
+	newconf = iface->interfaces->config_read_cb(iface->config_fname);
+	if (newconf == NULL)
+		return -1;
+
+	hostapd_clear_old(iface);
+
+	oldconf = hapd->iconf;
+	iface->conf = newconf;
+
+	for (j = 0; j < iface->num_bss; j++) {
+		hapd = iface->bss[j];
+		hapd->iconf = newconf;
+		hapd->iconf->channel = oldconf->channel;
+		hapd->iconf->acs = oldconf->acs;
+		hapd->iconf->secondary_channel = oldconf->secondary_channel;
+		hapd->iconf->ieee80211n = oldconf->ieee80211n;
+		hapd->iconf->ieee80211ac = oldconf->ieee80211ac;
+		hapd->iconf->ht_capab = oldconf->ht_capab;
+		hapd->iconf->vht_capab = oldconf->vht_capab;
+		hapd->iconf->vht_oper_chwidth = oldconf->vht_oper_chwidth;
+		hapd->iconf->vht_oper_centr_freq_seg0_idx =
+			oldconf->vht_oper_centr_freq_seg0_idx;
+		hapd->iconf->vht_oper_centr_freq_seg1_idx =
+			oldconf->vht_oper_centr_freq_seg1_idx;
+		hapd->conf = newconf->bss[j];
+		hostapd_reload_bss(hapd);
+	}
+
+	hostapd_config_free(oldconf);
+
+
+	return 0;
+}
+
+
+static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
+					      const char *ifname)
+{
+	int i;
+
+	if (!ifname)
+		return;
+	for (i = 0; i < NUM_WEP_KEYS; i++) {
+		if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
+					0, NULL, 0, NULL, 0)) {
+			wpa_printf(MSG_DEBUG, "Failed to clear default "
+				   "encryption keys (ifname=%s keyidx=%d)",
+				   ifname, i);
+		}
+	}
+#ifdef CONFIG_IEEE80211W
+	if (hapd->conf->ieee80211w) {
+		for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
+			if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
+						NULL, i, 0, NULL,
+						0, NULL, 0)) {
+				wpa_printf(MSG_DEBUG, "Failed to clear "
+					   "default mgmt encryption keys "
+					   "(ifname=%s keyidx=%d)", ifname, i);
+			}
+		}
+	}
+#endif /* CONFIG_IEEE80211W */
+}
+
+
+static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd)
+{
+	hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface);
+	return 0;
+}
+
+
+static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
+{
+	int errors = 0, idx;
+	struct hostapd_ssid *ssid = &hapd->conf->ssid;
+
+	idx = ssid->wep.idx;
+	if (ssid->wep.default_len &&
+	    hostapd_drv_set_key(hapd->conf->iface,
+				hapd, WPA_ALG_WEP, broadcast_ether_addr, idx,
+				1, NULL, 0, ssid->wep.key[idx],
+				ssid->wep.len[idx])) {
+		wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
+		errors++;
+	}
+
+	return errors;
+}
+
+
+static void hostapd_free_hapd_data(struct hostapd_data *hapd)
+{
+	os_free(hapd->probereq_cb);
+	hapd->probereq_cb = NULL;
+	hapd->num_probereq_cb = 0;
+
+#ifdef CONFIG_P2P
+	wpabuf_free(hapd->p2p_beacon_ie);
+	hapd->p2p_beacon_ie = NULL;
+	wpabuf_free(hapd->p2p_probe_resp_ie);
+	hapd->p2p_probe_resp_ie = NULL;
+#endif /* CONFIG_P2P */
+
+	if (!hapd->started) {
+		wpa_printf(MSG_ERROR, "%s: Interface %s wasn't started",
+			   __func__, hapd->conf->iface);
+		return;
+	}
+	hapd->started = 0;
+
+	wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
+	iapp_deinit(hapd->iapp);
+	hapd->iapp = NULL;
+	accounting_deinit(hapd);
+	hostapd_deinit_wpa(hapd);
+	vlan_deinit(hapd);
+	hostapd_acl_deinit(hapd);
+#ifndef CONFIG_NO_RADIUS
+	radius_client_deinit(hapd->radius);
+	hapd->radius = NULL;
+	radius_das_deinit(hapd->radius_das);
+	hapd->radius_das = NULL;
+#endif /* CONFIG_NO_RADIUS */
+
+	hostapd_deinit_wps(hapd);
+
+	authsrv_deinit(hapd);
+
+	if (hapd->interface_added) {
+		hapd->interface_added = 0;
+		if (hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
+			wpa_printf(MSG_WARNING,
+				   "Failed to remove BSS interface %s",
+				   hapd->conf->iface);
+			hapd->interface_added = 1;
+		} else {
+			/*
+			 * Since this was a dynamically added interface, the
+			 * driver wrapper may have removed its internal instance
+			 * and hapd->drv_priv is not valid anymore.
+			 */
+			hapd->drv_priv = NULL;
+		}
+	}
+
+	wpabuf_free(hapd->time_adv);
+
+#ifdef CONFIG_INTERWORKING
+	gas_serv_deinit(hapd);
+#endif /* CONFIG_INTERWORKING */
+
+	bss_load_update_deinit(hapd);
+	ndisc_snoop_deinit(hapd);
+	dhcp_snoop_deinit(hapd);
+	x_snoop_deinit(hapd);
+
+#ifdef CONFIG_SQLITE
+	bin_clear_free(hapd->tmp_eap_user.identity,
+		       hapd->tmp_eap_user.identity_len);
+	bin_clear_free(hapd->tmp_eap_user.password,
+		       hapd->tmp_eap_user.password_len);
+#endif /* CONFIG_SQLITE */
+
+#ifdef CONFIG_MESH
+	wpabuf_free(hapd->mesh_pending_auth);
+	hapd->mesh_pending_auth = NULL;
+#endif /* CONFIG_MESH */
+
+	hostapd_clean_rrm(hapd);
+}
+
+
+/**
+ * hostapd_cleanup - Per-BSS cleanup (deinitialization)
+ * @hapd: Pointer to BSS data
+ *
+ * This function is used to free all per-BSS data structures and resources.
+ * Most of the modules that are initialized in hostapd_setup_bss() are
+ * deinitialized here.
+ */
+static void hostapd_cleanup(struct hostapd_data *hapd)
+{
+	wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s))", __func__, hapd,
+		   hapd->conf->iface);
+	if (hapd->iface->interfaces &&
+	    hapd->iface->interfaces->ctrl_iface_deinit)
+		hapd->iface->interfaces->ctrl_iface_deinit(hapd);
+	hostapd_free_hapd_data(hapd);
+}
+
+
+static void sta_track_deinit(struct hostapd_iface *iface)
+{
+	struct hostapd_sta_info *info;
+
+	if (!iface->num_sta_seen)
+		return;
+
+	while ((info = dl_list_first(&iface->sta_seen, struct hostapd_sta_info,
+				     list))) {
+		dl_list_del(&info->list);
+		iface->num_sta_seen--;
+		sta_track_del(info);
+	}
+}
+
+
+static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
+{
+	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
+#ifdef CONFIG_IEEE80211N
+#ifdef NEED_AP_MLME
+	hostapd_stop_setup_timers(iface);
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_IEEE80211N */
+	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
+	iface->hw_features = NULL;
+	os_free(iface->current_rates);
+	iface->current_rates = NULL;
+	os_free(iface->basic_rates);
+	iface->basic_rates = NULL;
+	ap_list_deinit(iface);
+	sta_track_deinit(iface);
+}
+
+
+/**
+ * hostapd_cleanup_iface - Complete per-interface cleanup
+ * @iface: Pointer to interface data
+ *
+ * This function is called after per-BSS data structures are deinitialized
+ * with hostapd_cleanup().
+ */
+static void hostapd_cleanup_iface(struct hostapd_iface *iface)
+{
+	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
+	eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
+
+	hostapd_cleanup_iface_partial(iface);
+	hostapd_config_free(iface->conf);
+	iface->conf = NULL;
+
+	os_free(iface->config_fname);
+	os_free(iface->bss);
+	wpa_printf(MSG_DEBUG, "%s: free iface=%p", __func__, iface);
+	os_free(iface);
+}
+
+
+static void hostapd_clear_wep(struct hostapd_data *hapd)
+{
+	if (hapd->drv_priv && !hapd->iface->driver_ap_teardown) {
+		hostapd_set_privacy(hapd, 0);
+		hostapd_broadcast_wep_clear(hapd);
+	}
+}
+
+
+static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
+{
+	int i;
+
+	hostapd_broadcast_wep_set(hapd);
+
+	if (hapd->conf->ssid.wep.default_len) {
+		hostapd_set_privacy(hapd, 1);
+		return 0;
+	}
+
+	/*
+	 * When IEEE 802.1X is not enabled, the driver may need to know how to
+	 * set authentication algorithms for static WEP.
+	 */
+	hostapd_drv_set_authmode(hapd, hapd->conf->auth_algs);
+
+	for (i = 0; i < 4; i++) {
+		if (hapd->conf->ssid.wep.key[i] &&
+		    hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
+					i == hapd->conf->ssid.wep.idx, NULL, 0,
+					hapd->conf->ssid.wep.key[i],
+					hapd->conf->ssid.wep.len[i])) {
+			wpa_printf(MSG_WARNING, "Could not set WEP "
+				   "encryption.");
+			return -1;
+		}
+		if (hapd->conf->ssid.wep.key[i] &&
+		    i == hapd->conf->ssid.wep.idx)
+			hostapd_set_privacy(hapd, 1);
+	}
+
+	return 0;
+}
+
+
+static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason)
+{
+	int ret = 0;
+	u8 addr[ETH_ALEN];
+
+	if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL)
+		return 0;
+
+	if (!hapd->iface->driver_ap_teardown) {
+		wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
+			"Flushing old station entries");
+
+		if (hostapd_flush(hapd)) {
+			wpa_msg(hapd->msg_ctx, MSG_WARNING,
+				"Could not connect to kernel driver");
+			ret = -1;
+		}
+	}
+	wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations");
+	os_memset(addr, 0xff, ETH_ALEN);
+	hostapd_drv_sta_deauth(hapd, addr, reason);
+	hostapd_free_stas(hapd);
+
+	return ret;
+}
+
+
+static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd)
+{
+	hostapd_free_stas(hapd);
+	hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
+	hostapd_clear_wep(hapd);
+}
+
+
+/**
+ * hostapd_validate_bssid_configuration - Validate BSSID configuration
+ * @iface: Pointer to interface data
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to validate that the configured BSSIDs are valid.
+ */
+static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
+{
+	u8 mask[ETH_ALEN] = { 0 };
+	struct hostapd_data *hapd = iface->bss[0];
+	unsigned int i = iface->conf->num_bss, bits = 0, j;
+	int auto_addr = 0;
+
+	if (hostapd_drv_none(hapd))
+		return 0;
+
+	if (iface->conf->use_driver_iface_addr)
+		return 0;
+
+	/* Generate BSSID mask that is large enough to cover the BSSIDs. */
+
+	/* Determine the bits necessary to cover the number of BSSIDs. */
+	for (i--; i; i >>= 1)
+		bits++;
+
+	/* Determine the bits necessary to any configured BSSIDs,
+	   if they are higher than the number of BSSIDs. */
+	for (j = 0; j < iface->conf->num_bss; j++) {
+		if (is_zero_ether_addr(iface->conf->bss[j]->bssid)) {
+			if (j)
+				auto_addr++;
+			continue;
+		}
+
+		for (i = 0; i < ETH_ALEN; i++) {
+			mask[i] |=
+				iface->conf->bss[j]->bssid[i] ^
+				hapd->own_addr[i];
+		}
+	}
+
+	if (!auto_addr)
+		goto skip_mask_ext;
+
+	for (i = 0; i < ETH_ALEN && mask[i] == 0; i++)
+		;
+	j = 0;
+	if (i < ETH_ALEN) {
+		j = (5 - i) * 8;
+
+		while (mask[i] != 0) {
+			mask[i] >>= 1;
+			j++;
+		}
+	}
+
+	if (bits < j)
+		bits = j;
+
+	if (bits > 40) {
+		wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)",
+			   bits);
+		return -1;
+	}
+
+	os_memset(mask, 0xff, ETH_ALEN);
+	j = bits / 8;
+	for (i = 5; i > 5 - j; i--)
+		mask[i] = 0;
+	j = bits % 8;
+	while (j--)
+		mask[i] <<= 1;
+
+skip_mask_ext:
+	wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)",
+		   (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits);
+
+	if (!auto_addr)
+		return 0;
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) {
+			wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR
+				   " for start address " MACSTR ".",
+				   MAC2STR(mask), MAC2STR(hapd->own_addr));
+			wpa_printf(MSG_ERROR, "Start address must be the "
+				   "first address in the block (i.e., addr "
+				   "AND mask == addr).");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+
+static int mac_in_conf(struct hostapd_config *conf, const void *a)
+{
+	size_t i;
+
+	for (i = 0; i < conf->num_bss; i++) {
+		if (hostapd_mac_comp(conf->bss[i]->bssid, a) == 0) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+
+#ifndef CONFIG_NO_RADIUS
+
+static int hostapd_das_nas_mismatch(struct hostapd_data *hapd,
+				    struct radius_das_attrs *attr)
+{
+	if (attr->nas_identifier &&
+	    (!hapd->conf->nas_identifier ||
+	     os_strlen(hapd->conf->nas_identifier) !=
+	     attr->nas_identifier_len ||
+	     os_memcmp(hapd->conf->nas_identifier, attr->nas_identifier,
+		       attr->nas_identifier_len) != 0)) {
+		wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-Identifier mismatch");
+		return 1;
+	}
+
+	if (attr->nas_ip_addr &&
+	    (hapd->conf->own_ip_addr.af != AF_INET ||
+	     os_memcmp(&hapd->conf->own_ip_addr.u.v4, attr->nas_ip_addr, 4) !=
+	     0)) {
+		wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-IP-Address mismatch");
+		return 1;
+	}
+
+#ifdef CONFIG_IPV6
+	if (attr->nas_ipv6_addr &&
+	    (hapd->conf->own_ip_addr.af != AF_INET6 ||
+	     os_memcmp(&hapd->conf->own_ip_addr.u.v6, attr->nas_ipv6_addr, 16)
+	     != 0)) {
+		wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-IPv6-Address mismatch");
+		return 1;
+	}
+#endif /* CONFIG_IPV6 */
+
+	return 0;
+}
+
+
+static struct sta_info * hostapd_das_find_sta(struct hostapd_data *hapd,
+					      struct radius_das_attrs *attr,
+					      int *multi)
+{
+	struct sta_info *selected, *sta;
+	char buf[128];
+	int num_attr = 0;
+	int count;
+
+	*multi = 0;
+
+	for (sta = hapd->sta_list; sta; sta = sta->next)
+		sta->radius_das_match = 1;
+
+	if (attr->sta_addr) {
+		num_attr++;
+		sta = ap_get_sta(hapd, attr->sta_addr);
+		if (!sta) {
+			wpa_printf(MSG_DEBUG,
+				   "RADIUS DAS: No Calling-Station-Id match");
+			return NULL;
+		}
+
+		selected = sta;
+		for (sta = hapd->sta_list; sta; sta = sta->next) {
+			if (sta != selected)
+				sta->radius_das_match = 0;
+		}
+		wpa_printf(MSG_DEBUG, "RADIUS DAS: Calling-Station-Id match");
+	}
+
+	if (attr->acct_session_id) {
+		num_attr++;
+		if (attr->acct_session_id_len != 16) {
+			wpa_printf(MSG_DEBUG,
+				   "RADIUS DAS: Acct-Session-Id cannot match");
+			return NULL;
+		}
+		count = 0;
+
+		for (sta = hapd->sta_list; sta; sta = sta->next) {
+			if (!sta->radius_das_match)
+				continue;
+			os_snprintf(buf, sizeof(buf), "%016llX",
+				    (unsigned long long) sta->acct_session_id);
+			if (os_memcmp(attr->acct_session_id, buf, 16) != 0)
+				sta->radius_das_match = 0;
+			else
+				count++;
+		}
+
+		if (count == 0) {
+			wpa_printf(MSG_DEBUG,
+				   "RADIUS DAS: No matches remaining after Acct-Session-Id check");
+			return NULL;
+		}
+		wpa_printf(MSG_DEBUG, "RADIUS DAS: Acct-Session-Id match");
+	}
+
+	if (attr->acct_multi_session_id) {
+		num_attr++;
+		if (attr->acct_multi_session_id_len != 16) {
+			wpa_printf(MSG_DEBUG,
+				   "RADIUS DAS: Acct-Multi-Session-Id cannot match");
+			return NULL;
+		}
+		count = 0;
+
+		for (sta = hapd->sta_list; sta; sta = sta->next) {
+			if (!sta->radius_das_match)
+				continue;
+			if (!sta->eapol_sm ||
+			    !sta->eapol_sm->acct_multi_session_id) {
+				sta->radius_das_match = 0;
+				continue;
+			}
+			os_snprintf(buf, sizeof(buf), "%016llX",
+				    (unsigned long long)
+				    sta->eapol_sm->acct_multi_session_id);
+			if (os_memcmp(attr->acct_multi_session_id, buf, 16) !=
+			    0)
+				sta->radius_das_match = 0;
+			else
+				count++;
+		}
+
+		if (count == 0) {
+			wpa_printf(MSG_DEBUG,
+				   "RADIUS DAS: No matches remaining after Acct-Multi-Session-Id check");
+			return NULL;
+		}
+		wpa_printf(MSG_DEBUG,
+			   "RADIUS DAS: Acct-Multi-Session-Id match");
+	}
+
+	if (attr->cui) {
+		num_attr++;
+		count = 0;
+
+		for (sta = hapd->sta_list; sta; sta = sta->next) {
+			struct wpabuf *cui;
+
+			if (!sta->radius_das_match)
+				continue;
+			cui = ieee802_1x_get_radius_cui(sta->eapol_sm);
+			if (!cui || wpabuf_len(cui) != attr->cui_len ||
+			    os_memcmp(wpabuf_head(cui), attr->cui,
+				      attr->cui_len) != 0)
+				sta->radius_das_match = 0;
+			else
+				count++;
+		}
+
+		if (count == 0) {
+			wpa_printf(MSG_DEBUG,
+				   "RADIUS DAS: No matches remaining after Chargeable-User-Identity check");
+			return NULL;
+		}
+		wpa_printf(MSG_DEBUG,
+			   "RADIUS DAS: Chargeable-User-Identity match");
+	}
+
+	if (attr->user_name) {
+		num_attr++;
+		count = 0;
+
+		for (sta = hapd->sta_list; sta; sta = sta->next) {
+			u8 *identity;
+			size_t identity_len;
+
+			if (!sta->radius_das_match)
+				continue;
+			identity = ieee802_1x_get_identity(sta->eapol_sm,
+							   &identity_len);
+			if (!identity ||
+			    identity_len != attr->user_name_len ||
+			    os_memcmp(identity, attr->user_name, identity_len)
+			    != 0)
+				sta->radius_das_match = 0;
+			else
+				count++;
+		}
+
+		if (count == 0) {
+			wpa_printf(MSG_DEBUG,
+				   "RADIUS DAS: No matches remaining after User-Name check");
+			return NULL;
+		}
+		wpa_printf(MSG_DEBUG,
+			   "RADIUS DAS: User-Name match");
+	}
+
+	if (num_attr == 0) {
+		/*
+		 * In theory, we could match all current associations, but it
+		 * seems safer to just reject requests that do not include any
+		 * session identification attributes.
+		 */
+		wpa_printf(MSG_DEBUG,
+			   "RADIUS DAS: No session identification attributes included");
+		return NULL;
+	}
+
+	selected = NULL;
+	for (sta = hapd->sta_list; sta; sta = sta->next) {
+		if (sta->radius_das_match) {
+			if (selected) {
+				*multi = 1;
+				return NULL;
+			}
+			selected = sta;
+		}
+	}
+
+	return selected;
+}
+
+
+static int hostapd_das_disconnect_pmksa(struct hostapd_data *hapd,
+					struct radius_das_attrs *attr)
+{
+	if (!hapd->wpa_auth)
+		return -1;
+	return wpa_auth_radius_das_disconnect_pmksa(hapd->wpa_auth, attr);
+}
+
+
+static enum radius_das_res
+hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr)
+{
+	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta;
+	int multi;
+
+	if (hostapd_das_nas_mismatch(hapd, attr))
+		return RADIUS_DAS_NAS_MISMATCH;
+
+	sta = hostapd_das_find_sta(hapd, attr, &multi);
+	if (sta == NULL) {
+		if (multi) {
+			wpa_printf(MSG_DEBUG,
+				   "RADIUS DAS: Multiple sessions match - not supported");
+			return RADIUS_DAS_MULTI_SESSION_MATCH;
+		}
+		if (hostapd_das_disconnect_pmksa(hapd, attr) == 0) {
+			wpa_printf(MSG_DEBUG,
+				   "RADIUS DAS: PMKSA cache entry matched");
+			return RADIUS_DAS_SUCCESS;
+		}
+		wpa_printf(MSG_DEBUG, "RADIUS DAS: No matching session found");
+		return RADIUS_DAS_SESSION_NOT_FOUND;
+	}
+
+	wpa_printf(MSG_DEBUG, "RADIUS DAS: Found a matching session " MACSTR
+		   " - disconnecting", MAC2STR(sta->addr));
+	wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
+
+	hostapd_drv_sta_deauth(hapd, sta->addr,
+			       WLAN_REASON_PREV_AUTH_NOT_VALID);
+	ap_sta_deauthenticate(hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID);
+
+	return RADIUS_DAS_SUCCESS;
+}
+
+#endif /* CONFIG_NO_RADIUS */
+
+
+/**
+ * hostapd_setup_bss - Per-BSS setup (initialization)
+ * @hapd: Pointer to BSS data
+ * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
+ *	but interface may exist
+ *
+ * This function is used to initialize all per-BSS data structures and
+ * resources. This gets called in a loop for each BSS when an interface is
+ * initialized. Most of the modules that are initialized here will be
+ * deinitialized in hostapd_cleanup().
+ */
+static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+{
+	struct hostapd_bss_config *conf = hapd->conf;
+	u8 ssid[SSID_MAX_LEN + 1];
+	int ssid_len, set_ssid;
+	char force_ifname[IFNAMSIZ];
+	u8 if_addr[ETH_ALEN];
+	int flush_old_stations = 1;
+
+	wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)",
+		   __func__, hapd, conf->iface, first);
+
+#ifdef EAP_SERVER_TNC
+	if (conf->tnc && tncs_global_init() < 0) {
+		wpa_printf(MSG_ERROR, "Failed to initialize TNCS");
+		return -1;
+	}
+#endif /* EAP_SERVER_TNC */
+
+	if (hapd->started) {
+		wpa_printf(MSG_ERROR, "%s: Interface %s was already started",
+			   __func__, conf->iface);
+		return -1;
+	}
+	hapd->started = 1;
+
+	if (!first || first == -1) {
+		u8 *addr = hapd->own_addr;
+
+		if (!is_zero_ether_addr(conf->bssid)) {
+			/* Allocate the configured BSSID. */
+			os_memcpy(hapd->own_addr, conf->bssid, ETH_ALEN);
+
+			if (hostapd_mac_comp(hapd->own_addr,
+					     hapd->iface->bss[0]->own_addr) ==
+			    0) {
+				wpa_printf(MSG_ERROR, "BSS '%s' may not have "
+					   "BSSID set to the MAC address of "
+					   "the radio", conf->iface);
+				return -1;
+			}
+		} else if (hapd->iconf->use_driver_iface_addr) {
+			addr = NULL;
+		} else {
+			/* Allocate the next available BSSID. */
+			do {
+				inc_byte_array(hapd->own_addr, ETH_ALEN);
+			} while (mac_in_conf(hapd->iconf, hapd->own_addr));
+		}
+
+		hapd->interface_added = 1;
+		if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
+				   conf->iface, addr, hapd,
+				   &hapd->drv_priv, force_ifname, if_addr,
+				   conf->bridge[0] ? conf->bridge : NULL,
+				   first == -1)) {
+			wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
+				   MACSTR ")", MAC2STR(hapd->own_addr));
+			hapd->interface_added = 0;
+			return -1;
+		}
+
+		if (!addr)
+			os_memcpy(hapd->own_addr, if_addr, ETH_ALEN);
+	}
+
+	if (conf->wmm_enabled < 0)
+		conf->wmm_enabled = hapd->iconf->ieee80211n;
+
+#ifdef CONFIG_IEEE80211R
+	if (is_zero_ether_addr(conf->r1_key_holder))
+		os_memcpy(conf->r1_key_holder, hapd->own_addr, ETH_ALEN);
+#endif /* CONFIG_IEEE80211R */
+
+#ifdef CONFIG_MESH
+	if (hapd->iface->mconf == NULL)
+		flush_old_stations = 0;
+#endif /* CONFIG_MESH */
+
+	if (flush_old_stations)
+		hostapd_flush_old_stations(hapd,
+					   WLAN_REASON_PREV_AUTH_NOT_VALID);
+	hostapd_set_privacy(hapd, 0);
+
+	hostapd_broadcast_wep_clear(hapd);
+	if (hostapd_setup_encryption(conf->iface, hapd))
+		return -1;
+
+	/*
+	 * Fetch the SSID from the system and use it or,
+	 * if one was specified in the config file, verify they
+	 * match.
+	 */
+	ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid));
+	if (ssid_len < 0) {
+		wpa_printf(MSG_ERROR, "Could not read SSID from system");
+		return -1;
+	}
+	if (conf->ssid.ssid_set) {
+		/*
+		 * If SSID is specified in the config file and it differs
+		 * from what is being used then force installation of the
+		 * new SSID.
+		 */
+		set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len ||
+			    os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0);
+	} else {
+		/*
+		 * No SSID in the config file; just use the one we got
+		 * from the system.
+		 */
+		set_ssid = 0;
+		conf->ssid.ssid_len = ssid_len;
+		os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len);
+	}
+
+	if (!hostapd_drv_none(hapd)) {
+		wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR
+			   " and ssid \"%s\"",
+			   conf->iface, MAC2STR(hapd->own_addr),
+			   wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len));
+	}
+
+	if (hostapd_setup_wpa_psk(conf)) {
+		wpa_printf(MSG_ERROR, "WPA-PSK setup failed.");
+		return -1;
+	}
+
+	/* Set SSID for the kernel driver (to be used in beacon and probe
+	 * response frames) */
+	if (set_ssid && hostapd_set_ssid(hapd, conf->ssid.ssid,
+					 conf->ssid.ssid_len)) {
+		wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver");
+		return -1;
+	}
+
+	if (wpa_debug_level <= MSG_MSGDUMP)
+		conf->radius->msg_dumps = 1;
+#ifndef CONFIG_NO_RADIUS
+	hapd->radius = radius_client_init(hapd, conf->radius);
+	if (hapd->radius == NULL) {
+		wpa_printf(MSG_ERROR, "RADIUS client initialization failed.");
+		return -1;
+	}
+
+	if (conf->radius_das_port) {
+		struct radius_das_conf das_conf;
+		os_memset(&das_conf, 0, sizeof(das_conf));
+		das_conf.port = conf->radius_das_port;
+		das_conf.shared_secret = conf->radius_das_shared_secret;
+		das_conf.shared_secret_len =
+			conf->radius_das_shared_secret_len;
+		das_conf.client_addr = &conf->radius_das_client_addr;
+		das_conf.time_window = conf->radius_das_time_window;
+		das_conf.require_event_timestamp =
+			conf->radius_das_require_event_timestamp;
+		das_conf.require_message_authenticator =
+			conf->radius_das_require_message_authenticator;
+		das_conf.ctx = hapd;
+		das_conf.disconnect = hostapd_das_disconnect;
+		hapd->radius_das = radius_das_init(&das_conf);
+		if (hapd->radius_das == NULL) {
+			wpa_printf(MSG_ERROR, "RADIUS DAS initialization "
+				   "failed.");
+			return -1;
+		}
+	}
+#endif /* CONFIG_NO_RADIUS */
+
+	if (hostapd_acl_init(hapd)) {
+		wpa_printf(MSG_ERROR, "ACL initialization failed.");
+		return -1;
+	}
+	if (hostapd_init_wps(hapd, conf))
+		return -1;
+
+	if (authsrv_init(hapd) < 0)
+		return -1;
+
+	if (ieee802_1x_init(hapd)) {
+		wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed.");
+		return -1;
+	}
+
+	if ((conf->wpa || conf->osen) && hostapd_setup_wpa(hapd))
+		return -1;
+
+	if (accounting_init(hapd)) {
+		wpa_printf(MSG_ERROR, "Accounting initialization failed.");
+		return -1;
+	}
+
+	if (conf->ieee802_11f &&
+	    (hapd->iapp = iapp_init(hapd, conf->iapp_iface)) == NULL) {
+		wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
+			   "failed.");
+		return -1;
+	}
+
+#ifdef CONFIG_INTERWORKING
+	if (gas_serv_init(hapd)) {
+		wpa_printf(MSG_ERROR, "GAS server initialization failed");
+		return -1;
+	}
+
+	if (conf->qos_map_set_len &&
+	    hostapd_drv_set_qos_map(hapd, conf->qos_map_set,
+				    conf->qos_map_set_len)) {
+		wpa_printf(MSG_ERROR, "Failed to initialize QoS Map");
+		return -1;
+	}
+#endif /* CONFIG_INTERWORKING */
+
+	if (conf->bss_load_update_period && bss_load_update_init(hapd)) {
+		wpa_printf(MSG_ERROR, "BSS Load initialization failed");
+		return -1;
+	}
+
+	if (conf->proxy_arp) {
+		if (x_snoop_init(hapd)) {
+			wpa_printf(MSG_ERROR,
+				   "Generic snooping infrastructure initialization failed");
+			return -1;
+		}
+
+		if (dhcp_snoop_init(hapd)) {
+			wpa_printf(MSG_ERROR,
+				   "DHCP snooping initialization failed");
+			return -1;
+		}
+
+		if (ndisc_snoop_init(hapd)) {
+			wpa_printf(MSG_ERROR,
+				   "Neighbor Discovery snooping initialization failed");
+			return -1;
+		}
+	}
+
+	if (!hostapd_drv_none(hapd) && vlan_init(hapd)) {
+		wpa_printf(MSG_ERROR, "VLAN initialization failed.");
+		return -1;
+	}
+
+	if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+		return -1;
+
+	if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+		return -1;
+
+	if (hapd->driver && hapd->driver->set_operstate)
+		hapd->driver->set_operstate(hapd->drv_priv, 1);
+
+	return 0;
+}
+
+
+static void hostapd_tx_queue_params(struct hostapd_iface *iface)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+	int i;
+	struct hostapd_tx_queue_params *p;
+
+#ifdef CONFIG_MESH
+	if (iface->mconf == NULL)
+		return;
+#endif /* CONFIG_MESH */
+
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		p = &iface->conf->tx_queue[i];
+
+		if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin,
+						p->cwmax, p->burst)) {
+			wpa_printf(MSG_DEBUG, "Failed to set TX queue "
+				   "parameters for queue %d.", i);
+			/* Continue anyway */
+		}
+	}
+}
+
+
+static int hostapd_set_acl_list(struct hostapd_data *hapd,
+				struct mac_acl_entry *mac_acl,
+				int n_entries, u8 accept_acl)
+{
+	struct hostapd_acl_params *acl_params;
+	int i, err;
+
+	acl_params = os_zalloc(sizeof(*acl_params) +
+			       (n_entries * sizeof(acl_params->mac_acl[0])));
+	if (!acl_params)
+		return -ENOMEM;
+
+	for (i = 0; i < n_entries; i++)
+		os_memcpy(acl_params->mac_acl[i].addr, mac_acl[i].addr,
+			  ETH_ALEN);
+
+	acl_params->acl_policy = accept_acl;
+	acl_params->num_mac_acl = n_entries;
+
+	err = hostapd_drv_set_acl(hapd, acl_params);
+
+	os_free(acl_params);
+
+	return err;
+}
+
+
+static void hostapd_set_acl(struct hostapd_data *hapd)
+{
+	struct hostapd_config *conf = hapd->iconf;
+	int err;
+	u8 accept_acl;
+
+	if (hapd->iface->drv_max_acl_mac_addrs == 0)
+		return;
+
+	if (conf->bss[0]->macaddr_acl == DENY_UNLESS_ACCEPTED) {
+		accept_acl = 1;
+		err = hostapd_set_acl_list(hapd, conf->bss[0]->accept_mac,
+					   conf->bss[0]->num_accept_mac,
+					   accept_acl);
+		if (err) {
+			wpa_printf(MSG_DEBUG, "Failed to set accept acl");
+			return;
+		}
+	} else if (conf->bss[0]->macaddr_acl == ACCEPT_UNLESS_DENIED) {
+		accept_acl = 0;
+		err = hostapd_set_acl_list(hapd, conf->bss[0]->deny_mac,
+					   conf->bss[0]->num_deny_mac,
+					   accept_acl);
+		if (err) {
+			wpa_printf(MSG_DEBUG, "Failed to set deny acl");
+			return;
+		}
+	}
+}
+
+
+static int start_ctrl_iface_bss(struct hostapd_data *hapd)
+{
+	if (!hapd->iface->interfaces ||
+	    !hapd->iface->interfaces->ctrl_iface_init)
+		return 0;
+
+	if (hapd->iface->interfaces->ctrl_iface_init(hapd)) {
+		wpa_printf(MSG_ERROR,
+			   "Failed to setup control interface for %s",
+			   hapd->conf->iface);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int start_ctrl_iface(struct hostapd_iface *iface)
+{
+	size_t i;
+
+	if (!iface->interfaces || !iface->interfaces->ctrl_iface_init)
+		return 0;
+
+	for (i = 0; i < iface->num_bss; i++) {
+		struct hostapd_data *hapd = iface->bss[i];
+		if (iface->interfaces->ctrl_iface_init(hapd)) {
+			wpa_printf(MSG_ERROR,
+				   "Failed to setup control interface for %s",
+				   hapd->conf->iface);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+
+static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+	struct hostapd_iface *iface = eloop_ctx;
+
+	if (!iface->wait_channel_update) {
+		wpa_printf(MSG_INFO, "Channel list update timeout, but interface was not waiting for it");
+		return;
+	}
+
+	/*
+	 * It is possible that the existing channel list is acceptable, so try
+	 * to proceed.
+	 */
+	wpa_printf(MSG_DEBUG, "Channel list update timeout - try to continue anyway");
+	setup_interface2(iface);
+}
+
+
+void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator)
+{
+	if (!iface->wait_channel_update || initiator != REGDOM_SET_BY_USER)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Channel list updated - continue setup");
+	eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
+	setup_interface2(iface);
+}
+
+
+static int setup_interface(struct hostapd_iface *iface)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+	size_t i;
+
+	/*
+	 * It is possible that setup_interface() is called after the interface
+	 * was disabled etc., in which case driver_ap_teardown is possibly set
+	 * to 1. Clear it here so any other key/station deletion, which is not
+	 * part of a teardown flow, would also call the relevant driver
+	 * callbacks.
+	 */
+	iface->driver_ap_teardown = 0;
+
+	if (!iface->phy[0]) {
+		const char *phy = hostapd_drv_get_radio_name(hapd);
+		if (phy) {
+			wpa_printf(MSG_DEBUG, "phy: %s", phy);
+			os_strlcpy(iface->phy, phy, sizeof(iface->phy));
+		}
+	}
+
+	/*
+	 * Make sure that all BSSes get configured with a pointer to the same
+	 * driver interface.
+	 */
+	for (i = 1; i < iface->num_bss; i++) {
+		iface->bss[i]->driver = hapd->driver;
+		iface->bss[i]->drv_priv = hapd->drv_priv;
+	}
+
+	if (hostapd_validate_bssid_configuration(iface))
+		return -1;
+
+	/*
+	 * Initialize control interfaces early to allow external monitoring of
+	 * channel setup operations that may take considerable amount of time
+	 * especially for DFS cases.
+	 */
+	if (start_ctrl_iface(iface))
+		return -1;
+
+	if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
+		char country[4], previous_country[4];
+
+		hostapd_set_state(iface, HAPD_IFACE_COUNTRY_UPDATE);
+		if (hostapd_get_country(hapd, previous_country) < 0)
+			previous_country[0] = '\0';
+
+		os_memcpy(country, hapd->iconf->country, 3);
+		country[3] = '\0';
+		if (hostapd_set_country(hapd, country) < 0) {
+			wpa_printf(MSG_ERROR, "Failed to set country code");
+			return -1;
+		}
+
+		wpa_printf(MSG_DEBUG, "Previous country code %s, new country code %s",
+			   previous_country, country);
+
+		if (os_strncmp(previous_country, country, 2) != 0) {
+			wpa_printf(MSG_DEBUG, "Continue interface setup after channel list update");
+			iface->wait_channel_update = 1;
+			eloop_register_timeout(5, 0,
+					       channel_list_update_timeout,
+					       iface, NULL);
+			return 0;
+		}
+	}
+
+	return setup_interface2(iface);
+}
+
+
+static int setup_interface2(struct hostapd_iface *iface)
+{
+	iface->wait_channel_update = 0;
+
+	if (hostapd_get_hw_features(iface)) {
+		/* Not all drivers support this yet, so continue without hw
+		 * feature data. */
+	} else {
+		int ret = hostapd_select_hw_mode(iface);
+		if (ret < 0) {
+			wpa_printf(MSG_ERROR, "Could not select hw_mode and "
+				   "channel. (%d)", ret);
+			goto fail;
+		}
+		if (ret == 1) {
+			wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback (ACS)");
+			return 0;
+		}
+		ret = hostapd_check_ht_capab(iface);
+		if (ret < 0)
+			goto fail;
+		if (ret == 1) {
+			wpa_printf(MSG_DEBUG, "Interface initialization will "
+				   "be completed in a callback");
+			return 0;
+		}
+
+		if (iface->conf->ieee80211h)
+			wpa_printf(MSG_DEBUG, "DFS support is enabled");
+	}
+	return hostapd_setup_interface_complete(iface, 0);
+
+fail:
+	hostapd_set_state(iface, HAPD_IFACE_DISABLED);
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+	if (iface->interfaces && iface->interfaces->terminate_on_error)
+		eloop_terminate();
+	return -1;
+}
+
+
+#ifdef CONFIG_FST
+
+static const u8 * fst_hostapd_get_bssid_cb(void *ctx)
+{
+	struct hostapd_data *hapd = ctx;
+
+	return hapd->own_addr;
+}
+
+
+static void fst_hostapd_get_channel_info_cb(void *ctx,
+					    enum hostapd_hw_mode *hw_mode,
+					    u8 *channel)
+{
+	struct hostapd_data *hapd = ctx;
+
+	*hw_mode = ieee80211_freq_to_chan(hapd->iface->freq, channel);
+}
+
+
+static void fst_hostapd_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
+{
+	struct hostapd_data *hapd = ctx;
+
+	if (hapd->iface->fst_ies != fst_ies) {
+		hapd->iface->fst_ies = fst_ies;
+		if (ieee802_11_set_beacon(hapd))
+			wpa_printf(MSG_WARNING, "FST: Cannot set beacon");
+	}
+}
+
+
+static int fst_hostapd_send_action_cb(void *ctx, const u8 *da,
+				      struct wpabuf *buf)
+{
+	struct hostapd_data *hapd = ctx;
+
+	return hostapd_drv_send_action(hapd, hapd->iface->freq, 0, da,
+				       wpabuf_head(buf), wpabuf_len(buf));
+}
+
+
+static const struct wpabuf * fst_hostapd_get_mb_ie_cb(void *ctx, const u8 *addr)
+{
+	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta = ap_get_sta(hapd, addr);
+
+	return sta ? sta->mb_ies : NULL;
+}
+
+
+static void fst_hostapd_update_mb_ie_cb(void *ctx, const u8 *addr,
+					const u8 *buf, size_t size)
+{
+	struct hostapd_data *hapd = ctx;
+	struct sta_info *sta = ap_get_sta(hapd, addr);
+
+	if (sta) {
+		struct mb_ies_info info;
+
+		if (!mb_ies_info_by_ies(&info, buf, size)) {
+			wpabuf_free(sta->mb_ies);
+			sta->mb_ies = mb_ies_by_info(&info);
+		}
+	}
+}
+
+
+static const u8 * fst_hostapd_get_sta(struct fst_get_peer_ctx **get_ctx,
+				      Boolean mb_only)
+{
+	struct sta_info *s = (struct sta_info *) *get_ctx;
+
+	if (mb_only) {
+		for (; s && !s->mb_ies; s = s->next)
+			;
+	}
+
+	if (s) {
+		*get_ctx = (struct fst_get_peer_ctx *) s->next;
+
+		return s->addr;
+	}
+
+	*get_ctx = NULL;
+	return NULL;
+}
+
+
+static const u8 * fst_hostapd_get_peer_first(void *ctx,
+					     struct fst_get_peer_ctx **get_ctx,
+					     Boolean mb_only)
+{
+	struct hostapd_data *hapd = ctx;
+
+	*get_ctx = (struct fst_get_peer_ctx *) hapd->sta_list;
+
+	return fst_hostapd_get_sta(get_ctx, mb_only);
+}
+
+
+static const u8 * fst_hostapd_get_peer_next(void *ctx,
+					    struct fst_get_peer_ctx **get_ctx,
+					    Boolean mb_only)
+{
+	return fst_hostapd_get_sta(get_ctx, mb_only);
+}
+
+
+void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
+				struct fst_wpa_obj *iface_obj)
+{
+	iface_obj->ctx = hapd;
+	iface_obj->get_bssid = fst_hostapd_get_bssid_cb;
+	iface_obj->get_channel_info = fst_hostapd_get_channel_info_cb;
+	iface_obj->set_ies = fst_hostapd_set_ies_cb;
+	iface_obj->send_action = fst_hostapd_send_action_cb;
+	iface_obj->get_mb_ie = fst_hostapd_get_mb_ie_cb;
+	iface_obj->update_mb_ie = fst_hostapd_update_mb_ie_cb;
+	iface_obj->get_peer_first = fst_hostapd_get_peer_first;
+	iface_obj->get_peer_next = fst_hostapd_get_peer_next;
+}
+
+#endif /* CONFIG_FST */
+
+
+#ifdef NEED_AP_MLME
+static enum nr_chan_width hostapd_get_nr_chan_width(struct hostapd_data *hapd,
+						    int ht, int vht)
+{
+	if (!ht && !vht)
+		return NR_CHAN_WIDTH_20;
+	if (!hapd->iconf->secondary_channel)
+		return NR_CHAN_WIDTH_20;
+	if (!vht || hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_USE_HT)
+		return NR_CHAN_WIDTH_40;
+	if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
+		return NR_CHAN_WIDTH_80;
+	if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_160MHZ)
+		return NR_CHAN_WIDTH_160;
+	if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_80P80MHZ)
+		return NR_CHAN_WIDTH_80P80;
+	return NR_CHAN_WIDTH_20;
+}
+#endif /* NEED_AP_MLME */
+
+
+static void hostapd_set_own_neighbor_report(struct hostapd_data *hapd)
+{
+#ifdef NEED_AP_MLME
+	u16 capab = hostapd_own_capab_info(hapd);
+	int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
+	int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac;
+	struct wpa_ssid_value ssid;
+	u8 channel, op_class;
+	int center_freq1 = 0, center_freq2 = 0;
+	enum nr_chan_width width;
+	u32 bssid_info;
+	struct wpabuf *nr;
+
+	if (!(hapd->conf->radio_measurements[0] &
+	      WLAN_RRM_CAPS_NEIGHBOR_REPORT))
+		return;
+
+	bssid_info = 3; /* AP is reachable */
+	bssid_info |= NEI_REP_BSSID_INFO_SECURITY; /* "same as the AP" */
+	bssid_info |= NEI_REP_BSSID_INFO_KEY_SCOPE; /* "same as the AP" */
+
+	if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT)
+		bssid_info |= NEI_REP_BSSID_INFO_SPECTRUM_MGMT;
+
+	bssid_info |= NEI_REP_BSSID_INFO_RM; /* RRM is supported */
+
+	if (hapd->conf->wmm_enabled) {
+		bssid_info |= NEI_REP_BSSID_INFO_QOS;
+
+		if (hapd->conf->wmm_uapsd &&
+		    (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
+			bssid_info |= NEI_REP_BSSID_INFO_APSD;
+	}
+
+	if (ht) {
+		bssid_info |= NEI_REP_BSSID_INFO_HT |
+			NEI_REP_BSSID_INFO_DELAYED_BA;
+
+		/* VHT bit added in IEEE P802.11-REVmc/D4.3 */
+		if (vht)
+			bssid_info |= NEI_REP_BSSID_INFO_VHT;
+	}
+
+	/* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
+
+	ieee80211_freq_to_channel_ext(hapd->iface->freq,
+				      hapd->iconf->secondary_channel,
+				      hapd->iconf->vht_oper_chwidth,
+				      &op_class, &channel);
+	width = hostapd_get_nr_chan_width(hapd, ht, vht);
+	if (vht) {
+		center_freq1 = ieee80211_chan_to_freq(
+			NULL, op_class,
+			hapd->iconf->vht_oper_centr_freq_seg0_idx);
+		if (width == NR_CHAN_WIDTH_80P80)
+			center_freq2 = ieee80211_chan_to_freq(
+				NULL, op_class,
+				hapd->iconf->vht_oper_centr_freq_seg1_idx);
+	} else if (ht) {
+		center_freq1 = hapd->iface->freq +
+			10 * hapd->iconf->secondary_channel;
+	}
+
+	ssid.ssid_len = hapd->conf->ssid.ssid_len;
+	os_memcpy(ssid.ssid, hapd->conf->ssid.ssid, ssid.ssid_len);
+
+	/*
+	 * Neighbor Report element size = BSSID + BSSID info + op_class + chan +
+	 * phy type + wide bandwidth channel subelement.
+	 */
+	nr = wpabuf_alloc(ETH_ALEN + 4 + 1 + 1 + 1 + 5);
+	if (!nr)
+		return;
+
+	wpabuf_put_data(nr, hapd->own_addr, ETH_ALEN);
+	wpabuf_put_le32(nr, bssid_info);
+	wpabuf_put_u8(nr, op_class);
+	wpabuf_put_u8(nr, channel);
+	wpabuf_put_u8(nr, ieee80211_get_phy_type(hapd->iface->freq, ht, vht));
+
+	/*
+	 * Wide Bandwidth Channel subelement may be needed to allow the
+	 * receiving STA to send packets to the AP. See IEEE P802.11-REVmc/D5.0
+	 * Figure 9-301.
+	 */
+	wpabuf_put_u8(nr, WNM_NEIGHBOR_WIDE_BW_CHAN);
+	wpabuf_put_u8(nr, 3);
+	wpabuf_put_u8(nr, width);
+	wpabuf_put_u8(nr, center_freq1);
+	wpabuf_put_u8(nr, center_freq2);
+
+	hostapd_neighbor_set(hapd, hapd->own_addr, &ssid, nr, hapd->iconf->lci,
+			     hapd->iconf->civic);
+
+	wpabuf_free(nr);
+#endif /* NEED_AP_MLME */
+}
+
+
+static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+						 int err)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+	size_t j;
+	u8 *prev_addr;
+	int delay_apply_cfg = 0;
+	int res_dfs_offload = 0;
+
+	if (err)
+		goto fail;
+
+	wpa_printf(MSG_DEBUG, "Completing interface initialization");
+	if (iface->conf->channel) {
+#ifdef NEED_AP_MLME
+		int res;
+#endif /* NEED_AP_MLME */
+
+		iface->freq = hostapd_hw_get_freq(hapd, iface->conf->channel);
+		wpa_printf(MSG_DEBUG, "Mode: %s  Channel: %d  "
+			   "Frequency: %d MHz",
+			   hostapd_hw_mode_txt(iface->conf->hw_mode),
+			   iface->conf->channel, iface->freq);
+
+#ifdef NEED_AP_MLME
+		/* Handle DFS only if it is not offloaded to the driver */
+		if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) {
+			/* Check DFS */
+			res = hostapd_handle_dfs(iface);
+			if (res <= 0) {
+				if (res < 0)
+					goto fail;
+				return res;
+			}
+		} else {
+			/* If DFS is offloaded to the driver */
+			res_dfs_offload = hostapd_handle_dfs_offload(iface);
+			if (res_dfs_offload <= 0) {
+				if (res_dfs_offload < 0)
+					goto fail;
+			} else {
+				wpa_printf(MSG_DEBUG,
+					   "Proceed with AP/channel setup");
+				/*
+				 * If this is a DFS channel, move to completing
+				 * AP setup.
+				 */
+				if (res_dfs_offload == 1)
+					goto dfs_offload;
+				/* Otherwise fall through. */
+			}
+		}
+#endif /* NEED_AP_MLME */
+
+#ifdef CONFIG_MESH
+		if (iface->mconf != NULL) {
+			wpa_printf(MSG_DEBUG,
+				   "%s: Mesh configuration will be applied while joining the mesh network",
+				   iface->bss[0]->conf->iface);
+			delay_apply_cfg = 1;
+		}
+#endif /* CONFIG_MESH */
+
+		if (!delay_apply_cfg &&
+		    hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
+				     hapd->iconf->channel,
+				     hapd->iconf->ieee80211n,
+				     hapd->iconf->ieee80211ac,
+				     hapd->iconf->secondary_channel,
+				     hapd->iconf->vht_oper_chwidth,
+				     hapd->iconf->vht_oper_centr_freq_seg0_idx,
+				     hapd->iconf->vht_oper_centr_freq_seg1_idx)) {
+			wpa_printf(MSG_ERROR, "Could not set channel for "
+				   "kernel driver");
+			goto fail;
+		}
+	}
+
+	if (iface->current_mode) {
+		if (hostapd_prepare_rates(iface, iface->current_mode)) {
+			wpa_printf(MSG_ERROR, "Failed to prepare rates "
+				   "table.");
+			hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+				       HOSTAPD_LEVEL_WARNING,
+				       "Failed to prepare rates table.");
+			goto fail;
+		}
+	}
+
+	if (hapd->iconf->rts_threshold > -1 &&
+	    hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) {
+		wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
+			   "kernel driver");
+		goto fail;
+	}
+
+	if (hapd->iconf->fragm_threshold > -1 &&
+	    hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) {
+		wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
+			   "for kernel driver");
+		goto fail;
+	}
+
+	prev_addr = hapd->own_addr;
+
+	for (j = 0; j < iface->num_bss; j++) {
+		hapd = iface->bss[j];
+		if (j)
+			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+		if (hostapd_setup_bss(hapd, j == 0)) {
+			do {
+				hapd = iface->bss[j];
+				hostapd_bss_deinit_no_free(hapd);
+				hostapd_free_hapd_data(hapd);
+			} while (j-- > 0);
+			goto fail;
+		}
+		if (is_zero_ether_addr(hapd->conf->bssid))
+			prev_addr = hapd->own_addr;
+	}
+	hapd = iface->bss[0];
+
+	hostapd_tx_queue_params(iface);
+
+	ap_list_init(iface);
+
+	hostapd_set_acl(hapd);
+
+	if (hostapd_driver_commit(hapd) < 0) {
+		wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
+			   "configuration", __func__);
+		goto fail;
+	}
+
+	/*
+	 * WPS UPnP module can be initialized only when the "upnp_iface" is up.
+	 * If "interface" and "upnp_iface" are the same (e.g., non-bridge
+	 * mode), the interface is up only after driver_commit, so initialize
+	 * WPS after driver_commit.
+	 */
+	for (j = 0; j < iface->num_bss; j++) {
+		if (hostapd_init_wps_complete(iface->bss[j]))
+			goto fail;
+	}
+
+	if ((iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
+	    !res_dfs_offload) {
+		/*
+		 * If freq is DFS, and DFS is offloaded to the driver, then wait
+		 * for CAC to complete.
+		 */
+		wpa_printf(MSG_DEBUG, "%s: Wait for CAC to complete", __func__);
+		return res_dfs_offload;
+	}
+
+#ifdef NEED_AP_MLME
+dfs_offload:
+#endif /* NEED_AP_MLME */
+
+#ifdef CONFIG_FST
+	if (hapd->iconf->fst_cfg.group_id[0]) {
+		struct fst_wpa_obj iface_obj;
+
+		fst_hostapd_fill_iface_obj(hapd, &iface_obj);
+		iface->fst = fst_attach(hapd->conf->iface, hapd->own_addr,
+					&iface_obj, &hapd->iconf->fst_cfg);
+		if (!iface->fst) {
+			wpa_printf(MSG_ERROR, "Could not attach to FST %s",
+				   hapd->iconf->fst_cfg.group_id);
+			goto fail;
+		}
+	}
+#endif /* CONFIG_FST */
+
+	hostapd_set_state(iface, HAPD_IFACE_ENABLED);
+	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
+	if (hapd->setup_complete_cb)
+		hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
+
+	wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
+		   iface->bss[0]->conf->iface);
+	if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
+		iface->interfaces->terminate_on_error--;
+
+	for (j = 0; j < iface->num_bss; j++)
+		hostapd_set_own_neighbor_report(iface->bss[j]);
+
+	return 0;
+
+fail:
+	wpa_printf(MSG_ERROR, "Interface initialization failed");
+	hostapd_set_state(iface, HAPD_IFACE_DISABLED);
+	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+#ifdef CONFIG_FST
+	if (iface->fst) {
+		fst_detach(iface->fst);
+		iface->fst = NULL;
+	}
+#endif /* CONFIG_FST */
+	if (iface->interfaces && iface->interfaces->terminate_on_error)
+		eloop_terminate();
+	return -1;
+}
+
+
+/**
+ * hostapd_setup_interface_complete - Complete interface setup
+ *
+ * This function is called when previous steps in the interface setup has been
+ * completed. This can also start operations, e.g., DFS, that will require
+ * additional processing before interface is ready to be enabled. Such
+ * operations will call this function from eloop callbacks when finished.
+ */
+int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
+{
+	struct hapd_interfaces *interfaces = iface->interfaces;
+	struct hostapd_data *hapd = iface->bss[0];
+	unsigned int i;
+	int not_ready_in_sync_ifaces = 0;
+
+	if (!iface->need_to_start_in_sync)
+		return hostapd_setup_interface_complete_sync(iface, err);
+
+	if (err) {
+		wpa_printf(MSG_ERROR, "Interface initialization failed");
+		hostapd_set_state(iface, HAPD_IFACE_DISABLED);
+		iface->need_to_start_in_sync = 0;
+		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+		if (interfaces && interfaces->terminate_on_error)
+			eloop_terminate();
+		return -1;
+	}
+
+	if (iface->ready_to_start_in_sync) {
+		/* Already in ready and waiting. should never happpen */
+		return 0;
+	}
+
+	for (i = 0; i < interfaces->count; i++) {
+		if (interfaces->iface[i]->need_to_start_in_sync &&
+		    !interfaces->iface[i]->ready_to_start_in_sync)
+			not_ready_in_sync_ifaces++;
+	}
+
+	/*
+	 * Check if this is the last interface, if yes then start all the other
+	 * waiting interfaces. If not, add this interface to the waiting list.
+	 */
+	if (not_ready_in_sync_ifaces > 1 && iface->state == HAPD_IFACE_DFS) {
+		/*
+		 * If this interface went through CAC, do not synchronize, just
+		 * start immediately.
+		 */
+		iface->need_to_start_in_sync = 0;
+		wpa_printf(MSG_INFO,
+			   "%s: Finished CAC - bypass sync and start interface",
+			   iface->bss[0]->conf->iface);
+		return hostapd_setup_interface_complete_sync(iface, err);
+	}
+
+	if (not_ready_in_sync_ifaces > 1) {
+		/* need to wait as there are other interfaces still coming up */
+		iface->ready_to_start_in_sync = 1;
+		wpa_printf(MSG_INFO,
+			   "%s: Interface waiting to sync with other interfaces",
+			   iface->bss[0]->conf->iface);
+		return 0;
+	}
+
+	wpa_printf(MSG_INFO,
+		   "%s: Last interface to sync - starting all interfaces",
+		   iface->bss[0]->conf->iface);
+	iface->need_to_start_in_sync = 0;
+	hostapd_setup_interface_complete_sync(iface, err);
+	for (i = 0; i < interfaces->count; i++) {
+		if (interfaces->iface[i]->need_to_start_in_sync &&
+		    interfaces->iface[i]->ready_to_start_in_sync) {
+			hostapd_setup_interface_complete_sync(
+				interfaces->iface[i], 0);
+			/* Only once the interfaces are sync started */
+			interfaces->iface[i]->need_to_start_in_sync = 0;
+		}
+	}
+
+	return 0;
+}
+
+
+/**
+ * hostapd_setup_interface - Setup of an interface
+ * @iface: Pointer to interface data.
+ * Returns: 0 on success, -1 on failure
+ *
+ * Initializes the driver interface, validates the configuration,
+ * and sets driver parameters based on the configuration.
+ * Flushes old stations, sets the channel, encryption,
+ * beacons, and WDS links based on the configuration.
+ *
+ * If interface setup requires more time, e.g., to perform HT co-ex scans, ACS,
+ * or DFS operations, this function returns 0 before such operations have been
+ * completed. The pending operations are registered into eloop and will be
+ * completed from eloop callbacks. Those callbacks end up calling
+ * hostapd_setup_interface_complete() once setup has been completed.
+ */
+int hostapd_setup_interface(struct hostapd_iface *iface)
+{
+	int ret;
+
+	ret = setup_interface(iface);
+	if (ret) {
+		wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
+			   iface->bss[0]->conf->iface);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/**
+ * hostapd_alloc_bss_data - Allocate and initialize per-BSS data
+ * @hapd_iface: Pointer to interface data
+ * @conf: Pointer to per-interface configuration
+ * @bss: Pointer to per-BSS configuration for this BSS
+ * Returns: Pointer to allocated BSS data
+ *
+ * This function is used to allocate per-BSS data structure. This data will be
+ * freed after hostapd_cleanup() is called for it during interface
+ * deinitialization.
+ */
+struct hostapd_data *
+hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
+		       struct hostapd_config *conf,
+		       struct hostapd_bss_config *bss)
+{
+	struct hostapd_data *hapd;
+
+	hapd = os_zalloc(sizeof(*hapd));
+	if (hapd == NULL)
+		return NULL;
+
+	hapd->new_assoc_sta_cb = hostapd_new_assoc_sta;
+	hapd->iconf = conf;
+	hapd->conf = bss;
+	hapd->iface = hapd_iface;
+	hapd->driver = hapd->iconf->driver;
+	hapd->ctrl_sock = -1;
+	dl_list_init(&hapd->ctrl_dst);
+	dl_list_init(&hapd->nr_db);
+
+	return hapd;
+}
+
+
+static void hostapd_bss_deinit(struct hostapd_data *hapd)
+{
+	if (!hapd)
+		return;
+	wpa_printf(MSG_DEBUG, "%s: deinit bss %s", __func__,
+		   hapd->conf->iface);
+	hostapd_bss_deinit_no_free(hapd);
+	wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+	hostapd_cleanup(hapd);
+}
+
+
+void hostapd_interface_deinit(struct hostapd_iface *iface)
+{
+	int j;
+
+	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
+	if (iface == NULL)
+		return;
+
+	hostapd_set_state(iface, HAPD_IFACE_DISABLED);
+
+#ifdef CONFIG_IEEE80211N
+#ifdef NEED_AP_MLME
+	hostapd_stop_setup_timers(iface);
+	eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL);
+#endif /* NEED_AP_MLME */
+#endif /* CONFIG_IEEE80211N */
+	eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
+	iface->wait_channel_update = 0;
+
+#ifdef CONFIG_FST
+	if (iface->fst) {
+		fst_detach(iface->fst);
+		iface->fst = NULL;
+	}
+#endif /* CONFIG_FST */
+
+	for (j = iface->num_bss - 1; j >= 0; j--) {
+		if (!iface->bss)
+			break;
+		hostapd_bss_deinit(iface->bss[j]);
+	}
+}
+
+
+void hostapd_interface_free(struct hostapd_iface *iface)
+{
+	size_t j;
+	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
+	for (j = 0; j < iface->num_bss; j++) {
+		if (!iface->bss)
+			break;
+		wpa_printf(MSG_DEBUG, "%s: free hapd %p",
+			   __func__, iface->bss[j]);
+		os_free(iface->bss[j]);
+	}
+	hostapd_cleanup_iface(iface);
+}
+
+
+struct hostapd_iface * hostapd_alloc_iface(void)
+{
+	struct hostapd_iface *hapd_iface;
+
+	hapd_iface = os_zalloc(sizeof(*hapd_iface));
+	if (!hapd_iface)
+		return NULL;
+
+	dl_list_init(&hapd_iface->sta_seen);
+
+	return hapd_iface;
+}
+
+
+/**
+ * hostapd_init - Allocate and initialize per-interface data
+ * @config_file: Path to the configuration file
+ * Returns: Pointer to the allocated interface data or %NULL on failure
+ *
+ * This function is used to allocate main data structures for per-interface
+ * data. The allocated data buffer will be freed by calling
+ * hostapd_cleanup_iface().
+ */
+struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
+				    const char *config_file)
+{
+	struct hostapd_iface *hapd_iface = NULL;
+	struct hostapd_config *conf = NULL;
+	struct hostapd_data *hapd;
+	size_t i;
+
+	hapd_iface = hostapd_alloc_iface();
+	if (hapd_iface == NULL)
+		goto fail;
+
+	hapd_iface->config_fname = os_strdup(config_file);
+	if (hapd_iface->config_fname == NULL)
+		goto fail;
+
+	conf = interfaces->config_read_cb(hapd_iface->config_fname);
+	if (conf == NULL)
+		goto fail;
+	hapd_iface->conf = conf;
+
+	hapd_iface->num_bss = conf->num_bss;
+	hapd_iface->bss = os_calloc(conf->num_bss,
+				    sizeof(struct hostapd_data *));
+	if (hapd_iface->bss == NULL)
+		goto fail;
+
+	for (i = 0; i < conf->num_bss; i++) {
+		hapd = hapd_iface->bss[i] =
+			hostapd_alloc_bss_data(hapd_iface, conf,
+					       conf->bss[i]);
+		if (hapd == NULL)
+			goto fail;
+		hapd->msg_ctx = hapd;
+	}
+
+	return hapd_iface;
+
+fail:
+	wpa_printf(MSG_ERROR, "Failed to set up interface with %s",
+		   config_file);
+	if (conf)
+		hostapd_config_free(conf);
+	if (hapd_iface) {
+		os_free(hapd_iface->config_fname);
+		os_free(hapd_iface->bss);
+		wpa_printf(MSG_DEBUG, "%s: free iface %p",
+			   __func__, hapd_iface);
+		os_free(hapd_iface);
+	}
+	return NULL;
+}
+
+
+static int ifname_in_use(struct hapd_interfaces *interfaces, const char *ifname)
+{
+	size_t i, j;
+
+	for (i = 0; i < interfaces->count; i++) {
+		struct hostapd_iface *iface = interfaces->iface[i];
+		for (j = 0; j < iface->num_bss; j++) {
+			struct hostapd_data *hapd = iface->bss[j];
+			if (os_strcmp(ifname, hapd->conf->iface) == 0)
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+
+/**
+ * hostapd_interface_init_bss - Read configuration file and init BSS data
+ *
+ * This function is used to parse configuration file for a BSS. This BSS is
+ * added to an existing interface sharing the same radio (if any) or a new
+ * interface is created if this is the first interface on a radio. This
+ * allocate memory for the BSS. No actual driver operations are started.
+ *
+ * This is similar to hostapd_interface_init(), but for a case where the
+ * configuration is used to add a single BSS instead of all BSSes for a radio.
+ */
+struct hostapd_iface *
+hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
+			   const char *config_fname, int debug)
+{
+	struct hostapd_iface *new_iface = NULL, *iface = NULL;
+	struct hostapd_data *hapd;
+	int k;
+	size_t i, bss_idx;
+
+	if (!phy || !*phy)
+		return NULL;
+
+	for (i = 0; i < interfaces->count; i++) {
+		if (os_strcmp(interfaces->iface[i]->phy, phy) == 0) {
+			iface = interfaces->iface[i];
+			break;
+		}
+	}
+
+	wpa_printf(MSG_INFO, "Configuration file: %s (phy %s)%s",
+		   config_fname, phy, iface ? "" : " --> new PHY");
+	if (iface) {
+		struct hostapd_config *conf;
+		struct hostapd_bss_config **tmp_conf;
+		struct hostapd_data **tmp_bss;
+		struct hostapd_bss_config *bss;
+		const char *ifname;
+
+		/* Add new BSS to existing iface */
+		conf = interfaces->config_read_cb(config_fname);
+		if (conf == NULL)
+			return NULL;
+		if (conf->num_bss > 1) {
+			wpa_printf(MSG_ERROR, "Multiple BSSes specified in BSS-config");
+			hostapd_config_free(conf);
+			return NULL;
+		}
+
+		ifname = conf->bss[0]->iface;
+		if (ifname[0] != '\0' && ifname_in_use(interfaces, ifname)) {
+			wpa_printf(MSG_ERROR,
+				   "Interface name %s already in use", ifname);
+			hostapd_config_free(conf);
+			return NULL;
+		}
+
+		tmp_conf = os_realloc_array(
+			iface->conf->bss, iface->conf->num_bss + 1,
+			sizeof(struct hostapd_bss_config *));
+		tmp_bss = os_realloc_array(iface->bss, iface->num_bss + 1,
+					   sizeof(struct hostapd_data *));
+		if (tmp_bss)
+			iface->bss = tmp_bss;
+		if (tmp_conf) {
+			iface->conf->bss = tmp_conf;
+			iface->conf->last_bss = tmp_conf[0];
+		}
+		if (tmp_bss == NULL || tmp_conf == NULL) {
+			hostapd_config_free(conf);
+			return NULL;
+		}
+		bss = iface->conf->bss[iface->conf->num_bss] = conf->bss[0];
+		iface->conf->num_bss++;
+
+		hapd = hostapd_alloc_bss_data(iface, iface->conf, bss);
+		if (hapd == NULL) {
+			iface->conf->num_bss--;
+			hostapd_config_free(conf);
+			return NULL;
+		}
+		iface->conf->last_bss = bss;
+		iface->bss[iface->num_bss] = hapd;
+		hapd->msg_ctx = hapd;
+
+		bss_idx = iface->num_bss++;
+		conf->num_bss--;
+		conf->bss[0] = NULL;
+		hostapd_config_free(conf);
+	} else {
+		/* Add a new iface with the first BSS */
+		new_iface = iface = hostapd_init(interfaces, config_fname);
+		if (!iface)
+			return NULL;
+		os_strlcpy(iface->phy, phy, sizeof(iface->phy));
+		iface->interfaces = interfaces;
+		bss_idx = 0;
+	}
+
+	for (k = 0; k < debug; k++) {
+		if (iface->bss[bss_idx]->conf->logger_stdout_level > 0)
+			iface->bss[bss_idx]->conf->logger_stdout_level--;
+	}
+
+	if (iface->conf->bss[bss_idx]->iface[0] == '\0' &&
+	    !hostapd_drv_none(iface->bss[bss_idx])) {
+		wpa_printf(MSG_ERROR, "Interface name not specified in %s",
+			   config_fname);
+		if (new_iface)
+			hostapd_interface_deinit_free(new_iface);
+		return NULL;
+	}
+
+	return iface;
+}
+
+
+void hostapd_interface_deinit_free(struct hostapd_iface *iface)
+{
+	const struct wpa_driver_ops *driver;
+	void *drv_priv;
+
+	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
+	if (iface == NULL)
+		return;
+	wpa_printf(MSG_DEBUG, "%s: num_bss=%u conf->num_bss=%u",
+		   __func__, (unsigned int) iface->num_bss,
+		   (unsigned int) iface->conf->num_bss);
+	driver = iface->bss[0]->driver;
+	drv_priv = iface->bss[0]->drv_priv;
+	hostapd_interface_deinit(iface);
+	wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
+		   __func__, driver, drv_priv);
+	if (driver && driver->hapd_deinit && drv_priv) {
+		driver->hapd_deinit(drv_priv);
+		iface->bss[0]->drv_priv = NULL;
+	}
+	hostapd_interface_free(iface);
+}
+
+
+static void hostapd_deinit_driver(const struct wpa_driver_ops *driver,
+				  void *drv_priv,
+				  struct hostapd_iface *hapd_iface)
+{
+	size_t j;
+
+	wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
+		   __func__, driver, drv_priv);
+	if (driver && driver->hapd_deinit && drv_priv) {
+		driver->hapd_deinit(drv_priv);
+		for (j = 0; j < hapd_iface->num_bss; j++) {
+			wpa_printf(MSG_DEBUG, "%s:bss[%d]->drv_priv=%p",
+				   __func__, (int) j,
+				   hapd_iface->bss[j]->drv_priv);
+			if (hapd_iface->bss[j]->drv_priv == drv_priv)
+				hapd_iface->bss[j]->drv_priv = NULL;
+		}
+	}
+}
+
+
+int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
+{
+	size_t j;
+
+	if (hapd_iface->bss[0]->drv_priv != NULL) {
+		wpa_printf(MSG_ERROR, "Interface %s already enabled",
+			   hapd_iface->conf->bss[0]->iface);
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "Enable interface %s",
+		   hapd_iface->conf->bss[0]->iface);
+
+	for (j = 0; j < hapd_iface->num_bss; j++)
+		hostapd_set_security_params(hapd_iface->conf->bss[j], 1);
+	if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
+		wpa_printf(MSG_INFO, "Invalid configuration - cannot enable");
+		return -1;
+	}
+
+	if (hapd_iface->interfaces == NULL ||
+	    hapd_iface->interfaces->driver_init == NULL ||
+	    hapd_iface->interfaces->driver_init(hapd_iface))
+		return -1;
+
+	if (hostapd_setup_interface(hapd_iface)) {
+		hostapd_deinit_driver(hapd_iface->bss[0]->driver,
+				      hapd_iface->bss[0]->drv_priv,
+				      hapd_iface);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int hostapd_reload_iface(struct hostapd_iface *hapd_iface)
+{
+	size_t j;
+
+	wpa_printf(MSG_DEBUG, "Reload interface %s",
+		   hapd_iface->conf->bss[0]->iface);
+	for (j = 0; j < hapd_iface->num_bss; j++)
+		hostapd_set_security_params(hapd_iface->conf->bss[j], 1);
+	if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
+		wpa_printf(MSG_ERROR, "Updated configuration is invalid");
+		return -1;
+	}
+	hostapd_clear_old(hapd_iface);
+	for (j = 0; j < hapd_iface->num_bss; j++)
+		hostapd_reload_bss(hapd_iface->bss[j]);
+
+	return 0;
+}
+
+
+int hostapd_disable_iface(struct hostapd_iface *hapd_iface)
+{
+	size_t j;
+	const struct wpa_driver_ops *driver;
+	void *drv_priv;
+
+	if (hapd_iface == NULL)
+		return -1;
+
+	if (hapd_iface->bss[0]->drv_priv == NULL) {
+		wpa_printf(MSG_INFO, "Interface %s already disabled",
+			   hapd_iface->conf->bss[0]->iface);
+		return -1;
+	}
+
+	wpa_msg(hapd_iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
+	driver = hapd_iface->bss[0]->driver;
+	drv_priv = hapd_iface->bss[0]->drv_priv;
+
+	hapd_iface->driver_ap_teardown =
+		!!(hapd_iface->drv_flags &
+		   WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
+
+	/* same as hostapd_interface_deinit without deinitializing ctrl-iface */
+	for (j = 0; j < hapd_iface->num_bss; j++) {
+		struct hostapd_data *hapd = hapd_iface->bss[j];
+		hostapd_bss_deinit_no_free(hapd);
+		hostapd_free_hapd_data(hapd);
+	}
+
+	hostapd_deinit_driver(driver, drv_priv, hapd_iface);
+
+	/* From hostapd_cleanup_iface: These were initialized in
+	 * hostapd_setup_interface and hostapd_setup_interface_complete
+	 */
+	hostapd_cleanup_iface_partial(hapd_iface);
+
+	wpa_printf(MSG_DEBUG, "Interface %s disabled",
+		   hapd_iface->bss[0]->conf->iface);
+	hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED);
+	return 0;
+}
+
+
+static struct hostapd_iface *
+hostapd_iface_alloc(struct hapd_interfaces *interfaces)
+{
+	struct hostapd_iface **iface, *hapd_iface;
+
+	iface = os_realloc_array(interfaces->iface, interfaces->count + 1,
+				 sizeof(struct hostapd_iface *));
+	if (iface == NULL)
+		return NULL;
+	interfaces->iface = iface;
+	hapd_iface = interfaces->iface[interfaces->count] =
+		hostapd_alloc_iface();
+	if (hapd_iface == NULL) {
+		wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
+			   "the interface", __func__);
+		return NULL;
+	}
+	interfaces->count++;
+	hapd_iface->interfaces = interfaces;
+
+	return hapd_iface;
+}
+
+
+static struct hostapd_config *
+hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname,
+		     const char *ctrl_iface, const char *driver)
+{
+	struct hostapd_bss_config *bss;
+	struct hostapd_config *conf;
+
+	/* Allocates memory for bss and conf */
+	conf = hostapd_config_defaults();
+	if (conf == NULL) {
+		 wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
+				"configuration", __func__);
+		return NULL;
+	}
+
+	if (driver) {
+		int j;
+
+		for (j = 0; wpa_drivers[j]; j++) {
+			if (os_strcmp(driver, wpa_drivers[j]->name) == 0) {
+				conf->driver = wpa_drivers[j];
+				goto skip;
+			}
+		}
+
+		wpa_printf(MSG_ERROR,
+			   "Invalid/unknown driver '%s' - registering the default driver",
+			   driver);
+	}
+
+	conf->driver = wpa_drivers[0];
+	if (conf->driver == NULL) {
+		wpa_printf(MSG_ERROR, "No driver wrappers registered!");
+		hostapd_config_free(conf);
+		return NULL;
+	}
+
+skip:
+	bss = conf->last_bss = conf->bss[0];
+
+	os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
+	bss->ctrl_interface = os_strdup(ctrl_iface);
+	if (bss->ctrl_interface == NULL) {
+		hostapd_config_free(conf);
+		return NULL;
+	}
+
+	/* Reading configuration file skipped, will be done in SET!
+	 * From reading the configuration till the end has to be done in
+	 * SET
+	 */
+	return conf;
+}
+
+
+static int hostapd_data_alloc(struct hostapd_iface *hapd_iface,
+			      struct hostapd_config *conf)
+{
+	size_t i;
+	struct hostapd_data *hapd;
+
+	hapd_iface->bss = os_calloc(conf->num_bss,
+				    sizeof(struct hostapd_data *));
+	if (hapd_iface->bss == NULL)
+		return -1;
+
+	for (i = 0; i < conf->num_bss; i++) {
+		hapd = hapd_iface->bss[i] =
+			hostapd_alloc_bss_data(hapd_iface, conf, conf->bss[i]);
+		if (hapd == NULL) {
+			while (i > 0) {
+				i--;
+				os_free(hapd_iface->bss[i]);
+				hapd_iface->bss[i] = NULL;
+			}
+			os_free(hapd_iface->bss);
+			hapd_iface->bss = NULL;
+			return -1;
+		}
+		hapd->msg_ctx = hapd;
+	}
+
+	hapd_iface->conf = conf;
+	hapd_iface->num_bss = conf->num_bss;
+
+	return 0;
+}
+
+
+int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
+{
+	struct hostapd_config *conf = NULL;
+	struct hostapd_iface *hapd_iface = NULL, *new_iface = NULL;
+	struct hostapd_data *hapd;
+	char *ptr;
+	size_t i, j;
+	const char *conf_file = NULL, *phy_name = NULL;
+
+	if (os_strncmp(buf, "bss_config=", 11) == 0) {
+		char *pos;
+		phy_name = buf + 11;
+		pos = os_strchr(phy_name, ':');
+		if (!pos)
+			return -1;
+		*pos++ = '\0';
+		conf_file = pos;
+		if (!os_strlen(conf_file))
+			return -1;
+
+		hapd_iface = hostapd_interface_init_bss(interfaces, phy_name,
+							conf_file, 0);
+		if (!hapd_iface)
+			return -1;
+		for (j = 0; j < interfaces->count; j++) {
+			if (interfaces->iface[j] == hapd_iface)
+				break;
+		}
+		if (j == interfaces->count) {
+			struct hostapd_iface **tmp;
+			tmp = os_realloc_array(interfaces->iface,
+					       interfaces->count + 1,
+					       sizeof(struct hostapd_iface *));
+			if (!tmp) {
+				hostapd_interface_deinit_free(hapd_iface);
+				return -1;
+			}
+			interfaces->iface = tmp;
+			interfaces->iface[interfaces->count++] = hapd_iface;
+			new_iface = hapd_iface;
+		}
+
+		if (new_iface) {
+			if (interfaces->driver_init(hapd_iface))
+				goto fail;
+
+			if (hostapd_setup_interface(hapd_iface)) {
+				hostapd_deinit_driver(
+					hapd_iface->bss[0]->driver,
+					hapd_iface->bss[0]->drv_priv,
+					hapd_iface);
+				goto fail;
+			}
+		} else {
+			/* Assign new BSS with bss[0]'s driver info */
+			hapd = hapd_iface->bss[hapd_iface->num_bss - 1];
+			hapd->driver = hapd_iface->bss[0]->driver;
+			hapd->drv_priv = hapd_iface->bss[0]->drv_priv;
+			os_memcpy(hapd->own_addr, hapd_iface->bss[0]->own_addr,
+				  ETH_ALEN);
+
+			if (start_ctrl_iface_bss(hapd) < 0 ||
+			    (hapd_iface->state == HAPD_IFACE_ENABLED &&
+			     hostapd_setup_bss(hapd, -1))) {
+				hostapd_cleanup(hapd);
+				hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
+				hapd_iface->conf->num_bss--;
+				hapd_iface->num_bss--;
+				wpa_printf(MSG_DEBUG, "%s: free hapd %p %s",
+					   __func__, hapd, hapd->conf->iface);
+				hostapd_config_free_bss(hapd->conf);
+				hapd->conf = NULL;
+				os_free(hapd);
+				return -1;
+			}
+		}
+		return 0;
+	}
+
+	ptr = os_strchr(buf, ' ');
+	if (ptr == NULL)
+		return -1;
+	*ptr++ = '\0';
+
+	if (os_strncmp(ptr, "config=", 7) == 0)
+		conf_file = ptr + 7;
+
+	for (i = 0; i < interfaces->count; i++) {
+		if (!os_strcmp(interfaces->iface[i]->conf->bss[0]->iface,
+			       buf)) {
+			wpa_printf(MSG_INFO, "Cannot add interface - it "
+				   "already exists");
+			return -1;
+		}
+	}
+
+	hapd_iface = hostapd_iface_alloc(interfaces);
+	if (hapd_iface == NULL) {
+		wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
+			   "for interface", __func__);
+		goto fail;
+	}
+	new_iface = hapd_iface;
+
+	if (conf_file && interfaces->config_read_cb) {
+		conf = interfaces->config_read_cb(conf_file);
+		if (conf && conf->bss)
+			os_strlcpy(conf->bss[0]->iface, buf,
+				   sizeof(conf->bss[0]->iface));
+	} else {
+		char *driver = os_strchr(ptr, ' ');
+
+		if (driver)
+			*driver++ = '\0';
+		conf = hostapd_config_alloc(interfaces, buf, ptr, driver);
+	}
+
+	if (conf == NULL || conf->bss == NULL) {
+		wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
+			   "for configuration", __func__);
+		goto fail;
+	}
+
+	if (hostapd_data_alloc(hapd_iface, conf) < 0) {
+		wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
+			   "for hostapd", __func__);
+		goto fail;
+	}
+	conf = NULL;
+
+	if (start_ctrl_iface(hapd_iface) < 0)
+		goto fail;
+
+	wpa_printf(MSG_INFO, "Add interface '%s'",
+		   hapd_iface->conf->bss[0]->iface);
+
+	return 0;
+
+fail:
+	if (conf)
+		hostapd_config_free(conf);
+	if (hapd_iface) {
+		if (hapd_iface->bss) {
+			for (i = 0; i < hapd_iface->num_bss; i++) {
+				hapd = hapd_iface->bss[i];
+				if (!hapd)
+					continue;
+				if (hapd_iface->interfaces &&
+				    hapd_iface->interfaces->ctrl_iface_deinit)
+					hapd_iface->interfaces->
+						ctrl_iface_deinit(hapd);
+				wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
+					   __func__, hapd_iface->bss[i],
+					   hapd->conf->iface);
+				hostapd_cleanup(hapd);
+				os_free(hapd);
+				hapd_iface->bss[i] = NULL;
+			}
+			os_free(hapd_iface->bss);
+			hapd_iface->bss = NULL;
+		}
+		if (new_iface) {
+			interfaces->count--;
+			interfaces->iface[interfaces->count] = NULL;
+		}
+		hostapd_cleanup_iface(hapd_iface);
+	}
+	return -1;
+}
+
+
+static int hostapd_remove_bss(struct hostapd_iface *iface, unsigned int idx)
+{
+	size_t i;
+
+	wpa_printf(MSG_INFO, "Remove BSS '%s'", iface->conf->bss[idx]->iface);
+
+	/* Remove hostapd_data only if it has already been initialized */
+	if (idx < iface->num_bss) {
+		struct hostapd_data *hapd = iface->bss[idx];
+
+		hostapd_bss_deinit(hapd);
+		wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
+			   __func__, hapd, hapd->conf->iface);
+		hostapd_config_free_bss(hapd->conf);
+		hapd->conf = NULL;
+		os_free(hapd);
+
+		iface->num_bss--;
+
+		for (i = idx; i < iface->num_bss; i++)
+			iface->bss[i] = iface->bss[i + 1];
+	} else {
+		hostapd_config_free_bss(iface->conf->bss[idx]);
+		iface->conf->bss[idx] = NULL;
+	}
+
+	iface->conf->num_bss--;
+	for (i = idx; i < iface->conf->num_bss; i++)
+		iface->conf->bss[i] = iface->conf->bss[i + 1];
+
+	return 0;
+}
+
+
+int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
+{
+	struct hostapd_iface *hapd_iface;
+	size_t i, j, k = 0;
+
+	for (i = 0; i < interfaces->count; i++) {
+		hapd_iface = interfaces->iface[i];
+		if (hapd_iface == NULL)
+			return -1;
+		if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
+			wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
+			hapd_iface->driver_ap_teardown =
+				!!(hapd_iface->drv_flags &
+				   WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
+
+			hostapd_interface_deinit_free(hapd_iface);
+			k = i;
+			while (k < (interfaces->count - 1)) {
+				interfaces->iface[k] =
+					interfaces->iface[k + 1];
+				k++;
+			}
+			interfaces->count--;
+			return 0;
+		}
+
+		for (j = 0; j < hapd_iface->conf->num_bss; j++) {
+			if (!os_strcmp(hapd_iface->conf->bss[j]->iface, buf)) {
+				hapd_iface->driver_ap_teardown =
+					!(hapd_iface->drv_flags &
+					  WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
+				return hostapd_remove_bss(hapd_iface, j);
+			}
+		}
+	}
+	return -1;
+}
+
+
+/**
+ * hostapd_new_assoc_sta - Notify that a new station associated with the AP
+ * @hapd: Pointer to BSS data
+ * @sta: Pointer to the associated STA data
+ * @reassoc: 1 to indicate this was a re-association; 0 = first association
+ *
+ * This function will be called whenever a station associates with the AP. It
+ * can be called from ieee802_11.c for drivers that export MLME to hostapd and
+ * from drv_callbacks.c based on driver events for drivers that take care of
+ * management frames (IEEE 802.11 authentication and association) internally.
+ */
+void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
+			   int reassoc)
+{
+	if (hapd->tkip_countermeasures) {
+		hostapd_drv_sta_deauth(hapd, sta->addr,
+				       WLAN_REASON_MICHAEL_MIC_FAILURE);
+		return;
+	}
+
+	hostapd_prune_associations(hapd, sta->addr);
+	ap_sta_clear_disconnect_timeouts(hapd, sta);
+
+	/* IEEE 802.11F (IAPP) */
+	if (hapd->conf->ieee802_11f)
+		iapp_new_station(hapd->iapp, sta);
+
+#ifdef CONFIG_P2P
+	if (sta->p2p_ie == NULL && !sta->no_p2p_set) {
+		sta->no_p2p_set = 1;
+		hapd->num_sta_no_p2p++;
+		if (hapd->num_sta_no_p2p == 1)
+			hostapd_p2p_non_p2p_sta_connected(hapd);
+	}
+#endif /* CONFIG_P2P */
+
+	/* Start accounting here, if IEEE 802.1X and WPA are not used.
+	 * IEEE 802.1X/WPA code will start accounting after the station has
+	 * been authorized. */
+	if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen) {
+		ap_sta_set_authorized(hapd, sta, 1);
+		os_get_reltime(&sta->connected_time);
+		accounting_sta_start(hapd, sta);
+	}
+
+	/* Start IEEE 802.1X authentication process for new stations */
+	ieee802_1x_new_station(hapd, sta);
+	if (reassoc) {
+		if (sta->auth_alg != WLAN_AUTH_FT &&
+		    !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
+			wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
+	} else
+		wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
+
+	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) {
+		wpa_printf(MSG_DEBUG,
+			   "%s: %s: reschedule ap_handle_timer timeout for "
+			   MACSTR " (%d seconds - ap_max_inactivity)",
+			   hapd->conf->iface, __func__, MAC2STR(sta->addr),
+			   hapd->conf->ap_max_inactivity);
+		eloop_cancel_timeout(ap_handle_timer, hapd, sta);
+		eloop_register_timeout(hapd->conf->ap_max_inactivity, 0,
+				       ap_handle_timer, hapd, sta);
+	}
+}
+
+
+const char * hostapd_state_text(enum hostapd_iface_state s)
+{
+	switch (s) {
+	case HAPD_IFACE_UNINITIALIZED:
+		return "UNINITIALIZED";
+	case HAPD_IFACE_DISABLED:
+		return "DISABLED";
+	case HAPD_IFACE_COUNTRY_UPDATE:
+		return "COUNTRY_UPDATE";
+	case HAPD_IFACE_ACS:
+		return "ACS";
+	case HAPD_IFACE_HT_SCAN:
+		return "HT_SCAN";
+	case HAPD_IFACE_DFS:
+		return "DFS";
+	case HAPD_IFACE_ENABLED:
+		return "ENABLED";
+	}
+
+	return "UNKNOWN";
+}
+
+
+void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s)
+{
+	wpa_printf(MSG_INFO, "%s: interface state %s->%s",
+		   iface->conf ? iface->conf->bss[0]->iface : "N/A",
+		   hostapd_state_text(iface->state), hostapd_state_text(s));
+	iface->state = s;
+}
+
+
+int hostapd_csa_in_progress(struct hostapd_iface *iface)
+{
+	unsigned int i;
+
+	for (i = 0; i < iface->num_bss; i++)
+		if (iface->bss[i]->csa_in_progress)
+			return 1;
+	return 0;
+}
+
+
+#ifdef NEED_AP_MLME
+
+static void free_beacon_data(struct beacon_data *beacon)
+{
+	os_free(beacon->head);
+	beacon->head = NULL;
+	os_free(beacon->tail);
+	beacon->tail = NULL;
+	os_free(beacon->probe_resp);
+	beacon->probe_resp = NULL;
+	os_free(beacon->beacon_ies);
+	beacon->beacon_ies = NULL;
+	os_free(beacon->proberesp_ies);
+	beacon->proberesp_ies = NULL;
+	os_free(beacon->assocresp_ies);
+	beacon->assocresp_ies = NULL;
+}
+
+
+static int hostapd_build_beacon_data(struct hostapd_data *hapd,
+				     struct beacon_data *beacon)
+{
+	struct wpabuf *beacon_extra, *proberesp_extra, *assocresp_extra;
+	struct wpa_driver_ap_params params;
+	int ret;
+
+	os_memset(beacon, 0, sizeof(*beacon));
+	ret = ieee802_11_build_ap_params(hapd, &params);
+	if (ret < 0)
+		return ret;
+
+	ret = hostapd_build_ap_extra_ies(hapd, &beacon_extra,
+					 &proberesp_extra,
+					 &assocresp_extra);
+	if (ret)
+		goto free_ap_params;
+
+	ret = -1;
+	beacon->head = os_malloc(params.head_len);
+	if (!beacon->head)
+		goto free_ap_extra_ies;
+
+	os_memcpy(beacon->head, params.head, params.head_len);
+	beacon->head_len = params.head_len;
+
+	beacon->tail = os_malloc(params.tail_len);
+	if (!beacon->tail)
+		goto free_beacon;
+
+	os_memcpy(beacon->tail, params.tail, params.tail_len);
+	beacon->tail_len = params.tail_len;
+
+	if (params.proberesp != NULL) {
+		beacon->probe_resp = os_malloc(params.proberesp_len);
+		if (!beacon->probe_resp)
+			goto free_beacon;
+
+		os_memcpy(beacon->probe_resp, params.proberesp,
+			  params.proberesp_len);
+		beacon->probe_resp_len = params.proberesp_len;
+	}
+
+	/* copy the extra ies */
+	if (beacon_extra) {
+		beacon->beacon_ies = os_malloc(wpabuf_len(beacon_extra));
+		if (!beacon->beacon_ies)
+			goto free_beacon;
+
+		os_memcpy(beacon->beacon_ies,
+			  beacon_extra->buf, wpabuf_len(beacon_extra));
+		beacon->beacon_ies_len = wpabuf_len(beacon_extra);
+	}
+
+	if (proberesp_extra) {
+		beacon->proberesp_ies =
+			os_malloc(wpabuf_len(proberesp_extra));
+		if (!beacon->proberesp_ies)
+			goto free_beacon;
+
+		os_memcpy(beacon->proberesp_ies, proberesp_extra->buf,
+			  wpabuf_len(proberesp_extra));
+		beacon->proberesp_ies_len = wpabuf_len(proberesp_extra);
+	}
+
+	if (assocresp_extra) {
+		beacon->assocresp_ies =
+			os_malloc(wpabuf_len(assocresp_extra));
+		if (!beacon->assocresp_ies)
+			goto free_beacon;
+
+		os_memcpy(beacon->assocresp_ies, assocresp_extra->buf,
+			  wpabuf_len(assocresp_extra));
+		beacon->assocresp_ies_len = wpabuf_len(assocresp_extra);
+	}
+
+	ret = 0;
+free_beacon:
+	/* if the function fails, the caller should not free beacon data */
+	if (ret)
+		free_beacon_data(beacon);
+
+free_ap_extra_ies:
+	hostapd_free_ap_extra_ies(hapd, beacon_extra, proberesp_extra,
+				  assocresp_extra);
+free_ap_params:
+	ieee802_11_free_ap_params(&params);
+	return ret;
+}
+
+
+/*
+ * TODO: This flow currently supports only changing channel and width within
+ * the same hw_mode. Any other changes to MAC parameters or provided settings
+ * are not supported.
+ */
+static int hostapd_change_config_freq(struct hostapd_data *hapd,
+				      struct hostapd_config *conf,
+				      struct hostapd_freq_params *params,
+				      struct hostapd_freq_params *old_params)
+{
+	int channel;
+
+	if (!params->channel) {
+		/* check if the new channel is supported by hw */
+		params->channel = hostapd_hw_get_channel(hapd, params->freq);
+	}
+
+	channel = params->channel;
+	if (!channel)
+		return -1;
+
+	/* if a pointer to old_params is provided we save previous state */
+	if (old_params &&
+	    hostapd_set_freq_params(old_params, conf->hw_mode,
+				    hostapd_hw_get_freq(hapd, conf->channel),
+				    conf->channel, conf->ieee80211n,
+				    conf->ieee80211ac,
+				    conf->secondary_channel,
+				    conf->vht_oper_chwidth,
+				    conf->vht_oper_centr_freq_seg0_idx,
+				    conf->vht_oper_centr_freq_seg1_idx,
+				    conf->vht_capab))
+		return -1;
+
+	switch (params->bandwidth) {
+	case 0:
+	case 20:
+	case 40:
+		conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
+		break;
+	case 80:
+		if (params->center_freq2)
+			conf->vht_oper_chwidth = VHT_CHANWIDTH_80P80MHZ;
+		else
+			conf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
+		break;
+	case 160:
+		conf->vht_oper_chwidth = VHT_CHANWIDTH_160MHZ;
+		break;
+	default:
+		return -1;
+	}
+
+	conf->channel = channel;
+	conf->ieee80211n = params->ht_enabled;
+	conf->secondary_channel = params->sec_channel_offset;
+	ieee80211_freq_to_chan(params->center_freq1,
+			       &conf->vht_oper_centr_freq_seg0_idx);
+	ieee80211_freq_to_chan(params->center_freq2,
+			       &conf->vht_oper_centr_freq_seg1_idx);
+
+	/* TODO: maybe call here hostapd_config_check here? */
+
+	return 0;
+}
+
+
+static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
+				     struct csa_settings *settings)
+{
+	struct hostapd_iface *iface = hapd->iface;
+	struct hostapd_freq_params old_freq;
+	int ret;
+	u8 chan, vht_bandwidth;
+
+	os_memset(&old_freq, 0, sizeof(old_freq));
+	if (!iface || !iface->freq || hapd->csa_in_progress)
+		return -1;
+
+	switch (settings->freq_params.bandwidth) {
+	case 80:
+		if (settings->freq_params.center_freq2)
+			vht_bandwidth = VHT_CHANWIDTH_80P80MHZ;
+		else
+			vht_bandwidth = VHT_CHANWIDTH_80MHZ;
+		break;
+	case 160:
+		vht_bandwidth = VHT_CHANWIDTH_160MHZ;
+		break;
+	default:
+		vht_bandwidth = VHT_CHANWIDTH_USE_HT;
+		break;
+	}
+
+	if (ieee80211_freq_to_channel_ext(
+		    settings->freq_params.freq,
+		    settings->freq_params.sec_channel_offset,
+		    vht_bandwidth,
+		    &hapd->iface->cs_oper_class,
+		    &chan) == NUM_HOSTAPD_MODES) {
+		wpa_printf(MSG_DEBUG,
+			   "invalid frequency for channel switch (freq=%d, sec_channel_offset=%d, vht_enabled=%d)",
+			   settings->freq_params.freq,
+			   settings->freq_params.sec_channel_offset,
+			   settings->freq_params.vht_enabled);
+		return -1;
+	}
+
+	settings->freq_params.channel = chan;
+
+	ret = hostapd_change_config_freq(iface->bss[0], iface->conf,
+					 &settings->freq_params,
+					 &old_freq);
+	if (ret)
+		return ret;
+
+	ret = hostapd_build_beacon_data(hapd, &settings->beacon_after);
+
+	/* change back the configuration */
+	hostapd_change_config_freq(iface->bss[0], iface->conf,
+				   &old_freq, NULL);
+
+	if (ret)
+		return ret;
+
+	/* set channel switch parameters for csa ie */
+	hapd->cs_freq_params = settings->freq_params;
+	hapd->cs_count = settings->cs_count;
+	hapd->cs_block_tx = settings->block_tx;
+
+	ret = hostapd_build_beacon_data(hapd, &settings->beacon_csa);
+	if (ret) {
+		free_beacon_data(&settings->beacon_after);
+		return ret;
+	}
+
+	settings->counter_offset_beacon[0] = hapd->cs_c_off_beacon;
+	settings->counter_offset_presp[0] = hapd->cs_c_off_proberesp;
+	settings->counter_offset_beacon[1] = hapd->cs_c_off_ecsa_beacon;
+	settings->counter_offset_presp[1] = hapd->cs_c_off_ecsa_proberesp;
+
+	return 0;
+}
+
+
+void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
+{
+	os_memset(&hapd->cs_freq_params, 0, sizeof(hapd->cs_freq_params));
+	hapd->cs_count = 0;
+	hapd->cs_block_tx = 0;
+	hapd->cs_c_off_beacon = 0;
+	hapd->cs_c_off_proberesp = 0;
+	hapd->csa_in_progress = 0;
+	hapd->cs_c_off_ecsa_beacon = 0;
+	hapd->cs_c_off_ecsa_proberesp = 0;
+}
+
+
+int hostapd_switch_channel(struct hostapd_data *hapd,
+			   struct csa_settings *settings)
+{
+	int ret;
+
+	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)) {
+		wpa_printf(MSG_INFO, "CSA is not supported");
+		return -1;
+	}
+
+	ret = hostapd_fill_csa_settings(hapd, settings);
+	if (ret)
+		return ret;
+
+	ret = hostapd_drv_switch_channel(hapd, settings);
+	free_beacon_data(&settings->beacon_csa);
+	free_beacon_data(&settings->beacon_after);
+
+	if (ret) {
+		/* if we failed, clean cs parameters */
+		hostapd_cleanup_cs_params(hapd);
+		return ret;
+	}
+
+	hapd->csa_in_progress = 1;
+	return 0;
+}
+
+
+void
+hostapd_switch_channel_fallback(struct hostapd_iface *iface,
+				const struct hostapd_freq_params *freq_params)
+{
+	int vht_seg0_idx = 0, vht_seg1_idx = 0, vht_bw = VHT_CHANWIDTH_USE_HT;
+	unsigned int i;
+
+	wpa_printf(MSG_DEBUG, "Restarting all CSA-related BSSes");
+
+	if (freq_params->center_freq1)
+		vht_seg0_idx = 36 + (freq_params->center_freq1 - 5180) / 5;
+	if (freq_params->center_freq2)
+		vht_seg1_idx = 36 + (freq_params->center_freq2 - 5180) / 5;
+
+	switch (freq_params->bandwidth) {
+	case 0:
+	case 20:
+	case 40:
+		vht_bw = VHT_CHANWIDTH_USE_HT;
+		break;
+	case 80:
+		if (freq_params->center_freq2)
+			vht_bw = VHT_CHANWIDTH_80P80MHZ;
+		else
+			vht_bw = VHT_CHANWIDTH_80MHZ;
+		break;
+	case 160:
+		vht_bw = VHT_CHANWIDTH_160MHZ;
+		break;
+	default:
+		wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d",
+			   freq_params->bandwidth);
+		break;
+	}
+
+	iface->freq = freq_params->freq;
+	iface->conf->channel = freq_params->channel;
+	iface->conf->secondary_channel = freq_params->sec_channel_offset;
+	iface->conf->vht_oper_centr_freq_seg0_idx = vht_seg0_idx;
+	iface->conf->vht_oper_centr_freq_seg1_idx = vht_seg1_idx;
+	iface->conf->vht_oper_chwidth = vht_bw;
+	iface->conf->ieee80211n = freq_params->ht_enabled;
+	iface->conf->ieee80211ac = freq_params->vht_enabled;
+
+	/*
+	 * cs_params must not be cleared earlier because the freq_params
+	 * argument may actually point to one of these.
+	 */
+	for (i = 0; i < iface->num_bss; i++)
+		hostapd_cleanup_cs_params(iface->bss[i]);
+
+	hostapd_disable_iface(iface);
+	hostapd_enable_iface(iface);
+}
+
+#endif /* NEED_AP_MLME */
+
+
+struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
+					const char *ifname)
+{
+	size_t i, j;
+
+	for (i = 0; i < interfaces->count; i++) {
+		struct hostapd_iface *iface = interfaces->iface[i];
+
+		for (j = 0; j < iface->num_bss; j++) {
+			struct hostapd_data *hapd = iface->bss[j];
+
+			if (os_strcmp(ifname, hapd->conf->iface) == 0)
+				return hapd;
+		}
+	}
+
+	return NULL;
+}
+
+
+void hostapd_periodic_iface(struct hostapd_iface *iface)
+{
+	size_t i;
+
+	ap_list_timer(iface);
+
+	for (i = 0; i < iface->num_bss; i++) {
+		struct hostapd_data *hapd = iface->bss[i];
+
+		if (!hapd->started)
+			continue;
+
+#ifndef CONFIG_NO_RADIUS
+		hostapd_acl_expire(hapd);
+#endif /* CONFIG_NO_RADIUS */
+	}
+}

+ 41 - 0
EVSE/GPL/hostapd-2.6/src/ap/hostapd.d

@@ -0,0 +1,41 @@
+../src/ap/hostapd.o: ../src/ap/hostapd.c \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/includes.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/build_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/os.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpa_debug.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/wpabuf.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/eloop.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_ctrl.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/hw_features_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/drivers/driver.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius_client.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/ip_addr.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius_das.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eap_server/tncs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eapol_auth/eapol_auth_sm.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/eapol_auth/eapol_auth_sm_i.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/radius/radius.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/fst/fst.h \
+ ../src/ap/hostapd.h ../src/ap/ap_config.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/wpa_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/ieee802_11_common.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/defs.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/wps/wps_defs.h \
+ ../src/ap/vlan.h ../src/ap/authsrv.h ../src/ap/sta_info.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/utils/list.h \
+ ../src/ap/accounting.h ../src/ap/ap_list.h ../src/ap/beacon.h \
+ ../src/ap/iapp.h ../src/ap/ieee802_1x.h ../src/ap/ieee802_11_auth.h \
+ ../src/ap/vlan_init.h ../src/ap/wpa_auth.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/common/eapol_common.h \
+ ../src/ap/wps_hostapd.h ../src/ap/hw_features.h \
+ ../src/ap/wpa_auth_glue.h ../src/ap/ap_drv_ops.h ../src/ap/p2p_hostapd.h \
+ ../src/ap/gas_serv.h ../src/ap/dfs.h ../src/ap/ieee802_11.h \
+ ../src/ap/bss_load.h ../src/ap/x_snoop.h \
+ /opt/ti-processor-sdk-linux-am335x-evm-04.02.00.09/EVSE/GPL/hostapd-2.6/src/l2_packet/l2_packet.h \
+ ../src/ap/dhcp_snoop.h ../src/ap/ndisc_snoop.h ../src/ap/neighbor_db.h \
+ ../src/ap/rrm.h

+ 542 - 0
EVSE/GPL/hostapd-2.6/src/ap/hostapd.h

@@ -0,0 +1,542 @@
+/*
+ * hostapd / Initialization and configuration
+ * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef HOSTAPD_H
+#define HOSTAPD_H
+
+#include "common/defs.h"
+#include "utils/list.h"
+#include "ap_config.h"
+#include "drivers/driver.h"
+
+struct wpa_ctrl_dst;
+struct radius_server_data;
+struct upnp_wps_device_sm;
+struct hostapd_data;
+struct sta_info;
+struct ieee80211_ht_capabilities;
+struct full_dynamic_vlan;
+enum wps_event;
+union wps_event_data;
+#ifdef CONFIG_MESH
+struct mesh_conf;
+#endif /* CONFIG_MESH */
+
+struct hostapd_iface;
+
+struct hapd_interfaces {
+	int (*reload_config)(struct hostapd_iface *iface);
+	struct hostapd_config * (*config_read_cb)(const char *config_fname);
+	int (*ctrl_iface_init)(struct hostapd_data *hapd);
+	void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
+	int (*for_each_interface)(struct hapd_interfaces *interfaces,
+				  int (*cb)(struct hostapd_iface *iface,
+					    void *ctx), void *ctx);
+	int (*driver_init)(struct hostapd_iface *iface);
+
+	size_t count;
+	int global_ctrl_sock;
+	struct dl_list global_ctrl_dst;
+	char *global_iface_path;
+	char *global_iface_name;
+#ifndef CONFIG_NATIVE_WINDOWS
+	gid_t ctrl_iface_group;
+#endif /* CONFIG_NATIVE_WINDOWS */
+	struct hostapd_iface **iface;
+
+	size_t terminate_on_error;
+#ifndef CONFIG_NO_VLAN
+	struct dynamic_iface *vlan_priv;
+#endif /* CONFIG_NO_VLAN */
+	int eloop_initialized;
+};
+
+enum hostapd_chan_status {
+	HOSTAPD_CHAN_VALID = 0, /* channel is ready */
+	HOSTAPD_CHAN_INVALID = 1, /* no usable channel found */
+	HOSTAPD_CHAN_ACS = 2, /* ACS work being performed */
+};
+
+struct hostapd_probereq_cb {
+	int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid,
+		  const u8 *ie, size_t ie_len, int ssi_signal);
+	void *ctx;
+};
+
+#define HOSTAPD_RATE_BASIC 0x00000001
+
+struct hostapd_rate_data {
+	int rate; /* rate in 100 kbps */
+	int flags; /* HOSTAPD_RATE_ flags */
+};
+
+struct hostapd_frame_info {
+	u32 channel;
+	u32 datarate;
+	int ssi_signal; /* dBm */
+};
+
+enum wps_status {
+	WPS_STATUS_SUCCESS = 1,
+	WPS_STATUS_FAILURE
+};
+
+enum pbc_status {
+	WPS_PBC_STATUS_DISABLE,
+	WPS_PBC_STATUS_ACTIVE,
+	WPS_PBC_STATUS_TIMEOUT,
+	WPS_PBC_STATUS_OVERLAP
+};
+
+struct wps_stat {
+	enum wps_status status;
+	enum wps_error_indication failure_reason;
+	enum pbc_status pbc_status;
+	u8 peer_addr[ETH_ALEN];
+};
+
+struct hostapd_neighbor_entry {
+	struct dl_list list;
+	u8 bssid[ETH_ALEN];
+	struct wpa_ssid_value ssid;
+	struct wpabuf *nr;
+	struct wpabuf *lci;
+	struct wpabuf *civic;
+	/* LCI update time */
+	struct os_time lci_date;
+};
+
+/**
+ * struct hostapd_data - hostapd per-BSS data structure
+ */
+struct hostapd_data {
+	struct hostapd_iface *iface;
+	struct hostapd_config *iconf;
+	struct hostapd_bss_config *conf;
+	int interface_added; /* virtual interface added for this BSS */
+	unsigned int started:1;
+	unsigned int disabled:1;
+	unsigned int reenable_beacon:1;
+
+	u8 own_addr[ETH_ALEN];
+
+	int num_sta; /* number of entries in sta_list */
+	struct sta_info *sta_list; /* STA info list head */
+#define STA_HASH_SIZE 256
+#define STA_HASH(sta) (sta[5])
+	struct sta_info *sta_hash[STA_HASH_SIZE];
+
+	/*
+	 * Bitfield for indicating which AIDs are allocated. Only AID values
+	 * 1-2007 are used and as such, the bit at index 0 corresponds to AID
+	 * 1.
+	 */
+#define AID_WORDS ((2008 + 31) / 32)
+	u32 sta_aid[AID_WORDS];
+
+	const struct wpa_driver_ops *driver;
+	void *drv_priv;
+
+	void (*new_assoc_sta_cb)(struct hostapd_data *hapd,
+				 struct sta_info *sta, int reassoc);
+
+	void *msg_ctx; /* ctx for wpa_msg() calls */
+	void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */
+
+	struct radius_client_data *radius;
+	u64 acct_session_id;
+	struct radius_das_data *radius_das;
+
+	struct iapp_data *iapp;
+
+	struct hostapd_cached_radius_acl *acl_cache;
+	struct hostapd_acl_query_data *acl_queries;
+
+	struct wpa_authenticator *wpa_auth;
+	struct eapol_authenticator *eapol_auth;
+
+	struct rsn_preauth_interface *preauth_iface;
+	struct os_reltime michael_mic_failure;
+	int michael_mic_failures;
+	int tkip_countermeasures;
+
+	int ctrl_sock;
+	struct dl_list ctrl_dst;
+
+	void *ssl_ctx;
+	void *eap_sim_db_priv;
+	struct radius_server_data *radius_srv;
+	struct dl_list erp_keys; /* struct eap_server_erp_key */
+
+	int parameter_set_count;
+
+	/* Time Advertisement */
+	u8 time_update_counter;
+	struct wpabuf *time_adv;
+
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+	struct full_dynamic_vlan *full_dynamic_vlan;
+#endif /* CONFIG_FULL_DYNAMIC_VLAN */
+
+	struct l2_packet_data *l2;
+	struct wps_context *wps;
+
+	int beacon_set_done;
+	struct wpabuf *wps_beacon_ie;
+	struct wpabuf *wps_probe_resp_ie;
+#ifdef CONFIG_WPS
+	unsigned int ap_pin_failures;
+	unsigned int ap_pin_failures_consecutive;
+	struct upnp_wps_device_sm *wps_upnp;
+	unsigned int ap_pin_lockout_time;
+
+	struct wps_stat wps_stats;
+#endif /* CONFIG_WPS */
+
+	struct hostapd_probereq_cb *probereq_cb;
+	size_t num_probereq_cb;
+
+	void (*public_action_cb)(void *ctx, const u8 *buf, size_t len,
+				 int freq);
+	void *public_action_cb_ctx;
+	void (*public_action_cb2)(void *ctx, const u8 *buf, size_t len,
+				  int freq);
+	void *public_action_cb2_ctx;
+
+	int (*vendor_action_cb)(void *ctx, const u8 *buf, size_t len,
+				int freq);
+	void *vendor_action_cb_ctx;
+
+	void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr,
+				   const u8 *uuid_e);
+	void *wps_reg_success_cb_ctx;
+
+	void (*wps_event_cb)(void *ctx, enum wps_event event,
+			     union wps_event_data *data);
+	void *wps_event_cb_ctx;
+
+	void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr,
+				  int authorized, const u8 *p2p_dev_addr);
+	void *sta_authorized_cb_ctx;
+
+	void (*setup_complete_cb)(void *ctx);
+	void *setup_complete_cb_ctx;
+
+	void (*new_psk_cb)(void *ctx, const u8 *mac_addr,
+			   const u8 *p2p_dev_addr, const u8 *psk,
+			   size_t psk_len);
+	void *new_psk_cb_ctx;
+
+	/* channel switch parameters */
+	struct hostapd_freq_params cs_freq_params;
+	u8 cs_count;
+	int cs_block_tx;
+	unsigned int cs_c_off_beacon;
+	unsigned int cs_c_off_proberesp;
+	int csa_in_progress;
+	unsigned int cs_c_off_ecsa_beacon;
+	unsigned int cs_c_off_ecsa_proberesp;
+
+	/* BSS Load */
+	unsigned int bss_load_update_timeout;
+
+#ifdef CONFIG_P2P
+	struct p2p_data *p2p;
+	struct p2p_group *p2p_group;
+	struct wpabuf *p2p_beacon_ie;
+	struct wpabuf *p2p_probe_resp_ie;
+
+	/* Number of non-P2P association stations */
+	int num_sta_no_p2p;
+
+	/* Periodic NoA (used only when no non-P2P clients in the group) */
+	int noa_enabled;
+	int noa_start;
+	int noa_duration;
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_INTERWORKING
+	size_t gas_frag_limit;
+#endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_PROXYARP
+	struct l2_packet_data *sock_dhcp;
+	struct l2_packet_data *sock_ndisc;
+#endif /* CONFIG_PROXYARP */
+#ifdef CONFIG_MESH
+	int num_plinks;
+	int max_plinks;
+	void (*mesh_sta_free_cb)(struct hostapd_data *hapd,
+				 struct sta_info *sta);
+	struct wpabuf *mesh_pending_auth;
+	struct os_reltime mesh_pending_auth_time;
+	u8 mesh_required_peer[ETH_ALEN];
+#endif /* CONFIG_MESH */
+
+#ifdef CONFIG_SQLITE
+	struct hostapd_eap_user tmp_eap_user;
+#endif /* CONFIG_SQLITE */
+
+#ifdef CONFIG_SAE
+	/** Key used for generating SAE anti-clogging tokens */
+	u8 sae_token_key[8];
+	struct os_reltime last_sae_token_key_update;
+	int dot11RSNASAERetransPeriod; /* msec */
+#endif /* CONFIG_SAE */
+
+#ifdef CONFIG_TESTING_OPTIONS
+	unsigned int ext_mgmt_frame_handling:1;
+	unsigned int ext_eapol_frame_io:1;
+
+	struct l2_packet_data *l2_test;
+#endif /* CONFIG_TESTING_OPTIONS */
+
+#ifdef CONFIG_MBO
+	unsigned int mbo_assoc_disallow;
+#endif /* CONFIG_MBO */
+
+	struct dl_list nr_db;
+
+	u8 lci_req_token;
+	u8 range_req_token;
+	unsigned int lci_req_active:1;
+	unsigned int range_req_active:1;
+};
+
+
+struct hostapd_sta_info {
+	struct dl_list list;
+	u8 addr[ETH_ALEN];
+	struct os_reltime last_seen;
+#ifdef CONFIG_TAXONOMY
+	struct wpabuf *probe_ie_taxonomy;
+#endif /* CONFIG_TAXONOMY */
+};
+
+/**
+ * struct hostapd_iface - hostapd per-interface data structure
+ */
+struct hostapd_iface {
+	struct hapd_interfaces *interfaces;
+	void *owner;
+	char *config_fname;
+	struct hostapd_config *conf;
+	char phy[16]; /* Name of the PHY (radio) */
+
+	enum hostapd_iface_state {
+		HAPD_IFACE_UNINITIALIZED,
+		HAPD_IFACE_DISABLED,
+		HAPD_IFACE_COUNTRY_UPDATE,
+		HAPD_IFACE_ACS,
+		HAPD_IFACE_HT_SCAN,
+		HAPD_IFACE_DFS,
+		HAPD_IFACE_ENABLED
+	} state;
+
+#ifdef CONFIG_MESH
+	struct mesh_conf *mconf;
+#endif /* CONFIG_MESH */
+
+	size_t num_bss;
+	struct hostapd_data **bss;
+
+	unsigned int wait_channel_update:1;
+	unsigned int cac_started:1;
+#ifdef CONFIG_FST
+	struct fst_iface *fst;
+	const struct wpabuf *fst_ies;
+#endif /* CONFIG_FST */
+
+	/*
+	 * When set, indicates that the driver will handle the AP
+	 * teardown: delete global keys, station keys, and stations.
+	 */
+	unsigned int driver_ap_teardown:1;
+
+	/*
+	 * When set, indicates that this interface is part of list of
+	 * interfaces that need to be started together (synchronously).
+	 */
+	unsigned int need_to_start_in_sync:1;
+
+	/* Ready to start but waiting for other interfaces to become ready. */
+	unsigned int ready_to_start_in_sync:1;
+
+	int num_ap; /* number of entries in ap_list */
+	struct ap_info *ap_list; /* AP info list head */
+	struct ap_info *ap_hash[STA_HASH_SIZE];
+
+	u64 drv_flags;
+
+	/* SMPS modes supported by the driver (WPA_DRIVER_SMPS_MODE_*) */
+	unsigned int smps_modes;
+
+	/*
+	 * A bitmap of supported protocols for probe response offload. See
+	 * struct wpa_driver_capa in driver.h
+	 */
+	unsigned int probe_resp_offloads;
+
+	/* extended capabilities supported by the driver */
+	const u8 *extended_capa, *extended_capa_mask;
+	unsigned int extended_capa_len;
+
+	unsigned int drv_max_acl_mac_addrs;
+
+	struct hostapd_hw_modes *hw_features;
+	int num_hw_features;
+	struct hostapd_hw_modes *current_mode;
+	/* Rates that are currently used (i.e., filtered copy of
+	 * current_mode->channels */
+	int num_rates;
+	struct hostapd_rate_data *current_rates;
+	int *basic_rates;
+	int freq;
+
+	u16 hw_flags;
+
+	/* Number of associated Non-ERP stations (i.e., stations using 802.11b
+	 * in 802.11g BSS) */
+	int num_sta_non_erp;
+
+	/* Number of associated stations that do not support Short Slot Time */
+	int num_sta_no_short_slot_time;
+
+	/* Number of associated stations that do not support Short Preamble */
+	int num_sta_no_short_preamble;
+
+	int olbc; /* Overlapping Legacy BSS Condition */
+
+	/* Number of HT associated stations that do not support greenfield */
+	int num_sta_ht_no_gf;
+
+	/* Number of associated non-HT stations */
+	int num_sta_no_ht;
+
+	/* Number of HT associated stations 20 MHz */
+	int num_sta_ht_20mhz;
+
+	/* Number of HT40 intolerant stations */
+	int num_sta_ht40_intolerant;
+
+	/* Overlapping BSS information */
+	int olbc_ht;
+
+	u16 ht_op_mode;
+
+	/* surveying helpers */
+
+	/* number of channels surveyed */
+	unsigned int chans_surveyed;
+
+	/* lowest observed noise floor in dBm */
+	s8 lowest_nf;
+
+	/* channel utilization calculation */
+	u64 last_channel_time;
+	u64 last_channel_time_busy;
+	u8 channel_utilization;
+
+	/* eCSA IE will be added only if operating class is specified */
+	u8 cs_oper_class;
+
+	unsigned int dfs_cac_ms;
+	struct os_reltime dfs_cac_start;
+
+	/* Latched with the actual secondary channel information and will be
+	 * used while juggling between HT20 and HT40 modes. */
+	int secondary_ch;
+
+#ifdef CONFIG_ACS
+	unsigned int acs_num_completed_scans;
+#endif /* CONFIG_ACS */
+
+	void (*scan_cb)(struct hostapd_iface *iface);
+	int num_ht40_scan_tries;
+
+	struct dl_list sta_seen; /* struct hostapd_sta_info */
+	unsigned int num_sta_seen;
+};
+
+/* hostapd.c */
+int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+			       int (*cb)(struct hostapd_iface *iface,
+					 void *ctx), void *ctx);
+int hostapd_reload_config(struct hostapd_iface *iface);
+struct hostapd_data *
+hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
+		       struct hostapd_config *conf,
+		       struct hostapd_bss_config *bss);
+int hostapd_setup_interface(struct hostapd_iface *iface);
+int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
+void hostapd_interface_deinit(struct hostapd_iface *iface);
+void hostapd_interface_free(struct hostapd_iface *iface);
+struct hostapd_iface * hostapd_alloc_iface(void);
+struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
+				    const char *config_file);
+struct hostapd_iface *
+hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
+			   const char *config_fname, int debug);
+void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
+			   int reassoc);
+void hostapd_interface_deinit_free(struct hostapd_iface *iface);
+int hostapd_enable_iface(struct hostapd_iface *hapd_iface);
+int hostapd_reload_iface(struct hostapd_iface *hapd_iface);
+int hostapd_disable_iface(struct hostapd_iface *hapd_iface);
+int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf);
+int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
+void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
+void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s);
+const char * hostapd_state_text(enum hostapd_iface_state s);
+int hostapd_csa_in_progress(struct hostapd_iface *iface);
+int hostapd_switch_channel(struct hostapd_data *hapd,
+			   struct csa_settings *settings);
+void
+hostapd_switch_channel_fallback(struct hostapd_iface *iface,
+				const struct hostapd_freq_params *freq_params);
+void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
+void hostapd_periodic_iface(struct hostapd_iface *iface);
+
+/* utils.c */
+int hostapd_register_probereq_cb(struct hostapd_data *hapd,
+				 int (*cb)(void *ctx, const u8 *sa,
+					   const u8 *da, const u8 *bssid,
+					   const u8 *ie, size_t ie_len,
+					   int ssi_signal),
+				 void *ctx);
+void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr);
+
+/* drv_callbacks.c (TODO: move to somewhere else?) */
+int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
+			const u8 *ie, size_t ielen, int reassoc);
+void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
+void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
+void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
+					 const u8 *addr, int reason_code);
+int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
+			 const u8 *bssid, const u8 *ie, size_t ie_len,
+			 int ssi_signal);
+void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
+			     int offset, int width, int cf1, int cf2);
+struct survey_results;
+void hostapd_event_get_survey(struct hostapd_iface *iface,
+			      struct survey_results *survey_results);
+void hostapd_acs_channel_selected(struct hostapd_data *hapd,
+				  struct acs_selected_channels *acs_res);
+
+const struct hostapd_eap_user *
+hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
+		     size_t identity_len, int phase2);
+
+struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
+					const char *ifname);
+
+#ifdef CONFIG_FST
+void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
+				struct fst_wpa_obj *iface_obj);
+#endif /* CONFIG_FST */
+
+#endif /* HOSTAPD_H */

+ 177 - 0
EVSE/GPL/hostapd-2.6/src/ap/hs20.c

@@ -0,0 +1,177 @@
+/*
+ * Hotspot 2.0 AP ANQP processing
+ * Copyright (c) 2009, Atheros Communications, Inc.
+ * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "common/ieee802_11_defs.h"
+#include "hostapd.h"
+#include "ap_config.h"
+#include "ap_drv_ops.h"
+#include "hs20.h"
+
+
+u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid)
+{
+	u8 conf;
+	if (!hapd->conf->hs20)
+		return eid;
+	*eid++ = WLAN_EID_VENDOR_SPECIFIC;
+	*eid++ = 7;
+	WPA_PUT_BE24(eid, OUI_WFA);
+	eid += 3;
+	*eid++ = HS20_INDICATION_OUI_TYPE;
+	conf = HS20_VERSION; /* Release Number */
+	conf |= HS20_ANQP_DOMAIN_ID_PRESENT;
+	if (hapd->conf->disable_dgaf)
+		conf |= HS20_DGAF_DISABLED;
+	*eid++ = conf;
+	WPA_PUT_LE16(eid, hapd->conf->anqp_domain_id);
+	eid += 2;
+
+	return eid;
+}
+
+
+u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid)
+{
+	u8 *len;
+	u16 capab;
+
+	if (!hapd->conf->osen)
+		return eid;
+
+	*eid++ = WLAN_EID_VENDOR_SPECIFIC;
+	len = eid++; /* to be filled */
+	WPA_PUT_BE24(eid, OUI_WFA);
+	eid += 3;
+	*eid++ = HS20_OSEN_OUI_TYPE;
+
+	/* Group Data Cipher Suite */
+	RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
+	eid += RSN_SELECTOR_LEN;
+
+	/* Pairwise Cipher Suite Count and List */
+	WPA_PUT_LE16(eid, 1);
+	eid += 2;
+	RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP);
+	eid += RSN_SELECTOR_LEN;
+
+	/* AKM Suite Count and List */
+	WPA_PUT_LE16(eid, 1);
+	eid += 2;
+	RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN);
+	eid += RSN_SELECTOR_LEN;
+
+	/* RSN Capabilities */
+	capab = 0;
+	if (hapd->conf->wmm_enabled) {
+		/* 4 PTKSA replay counters when using WMM */
+		capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
+	}
+#ifdef CONFIG_IEEE80211W
+	if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+		capab |= WPA_CAPABILITY_MFPC;
+		if (hapd->conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
+			capab |= WPA_CAPABILITY_MFPR;
+	}
+#endif /* CONFIG_IEEE80211W */
+	WPA_PUT_LE16(eid, capab);
+	eid += 2;
+
+	*len = eid - len - 1;
+
+	return eid;
+}
+
+
+int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
+			       u8 osu_method, const char *url)
+{
+	struct wpabuf *buf;
+	size_t len = 0;
+	int ret;
+
+	/* TODO: should refuse to send notification if the STA is not associated
+	 * or if the STA did not indicate support for WNM-Notification */
+
+	if (url) {
+		len = 1 + os_strlen(url);
+		if (5 + len > 255) {
+			wpa_printf(MSG_INFO, "HS 2.0: Too long URL for "
+				   "WNM-Notification: '%s'", url);
+			return -1;
+		}
+	}
+
+	buf = wpabuf_alloc(4 + 7 + len);
+	if (buf == NULL)
+		return -1;
+
+	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
+	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
+	wpabuf_put_u8(buf, 1); /* Dialog token */
+	wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
+
+	/* Subscription Remediation subelement */
+	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
+	wpabuf_put_u8(buf, 5 + len);
+	wpabuf_put_be24(buf, OUI_WFA);
+	wpabuf_put_u8(buf, HS20_WNM_SUB_REM_NEEDED);
+	if (url) {
+		wpabuf_put_u8(buf, len - 1);
+		wpabuf_put_data(buf, url, len - 1);
+		wpabuf_put_u8(buf, osu_method);
+	} else {
+		/* Server URL and Server Method fields not included */
+		wpabuf_put_u8(buf, 0);
+	}
+
+	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
+				      wpabuf_head(buf), wpabuf_len(buf));
+
+	wpabuf_free(buf);
+
+	return ret;
+}
+
+
+int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
+					  const u8 *addr,
+					  const struct wpabuf *payload)
+{
+	struct wpabuf *buf;
+	int ret;
+
+	/* TODO: should refuse to send notification if the STA is not associated
+	 * or if the STA did not indicate support for WNM-Notification */
+
+	buf = wpabuf_alloc(4 + 6 + wpabuf_len(payload));
+	if (buf == NULL)
+		return -1;
+
+	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
+	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
+	wpabuf_put_u8(buf, 1); /* Dialog token */
+	wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */
+
+	/* Deauthentication Imminent Notice subelement */
+	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
+	wpabuf_put_u8(buf, 4 + wpabuf_len(payload));
+	wpabuf_put_be24(buf, OUI_WFA);
+	wpabuf_put_u8(buf, HS20_WNM_DEAUTH_IMMINENT_NOTICE);
+	wpabuf_put_buf(buf, payload);
+
+	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
+				      wpabuf_head(buf), wpabuf_len(buf));
+
+	wpabuf_free(buf);
+
+	return ret;
+}

+ 22 - 0
EVSE/GPL/hostapd-2.6/src/ap/hs20.h

@@ -0,0 +1,22 @@
+/*
+ * Hotspot 2.0 AP ANQP processing
+ * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef HS20_H
+#define HS20_H
+
+struct hostapd_data;
+
+u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid);
+int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr,
+			       u8 osu_method, const char *url);
+int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
+					  const u8 *addr,
+					  const struct wpabuf *payload);
+
+#endif /* HS20_H */

Some files were not shown because too many files changed in this diff