aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hostapd/.gitignore7
-rw-r--r--hostapd/ChangeLog663
-rw-r--r--hostapd/Makefile791
-rw-r--r--hostapd/README387
-rw-r--r--hostapd/README-WPS265
-rw-r--r--hostapd/config_file.c2049
-rw-r--r--hostapd/config_file.h20
-rw-r--r--hostapd/ctrl_iface.c726
-rw-r--r--hostapd/ctrl_iface.h32
-rw-r--r--hostapd/defconfig175
-rw-r--r--hostapd/dump_state.c184
-rw-r--r--hostapd/dump_state.h20
-rw-r--r--hostapd/eap_register.c134
-rw-r--r--hostapd/eap_register.h20
-rw-r--r--hostapd/eap_testing.txt77
-rw-r--r--hostapd/hlr_auc_gw.c714
-rw-r--r--hostapd/hlr_auc_gw.milenage_db13
-rw-r--r--hostapd/hostapd.859
-rw-r--r--hostapd/hostapd.accept6
-rw-r--r--hostapd/hostapd.conf1016
-rw-r--r--hostapd/hostapd.deny5
-rw-r--r--hostapd/hostapd.eap_user91
-rw-r--r--hostapd/hostapd.radius_clients4
-rw-r--r--hostapd/hostapd.sim_db9
-rw-r--r--hostapd/hostapd.vlan9
-rw-r--r--hostapd/hostapd.wpa_psk9
-rw-r--r--hostapd/hostapd_cli.189
-rw-r--r--hostapd/hostapd_cli.c904
-rw-r--r--hostapd/logwatch/README9
-rwxr-xr-xhostapd/logwatch/hostapd65
-rw-r--r--hostapd/logwatch/hostapd.conf10
-rw-r--r--hostapd/main.c565
-rw-r--r--hostapd/nt_password_hash.c53
-rw-r--r--hostapd/wired.conf40
34 files changed, 9220 insertions, 0 deletions
diff --git a/hostapd/.gitignore b/hostapd/.gitignore
new file mode 100644
index 000000000000..6dd2c2fd35c4
--- /dev/null
+++ b/hostapd/.gitignore
@@ -0,0 +1,7 @@
+*.d
+.config
+driver_conf.c
+hostapd
+hostapd_cli
+hlr_auc_gw
+nt_password_hash
diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog
new file mode 100644
index 000000000000..a7f1f108f9a0
--- /dev/null
+++ b/hostapd/ChangeLog
@@ -0,0 +1,663 @@
+ChangeLog for hostapd
+
+2010-09-07 - v0.7.3
+ * fixed re-association after WPS not initializing WPA state machine in
+ some cases
+ * fixed WPS IE update on reconfiguration
+ * fixed WPS code not to proxy Probe Request frames for foreign SSIDs
+ * added WPS workaround for open networks and some known interop issues
+ * fixed WPS Diffie-Hellman derivation to use correct public key length
+ * fixed FT RRB messages on big endian CPUs
+ * changed WPS protection for brute force AP PIN attacks to disable AP
+ PIN only temporarily (but with increasing time) to avoid usability
+ issues on Label-only devices
+ * added wps_ap_pin command for more secure handling of AP PIN
+ operations (e.g., to generate a random AP PIN and only use it for
+ short amount of time)
+ * fixed HT STBC negotiation
+
+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-existance 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.
diff --git a/hostapd/Makefile b/hostapd/Makefile
new file mode 100644
index 000000000000..6d344d2a92ff
--- /dev/null
+++ b/hostapd/Makefile
@@ -0,0 +1,791 @@
+ifndef CC
+CC=gcc
+endif
+
+ifndef CFLAGS
+CFLAGS = -MMD -O2 -Wall -g
+endif
+
+CFLAGS += -I../src
+CFLAGS += -I../src/utils
+
+# Uncomment following line and set the path to your kernel tree include
+# directory if your C library does not include all header files.
+# CFLAGS += -DUSE_KERNEL_HEADERS -I/usr/src/linux/include
+
+-include .config
+
+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/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
+
+NEED_RC4=y
+NEED_AES=y
+NEED_MD5=y
+NEED_SHA1=y
+
+OBJS += ../src/drivers/drivers.o
+CFLAGS += -DHOSTAPD
+
+ifdef CONFIG_WPA_TRACE
+CFLAGS += -DWPA_TRACE
+OBJS += ../src/utils/trace.o
+LDFLAGS += -rdynamic
+CFLAGS += -funwind-tables
+ifdef CONFIG_WPA_TRACE_BFD
+CFLAGS += -DWPA_TRACE_BFD
+LIBS += -lbfd
+LIBS_c += -lbfd
+endif
+endif
+
+OBJS += ../src/utils/eloop.o
+OBJS += ../src/utils/common.o
+OBJS += ../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/eapol_auth/eapol_auth_sm.o
+
+
+ifndef CONFIG_NO_DUMP_STATE
+# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to
+# a file (undefine it, if you want to save in binary size)
+CFLAGS += -DHOSTAPD_DUMP_STATE
+OBJS += dump_state.o
+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
+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
+endif
+
+ifdef CONFIG_NO_CTRL_IFACE
+CFLAGS += -DCONFIG_NO_CTRL_IFACE
+else
+OBJS += ctrl_iface.o
+OBJS += ../src/ap/ctrl_iface_ap.o
+endif
+
+OBJS += ../src/crypto/md5.o
+
+CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX
+
+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_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_IEEE80211N
+CFLAGS += -DCONFIG_IEEE80211N
+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_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_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_SERVER_GPSK_SHA256
+endif
+NEED_SHA256=y
+NEED_AES_OMAC1=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_UFD
+CFLAGS += -DCONFIG_WPS_UFD
+OBJS += ../src/wps/wps_ufd.o
+NEED_WPS_OOB=y
+endif
+
+ifdef CONFIG_WPS_NFC
+CFLAGS += -DCONFIG_WPS_NFC
+OBJS += ../src/wps/ndef.o
+OBJS += ../src/wps/wps_nfc.o
+NEED_WPS_OOB=y
+ifdef CONFIG_WPS_NFC_PN531
+PN531_PATH ?= /usr/local/src/nfc
+CFLAGS += -DCONFIG_WPS_NFC_PN531
+CFLAGS += -I${PN531_PATH}/inc
+OBJS += ../src/wps/wps_nfc_pn531.o
+LIBS += ${PN531_PATH}/lib/wpsnfc.dll
+LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll
+endif
+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
+
+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
+
+ifeq ($(CONFIG_TLS), openssl)
+ifdef TLS_FUNCS
+OBJS += ../src/crypto/tls_openssl.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
+LIBS += -lcrypto
+LIBS_h += -lcrypto
+endif
+
+ifeq ($(CONFIG_TLS), gnutls)
+ifdef TLS_FUNCS
+OBJS += ../src/crypto/tls_gnutls.o
+LIBS += -lgnutls -lgpg-error
+ifdef CONFIG_GNUTLS_EXTRA
+CFLAGS += -DCONFIG_GNUTLS_EXTRA
+LIBS += -lgnutls-extra
+endif
+endif
+OBJS += ../src/crypto/crypto_gnutls.o
+HOBJS += ../src/crypto/crypto_gnutls.o
+ifdef NEED_FIPS186_2_PRF
+OBJS += ../src/crypto/fips_prf_gnutls.o
+endif
+LIBS += -lgcrypt
+LIBS_h += -lgcrypt
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+
+ifeq ($(CONFIG_TLS), schannel)
+ifdef TLS_FUNCS
+OBJS += ../src/crypto/tls_schannel.o
+endif
+OBJS += ../src/crypto/crypto_cryptoapi.o
+OBJS_p += ../src/crypto/crypto_cryptoapi.o
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_DH_GROUP5=y
+endif
+
+ifeq ($(CONFIG_TLS), nss)
+ifdef TLS_FUNCS
+OBJS += ../src/crypto/tls_nss.o
+LIBS += -lssl3
+endif
+OBJS += ../src/crypto/crypto_nss.o
+ifdef NEED_FIPS186_2_PRF
+OBJS += ../src/crypto/fips_prf_nss.o
+endif
+LIBS += -lnss3
+LIBS_h += -lnss3
+CONFIG_INTERNAL_MD4=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
+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_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
+
+AESOBJS += ../src/crypto/aes-wrap.o
+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
+NEED_AES_DEC=y
+AESOBJS += ../src/crypto/aes-unwrap.o
+endif
+ifdef NEED_AES_CBC
+NEED_AES_DEC=y
+AESOBJS += ../src/crypto/aes-cbc.o
+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
+SHA1OBJS += ../src/crypto/sha1.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
+SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
+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
+
+ifdef NEED_MD5
+ifdef CONFIG_INTERNAL_MD5
+OBJS += ../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 NEED_RC4
+ifdef CONFIG_INTERNAL_RC4
+OBJS += ../src/crypto/rc4.o
+endif
+endif
+
+ifdef NEED_SHA256
+OBJS += ../src/crypto/sha256.o
+ifdef CONFIG_INTERNAL_SHA256
+OBJS += ../src/crypto/sha256-internal.o
+endif
+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 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 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
+endif
+
+ifdef NEED_BASE64
+OBJS += ../src/utils/base64.o
+endif
+
+ifdef NEED_AP_MLME
+OBJS += ../src/ap/beacon.o
+OBJS += ../src/ap/wmm.o
+OBJS += ../src/ap/ap_list.o
+OBJS += ../src/ap/ieee802_11.o
+OBJS += ../src/ap/hw_features.o
+CFLAGS += -DNEED_AP_MLME
+endif
+ifdef CONFIG_IEEE80211N
+OBJS += ../src/ap/ieee802_11_ht.o
+endif
+
+ifdef CONFIG_NO_STDOUT_DEBUG
+CFLAGS += -DCONFIG_NO_STDOUT_DEBUG
+endif
+
+ALL=hostapd hostapd_cli
+
+all: verify_config $(ALL)
+
+Q=@
+E=echo
+ifeq ($(V), 1)
+Q=
+E=true
+endif
+
+%.o: %.c
+ $(Q)$(CC) -c -o $@ $(CFLAGS) $<
+ @$(E) " CC " $<
+
+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
+
+install: all
+ for i in $(ALL); do cp -f $$i /usr/local/bin/$$i; done
+
+../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)
+ $(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
+
+OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o
+ifdef CONFIG_WPA_TRACE
+OBJS_c += ../src/utils/trace.o
+OBJS_c += ../src/utils/wpa_debug.o
+endif
+hostapd_cli: $(OBJS_c)
+ $(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
+
+NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) ../src/crypto/md5.o
+ifdef NEED_RC4
+ifdef CONFIG_INTERNAL_RC4
+NOBJS += ../src/crypto/rc4.o
+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)
+ $(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
+
+hlr_auc_gw: $(HOBJS)
+ $(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h)
+
+clean:
+ $(MAKE) -C ../src clean
+ rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw
+ rm -f *.d
+
+-include $(OBJS:%.o=%.d)
diff --git a/hostapd/README b/hostapd/README
new file mode 100644
index 000000000000..1af487d76593
--- /dev/null
+++ b/hostapd/README
@@ -0,0 +1,387 @@
+hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
+ Authenticator and RADIUS authentication server
+================================================================
+
+Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+This program is dual-licensed under both the GPL version 2 and BSD
+license. Either license may be used at your option.
+
+
+
+License
+-------
+
+GPL v2:
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+(this copy of the license is in COPYING file)
+
+
+Alternatively, 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.
+
+ madwifi driver for cards based on Atheros chip set (ar521x)
+ (http://sourceforge.net/projects/madwifi/)
+ Please note that you will need to add the correct path for
+ madwifi driver root directory in .config (see defconfig file for
+ an example: CFLAGS += -I<path>)
+
+ 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
diff --git a/hostapd/README-WPS b/hostapd/README-WPS
new file mode 100644
index 000000000000..74f211348ede
--- /dev/null
+++ b/hostapd/README-WPS
@@ -0,0 +1,265 @@
+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 madwifi driver interface:
+
+CONFIG_DRIVER_MADWIFI=y
+CFLAGS += -I/usr/src/madwifi-0.9.3
+CONFIG_WPS=y
+CONFIG_WPS_UPNP=y
+
+
+Following section shows an example runtime configuration
+(hostapd.conf) that enables WPS:
+
+# Configure the driver and network interface
+driver=madwifi
+interface=ath0
+
+# 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.
+
+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 can be set for the new PIN:
+
+hostapd_cli wps_pin any 12345670 300
+
+
+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
+
+
+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 tricker 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).
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
new file mode 100644
index 000000000000..8916b03db826
--- /dev/null
+++ b/hostapd/config_file.c
@@ -0,0 +1,2049 @@
+/*
+ * hostapd / Configuration file parser
+ * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING 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"
+
+
+extern struct wpa_driver_ops *wpa_drivers[];
+
+
+#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_malloc(sizeof(*vlan));
+ if (vlan == NULL) {
+ wpa_printf(MSG_ERROR, "Out of memory while reading "
+ "VLAN interfaces from '%s'", fname);
+ fclose(f);
+ return -1;
+ }
+
+ os_memset(vlan, 0, sizeof(*vlan));
+ vlan->vlan_id = vlan_id;
+ os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
+ if (bss->vlan_tail)
+ bss->vlan_tail->next = vlan;
+ else
+ bss->vlan = vlan;
+ bss->vlan_tail = 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)) {
+ 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' at "
+ "line %d in '%s'", buf, line, fname);
+ fclose(f);
+ return -1;
+ }
+
+ 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(*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);
+ (*acl)[*num].vlan_id = 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, *tail = NULL;
+
+ if (!fname)
+ return 0;
+
+ 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;
+
+ 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;
+ }
+ wpa_printf(MSG_ERROR, "Unsupported EAP type "
+ "'%s' on line %d in '%s'",
+ start, line, fname);
+ goto failed;
+ }
+
+ num_methods++;
+ if (num_methods >= EAP_USER_MAX_METHODS)
+ break;
+ skip_eap:
+ if (pos3 == NULL)
+ break;
+ start = pos3;
+ }
+ if (num_methods == 0 && user->ttls_auth == 0) {
+ 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 = conf->eap_user = user;
+ } else {
+ tail->next = user;
+ tail = user;
+ }
+ continue;
+
+ failed:
+ if (user) {
+ os_free(user->password);
+ os_free(user->identity);
+ os_free(user);
+ }
+ ret = -1;
+ break;
+ }
+
+ fclose(f);
+
+ 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(*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;
+}
+#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 */
+ 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 = 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, "CCMP") == 0)
+ val |= WPA_CIPHER_CCMP;
+ else if (os_strcmp(start, "TKIP") == 0)
+ val |= WPA_CIPHER_TKIP;
+ else if (os_strcmp(start, "WEP104") == 0)
+ val |= WPA_CIPHER_WEP104;
+ else if (os_strcmp(start, "WEP40") == 0)
+ val |= WPA_CIPHER_WEP40;
+ else if (os_strcmp(start, "NONE") == 0)
+ val |= WPA_CIPHER_NONE;
+ else {
+ wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%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 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_rates(int **rate_list, char *val)
+{
+ int *list;
+ int count;
+ char *pos, *end;
+
+ os_free(*rate_list);
+ *rate_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;
+
+ *rate_list = list;
+ return 0;
+}
+
+
+static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
+{
+ struct hostapd_bss_config *bss;
+
+ if (*ifname == '\0')
+ return -1;
+
+ bss = os_realloc(conf->bss, (conf->num_bss + 1) *
+ sizeof(struct hostapd_bss_config));
+ if (bss == NULL) {
+ wpa_printf(MSG_ERROR, "Failed to allocate memory for "
+ "multi-BSS entry");
+ return -1;
+ }
+ conf->bss = bss;
+
+ bss = &(conf->bss[conf->num_bss]);
+ os_memset(bss, 0, sizeof(*bss));
+ bss->radius = os_zalloc(sizeof(*bss->radius));
+ if (bss->radius == NULL) {
+ wpa_printf(MSG_ERROR, "Failed to allocate memory for "
+ "multi-BSS RADIUS data");
+ return -1;
+ }
+
+ conf->num_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);
+}
+
+
+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 */
+ IEEE80211_TX_QUEUE_DATA4 = 4,
+ IEEE80211_TX_QUEUE_AFTER_BEACON = 6,
+ IEEE80211_TX_QUEUE_BEACON = 7
+};
+
+static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name,
+ char *val)
+{
+ int num;
+ 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) {
+ num = IEEE80211_TX_QUEUE_AFTER_BEACON;
+ pos += 13;
+ } else if (os_strncmp(pos, "beacon_", 7) == 0) {
+ num = IEEE80211_TX_QUEUE_BEACON;
+ pos += 7;
+ } else {
+ wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos);
+ return -1;
+ }
+
+ 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;
+ }
+
+ queue->configured = 1;
+
+ return 0;
+}
+
+
+static int hostapd_config_wmm_ac(struct hostapd_config *conf, char *name,
+ char *val)
+{
+ int num, v;
+ char *pos;
+ struct hostapd_wmm_ac_params *ac;
+
+ /* skip 'wme_ac_' or 'wmm_ac_' prefix */
+ pos = name + 7;
+ if (os_strncmp(pos, "be_", 3) == 0) {
+ num = 0;
+ pos += 3;
+ } else if (os_strncmp(pos, "bk_", 3) == 0) {
+ num = 1;
+ pos += 3;
+ } else if (os_strncmp(pos, "vi_", 3) == 0) {
+ num = 2;
+ pos += 3;
+ } else if (os_strncmp(pos, "vo_", 3) == 0) {
+ num = 3;
+ pos += 3;
+ } else {
+ wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos);
+ return -1;
+ }
+
+ ac = &conf->wmm_ac_params[num];
+
+ if (os_strcmp(pos, "aifs") == 0) {
+ v = atoi(val);
+ if (v < 1 || v > 255) {
+ wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v);
+ return -1;
+ }
+ ac->aifs = v;
+ } else if (os_strcmp(pos, "cwmin") == 0) {
+ v = atoi(val);
+ if (v < 0 || v > 12) {
+ wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
+ return -1;
+ }
+ ac->cwmin = v;
+ } else if (os_strcmp(pos, "cwmax") == 0) {
+ v = atoi(val);
+ if (v < 0 || v > 12) {
+ wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
+ return -1;
+ }
+ ac->cwmax = v;
+ } else if (os_strcmp(pos, "txop_limit") == 0) {
+ v = atoi(val);
+ if (v < 0 || v > 0xffff) {
+ wpa_printf(MSG_ERROR, "Invalid txop value %d", v);
+ return -1;
+ }
+ ac->txop_limit = v;
+ } else if (os_strcmp(pos, "acm") == 0) {
+ v = atoi(val);
+ if (v < 0 || v > 1) {
+ wpa_printf(MSG_ERROR, "Invalid acm value %d", v);
+ return -1;
+ }
+ ac->admission_control_mandatory = v;
+ } else {
+ wpa_printf(MSG_ERROR, "Unknown wmm_ac_ 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, "[PSMP]"))
+ conf->ht_capab |= HT_CAP_INFO_PSMP_SUPP;
+ if (os_strstr(capab, "[LSIG-TXOP-PROT]"))
+ conf->ht_capab |= HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT;
+
+ return 0;
+}
+#endif /* CONFIG_IEEE80211N */
+
+
+static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
+ struct hostapd_config *conf)
+{
+ if (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 && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
+ bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
+ bss->ssid.wpa_psk_file == NULL) {
+ wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
+ "is not configured.");
+ return -1;
+ }
+
+ if (hostapd_mac_comp_empty(bss->bssid) != 0) {
+ 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 ((bss->wpa_key_mgmt &
+ (WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X)) &&
+ (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 (conf->ieee80211n && bss->wpa &&
+ !(bss->wpa_pairwise & WPA_CIPHER_CCMP) &&
+ !(bss->rsn_pairwise & WPA_CIPHER_CCMP)) {
+ wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 "
+ "requires CCMP to be enabled");
+ return -1;
+ }
+#endif /* CONFIG_IEEE80211N */
+
+ return 0;
+}
+
+
+static int hostapd_config_check(struct hostapd_config *conf)
+{
+ size_t i;
+
+ if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) {
+ wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without "
+ "setting the country_code");
+ return -1;
+ }
+
+ for (i = 0; i < conf->num_bss; i++) {
+ if (hostapd_config_check_bss(&conf->bss[i], conf))
+ 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;
+ struct hostapd_bss_config *bss;
+ FILE *f;
+ char buf[256], *pos;
+ int line = 0;
+ int errors = 0;
+ int pairwise;
+ 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;
+ }
+
+ bss = conf->last_bss = conf->bss;
+
+ while (fgets(buf, sizeof(buf), f)) {
+ 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++;
+
+ 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, "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);
+ errors++;
+ }
+ } 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) {
+ bss->dump_log_name = os_strdup(pos);
+ } else if (os_strcmp(buf, "ssid") == 0) {
+ bss->ssid.ssid_len = os_strlen(pos);
+ if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN ||
+ bss->ssid.ssid_len < 1) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid SSID "
+ "'%s'", line, pos);
+ errors++;
+ } else {
+ os_memcpy(bss->ssid.ssid, pos,
+ bss->ssid.ssid_len);
+ bss->ssid.ssid[bss->ssid.ssid_len] = '\0';
+ bss->ssid.ssid_set = 1;
+ }
+ } 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "wds_sta") == 0) {
+ bss->wds_sta = atoi(pos);
+ } else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
+ bss->ap_max_inactivity = 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, "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);
+ errors++;
+ } else
+ 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))
+ errors++;
+ } 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, "dh_file") == 0) {
+ os_free(bss->dh_file);
+ bss->dh_file = os_strdup(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);
+ errors++;
+ } else if (hexstr2bin(pos, bss->pac_opaque_encr_key,
+ 16)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid "
+ "pac_opaque_encr_key", line);
+ errors++;
+ }
+ } 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);
+ errors++;
+ } else {
+ 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);
+ errors++;
+ } 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_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 */
+#endif /* EAP_SERVER */
+ } else if (os_strcmp(buf, "eap_message") == 0) {
+ char *term;
+ 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);
+ errors++;
+ continue;
+ }
+ 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, "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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "nas_identifier") == 0) {
+ bss->nas_identifier = os_strdup(pos);
+#ifndef CONFIG_NO_RADIUS
+ } 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ 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);
+#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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ } else {
+ os_free(bss->ssid.wpa_passphrase);
+ bss->ssid.wpa_passphrase = os_strdup(pos);
+ }
+ } else if (os_strcmp(buf, "wpa_psk") == 0) {
+ os_free(bss->ssid.wpa_psk);
+ bss->ssid.wpa_psk =
+ os_zalloc(sizeof(struct hostapd_wpa_psk));
+ if (bss->ssid.wpa_psk == NULL)
+ errors++;
+ else 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);
+ errors++;
+ } else {
+ bss->ssid.wpa_psk->group = 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);
+ errors++;
+ }
+ } 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)
+ errors++;
+ } 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)
+ errors++;
+ else 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);
+ errors++;
+ }
+ } 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)
+ errors++;
+ else 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);
+ errors++;
+ }
+#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) {
+ 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_DEBUG, "Line %d: Invalid "
+ "mobility_domain '%s'", line, pos);
+ errors++;
+ continue;
+ }
+ } 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_DEBUG, "Line %d: Invalid "
+ "r1_key_holder '%s'", line, pos);
+ errors++;
+ continue;
+ }
+ } 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);
+ errors++;
+ continue;
+ }
+ } else if (os_strcmp(buf, "r1kh") == 0) {
+ if (add_r1kh(bss, pos) < 0) {
+ wpa_printf(MSG_DEBUG, "Line %d: Invalid "
+ "r1kh '%s'", line, pos);
+ errors++;
+ continue;
+ }
+ } else if (os_strcmp(buf, "pmk_r1_push") == 0) {
+ bss->pmk_r1_push = 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);
+ continue;
+ }
+
+ /* 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);
+ errors++;
+ continue;
+ }
+ 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_ipv6") == 0) {
+ bss->radius_server_ipv6 = atoi(pos);
+#endif /* RADIUS_SERVER */
+ } else if (os_strcmp(buf, "test_socket") == 0) {
+ os_free(bss->test_socket);
+ bss->test_socket = os_strdup(pos);
+ } 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 {
+ wpa_printf(MSG_ERROR, "Line %d: unknown "
+ "hw_mode '%s'", line, pos);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "channel") == 0) {
+ conf->channel = atoi(pos);
+ } 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);
+ errors++;
+ } else
+ conf->beacon_int = val;
+ } 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);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "rts_threshold") == 0) {
+ conf->rts_threshold = atoi(pos);
+ if (conf->rts_threshold < 0 ||
+ conf->rts_threshold > 2347) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid "
+ "rts_threshold %d",
+ line, conf->rts_threshold);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "fragm_threshold") == 0) {
+ conf->fragm_threshold = atoi(pos);
+ if (conf->fragm_threshold < 256 ||
+ conf->fragm_threshold > 2346) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid "
+ "fragm_threshold %d",
+ line, conf->fragm_threshold);
+ errors++;
+ }
+ } 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);
+ } else
+ conf->send_probe_response = val;
+ } else if (os_strcmp(buf, "supported_rates") == 0) {
+ if (hostapd_parse_rates(&conf->supported_rates, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid rate "
+ "list", line);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "basic_rates") == 0) {
+ if (hostapd_parse_rates(&conf->basic_rates, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid rate "
+ "list", line);
+ errors++;
+ }
+ } 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, "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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+#ifndef CONFIG_NO_VLAN
+ } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
+ bss->ssid.dynamic_vlan = 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);
+ errors++;
+ }
+#ifdef CONFIG_FULL_DYNAMIC_VLAN
+ } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) {
+ 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);
+ errors++;
+ }
+ } 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, buf, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
+ "ac item", line);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "bss") == 0) {
+ if (hostapd_config_bss(conf, pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid bss "
+ "item", line);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "bssid") == 0) {
+ if (hwaddr_aton(pos, bss->bssid)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid bssid "
+ "item", line);
+ errors++;
+ }
+#ifdef CONFIG_IEEE80211W
+ } else if (os_strcmp(buf, "ieee80211w") == 0) {
+ bss->ieee80211w = atoi(pos);
+ } 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+#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);
+ errors++;
+ }
+#endif /* CONFIG_IEEE80211N */
+ } else if (os_strcmp(buf, "max_listen_interval") == 0) {
+ bss->max_listen_interval = 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ } 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) > 32) {
+ wpa_printf(MSG_ERROR, "Line %d: Too long "
+ "device_name", line);
+ errors++;
+ }
+ 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);
+ errors++;
+ }
+ 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);
+ errors++;
+ }
+ 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);
+ errors++;
+ }
+ 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);
+ errors++;
+ }
+ os_free(bss->serial_number);
+ bss->serial_number = os_strdup(pos);
+ } else if (os_strcmp(buf, "device_type") == 0) {
+ os_free(bss->device_type);
+ bss->device_type = os_strdup(pos);
+ } 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ } 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);
+ errors++;
+ }
+ } else if (os_strcmp(buf, "upnp_iface") == 0) {
+ 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);
+#endif /* CONFIG_WPS */
+ } else {
+ wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
+ "item '%s'", line, buf);
+ errors++;
+ }
+ }
+
+ fclose(f);
+
+ for (i = 0; i < conf->num_bss; i++) {
+ bss = &conf->bss[i];
+
+ 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;
+ }
+
+ /* Select group cipher based on the enabled pairwise cipher
+ * suites */
+ pairwise = 0;
+ if (bss->wpa & 1)
+ pairwise |= bss->wpa_pairwise;
+ if (bss->wpa & 2) {
+ if (bss->rsn_pairwise == 0)
+ bss->rsn_pairwise = bss->wpa_pairwise;
+ pairwise |= bss->rsn_pairwise;
+ }
+ if (pairwise & WPA_CIPHER_TKIP)
+ bss->wpa_group = WPA_CIPHER_TKIP;
+ else
+ bss->wpa_group = WPA_CIPHER_CCMP;
+
+ 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) {
+ bss->ssid.security_policy = SECURITY_IEEE_802_1X;
+ bss->ssid.wep.default_len = bss->default_wep_key_len;
+ } else if (bss->ssid.wep.keys_set)
+ bss->ssid.security_policy = SECURITY_STATIC_WEP;
+ else
+ bss->ssid.security_policy = SECURITY_PLAINTEXT;
+ }
+
+ if (hostapd_config_check(conf))
+ errors++;
+
+ if (errors) {
+ wpa_printf(MSG_ERROR, "%d errors found in configuration file "
+ "'%s'", errors, fname);
+ hostapd_config_free(conf);
+ conf = NULL;
+ }
+
+ return conf;
+}
diff --git a/hostapd/config_file.h b/hostapd/config_file.h
new file mode 100644
index 000000000000..7111a9a3167f
--- /dev/null
+++ b/hostapd/config_file.h
@@ -0,0 +1,20 @@
+/*
+ * hostapd / Configuration file parser
+ * Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef CONFIG_FILE_H
+#define CONFIG_FILE_H
+
+struct hostapd_config * hostapd_config_read(const char *fname);
+
+#endif /* CONFIG_FILE_H */
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
new file mode 100644
index 000000000000..9c47ba8bb76d
--- /dev/null
+++ b/hostapd/ctrl_iface.c
@@ -0,0 +1,726 @@
+/*
+ * hostapd / UNIX domain socket -based control interface
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "utils/includes.h"
+
+#ifndef CONFIG_NATIVE_WINDOWS
+
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <stddef.h>
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "common/ieee802_11_defs.h"
+#include "drivers/driver.h"
+#include "radius/radius_client.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/accounting.h"
+#include "ap/wps_hostapd.h"
+#include "ap/ctrl_iface_ap.h"
+#include "ctrl_iface.h"
+
+
+struct wpa_ctrl_dst {
+ struct wpa_ctrl_dst *next;
+ struct sockaddr_un addr;
+ socklen_t addrlen;
+ int debug_level;
+ int errors;
+};
+
+
+static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ const char *buf, size_t len);
+
+
+static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
+ struct sockaddr_un *from,
+ socklen_t fromlen)
+{
+ struct wpa_ctrl_dst *dst;
+
+ dst = os_zalloc(sizeof(*dst));
+ if (dst == NULL)
+ return -1;
+ os_memcpy(&dst->addr, from, sizeof(struct sockaddr_un));
+ dst->addrlen = fromlen;
+ dst->debug_level = MSG_INFO;
+ dst->next = hapd->ctrl_dst;
+ hapd->ctrl_dst = dst;
+ wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
+ (u8 *) from->sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path));
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_detach(struct hostapd_data *hapd,
+ struct sockaddr_un *from,
+ socklen_t fromlen)
+{
+ struct wpa_ctrl_dst *dst, *prev = NULL;
+
+ dst = hapd->ctrl_dst;
+ while (dst) {
+ if (fromlen == dst->addrlen &&
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
+ if (prev == NULL)
+ hapd->ctrl_dst = dst->next;
+ else
+ prev->next = dst->next;
+ os_free(dst);
+ wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
+ (u8 *) from->sun_path,
+ fromlen -
+ offsetof(struct sockaddr_un, sun_path));
+ return 0;
+ }
+ prev = dst;
+ dst = dst->next;
+ }
+ return -1;
+}
+
+
+static int hostapd_ctrl_iface_level(struct hostapd_data *hapd,
+ struct sockaddr_un *from,
+ socklen_t fromlen,
+ char *level)
+{
+ struct wpa_ctrl_dst *dst;
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
+
+ dst = hapd->ctrl_dst;
+ while (dst) {
+ if (fromlen == dst->addrlen &&
+ os_memcmp(from->sun_path, dst->addr.sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path))
+ == 0) {
+ wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
+ "level", (u8 *) from->sun_path, fromlen -
+ offsetof(struct sockaddr_un, sun_path));
+ dst->debug_level = atoi(level);
+ return 0;
+ }
+ dst = dst->next;
+ }
+
+ return -1;
+}
+
+
+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;
+}
+
+
+static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd,
+ const char *txtaddr)
+{
+ u8 addr[ETH_ALEN];
+ struct sta_info *sta;
+ const char *pos;
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr);
+
+ if (hwaddr_aton(txtaddr, addr))
+ return -1;
+
+ pos = os_strstr(txtaddr, " test=");
+ if (pos) {
+ struct ieee80211_mgmt mgmt;
+ int encrypt;
+ if (hapd->driver->send_frame == NULL)
+ 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(WLAN_REASON_PREV_AUTH_NOT_VALID);
+ if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
+ IEEE80211_HDRLEN +
+ sizeof(mgmt.u.deauth),
+ encrypt) < 0)
+ return -1;
+ return 0;
+ }
+
+ hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
+ sta = ap_get_sta(hapd, addr);
+ if (sta)
+ ap_sta_deauthenticate(hapd, sta,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+
+ return 0;
+}
+
+
+static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd,
+ const char *txtaddr)
+{
+ u8 addr[ETH_ALEN];
+ struct sta_info *sta;
+ const char *pos;
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr);
+
+ if (hwaddr_aton(txtaddr, addr))
+ return -1;
+
+ pos = os_strstr(txtaddr, " test=");
+ if (pos) {
+ struct ieee80211_mgmt mgmt;
+ int encrypt;
+ if (hapd->driver->send_frame == NULL)
+ 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(WLAN_REASON_PREV_AUTH_NOT_VALID);
+ if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt,
+ IEEE80211_HDRLEN +
+ sizeof(mgmt.u.deauth),
+ encrypt) < 0)
+ return -1;
+ return 0;
+ }
+
+ hapd->drv.sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
+ sta = ap_get_sta(hapd, addr);
+ if (sta)
+ ap_sta_disassociate(hapd, sta,
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
+
+ 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;
+
+ if (pin == NULL)
+ return -1;
+ *pin++ = '\0';
+
+ timeout_txt = os_strchr(pin, ' ');
+ if (timeout_txt) {
+ *timeout_txt++ = '\0';
+ timeout = atoi(timeout_txt);
+ } else
+ timeout = 0;
+
+ return hostapd_wps_add_pin(hapd, txt, pin, timeout);
+}
+
+
+#ifdef CONFIG_WPS_OOB
+static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt)
+{
+ char *path, *method, *name;
+
+ path = os_strchr(txt, ' ');
+ if (path == NULL)
+ return -1;
+ *path++ = '\0';
+
+ method = os_strchr(path, ' ');
+ if (method == NULL)
+ return -1;
+ *method++ = '\0';
+
+ name = os_strchr(method, ' ');
+ if (name != NULL)
+ *name++ = '\0';
+
+ return hostapd_wps_start_oob(hapd, txt, path, method, name);
+}
+#endif /* CONFIG_WPS_OOB */
+
+
+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;
+}
+#endif /* CONFIG_WPS */
+
+
+static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
+ void *sock_ctx)
+{
+ struct hostapd_data *hapd = eloop_ctx;
+ char buf[256];
+ int res;
+ struct sockaddr_un from;
+ socklen_t fromlen = sizeof(from);
+ char *reply;
+ const int reply_size = 4096;
+ int reply_len;
+
+ res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
+ (struct sockaddr *) &from, &fromlen);
+ if (res < 0) {
+ perror("recvfrom(ctrl_iface)");
+ return;
+ }
+ buf[res] = '\0';
+ wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res);
+
+ reply = os_malloc(reply_size);
+ if (reply == NULL) {
+ sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
+ fromlen);
+ return;
+ }
+
+ 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_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_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_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_strcmp(buf, "WPS_PBC") == 0) {
+ if (hostapd_wps_button_pushed(hapd))
+ reply_len = -1;
+#ifdef CONFIG_WPS_OOB
+ } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
+ if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8))
+ reply_len = -1;
+#endif /* CONFIG_WPS_OOB */
+ } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) {
+ reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11,
+ reply, reply_size);
+#endif /* CONFIG_WPS */
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+ }
+
+ if (reply_len < 0) {
+ os_memcpy(reply, "FAIL\n", 5);
+ reply_len = 5;
+ }
+ sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
+ os_free(reply);
+}
+
+
+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;
+}
+
+
+static void hostapd_ctrl_iface_msg_cb(void *ctx, int level,
+ const char *txt, size_t len)
+{
+ struct hostapd_data *hapd = ctx;
+ if (hapd == NULL)
+ return;
+ hostapd_ctrl_iface_send(hapd, level, txt, len);
+}
+
+
+int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
+{
+ struct sockaddr_un addr;
+ int s = -1;
+ char *fname = NULL;
+
+ hapd->ctrl_sock = -1;
+
+ 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 {
+ perror("mkdir[ctrl_interface]");
+ goto fail;
+ }
+ }
+
+ if (hapd->conf->ctrl_interface_gid_set &&
+ chown(hapd->conf->ctrl_interface, 0,
+ hapd->conf->ctrl_interface_gid) < 0) {
+ perror("chown[ctrl_interface]");
+ return -1;
+ }
+
+ 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) {
+ perror("socket(PF_UNIX)");
+ 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) {
+ perror("unlink[ctrl_iface]");
+ wpa_printf(MSG_ERROR, "Could not unlink "
+ "existing ctrl_iface socket '%s'",
+ fname);
+ goto fail;
+ }
+ if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
+ 0) {
+ perror("bind(PF_UNIX)");
+ 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, 0, hapd->conf->ctrl_interface_gid) < 0) {
+ perror("chown[ctrl_interface/ifname]");
+ goto fail;
+ }
+
+ if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
+ perror("chmod[ctrl_interface/ifname]");
+ goto fail;
+ }
+ os_free(fname);
+
+ hapd->ctrl_sock = s;
+ eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd,
+ NULL);
+ 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;
+}
+
+
+void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
+{
+ struct wpa_ctrl_dst *dst, *prev;
+
+ if (hapd->ctrl_sock > -1) {
+ char *fname;
+ eloop_unregister_read_sock(hapd->ctrl_sock);
+ close(hapd->ctrl_sock);
+ hapd->ctrl_sock = -1;
+ 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 {
+ perror("rmdir[ctrl_interface]");
+ }
+ }
+ }
+
+ dst = hapd->ctrl_dst;
+ while (dst) {
+ prev = dst;
+ dst = dst->next;
+ os_free(prev);
+ }
+}
+
+
+static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
+ const char *buf, size_t len)
+{
+ struct wpa_ctrl_dst *dst, *next;
+ struct msghdr msg;
+ int idx;
+ struct iovec io[2];
+ char levelstr[10];
+
+ dst = hapd->ctrl_dst;
+ if (hapd->ctrl_sock < 0 || dst == NULL)
+ 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;
+ while (dst) {
+ next = dst->next;
+ if (level >= dst->debug_level) {
+ wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
+ (u8 *) dst->addr.sun_path, dst->addrlen -
+ offsetof(struct sockaddr_un, sun_path));
+ msg.msg_name = &dst->addr;
+ msg.msg_namelen = dst->addrlen;
+ if (sendmsg(hapd->ctrl_sock, &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) {
+ hostapd_ctrl_iface_detach(
+ hapd, &dst->addr,
+ dst->addrlen);
+ }
+ } else
+ dst->errors = 0;
+ }
+ idx++;
+ dst = next;
+ }
+}
+
+#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/hostapd/ctrl_iface.h b/hostapd/ctrl_iface.h
new file mode 100644
index 000000000000..c997141a1510
--- /dev/null
+++ b/hostapd/ctrl_iface.h
@@ -0,0 +1,32 @@
+/*
+ * hostapd / UNIX domain socket -based control interface
+ * Copyright (c) 2004, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING 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);
+#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)
+{
+}
+#endif /* CONFIG_NO_CTRL_IFACE */
+
+#endif /* CTRL_IFACE_H */
diff --git a/hostapd/defconfig b/hostapd/defconfig
new file mode 100644
index 000000000000..1d28c022fa46
--- /dev/null
+++ b/hostapd/defconfig
@@ -0,0 +1,175 @@
+# 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 madwifi driver
+#CONFIG_DRIVER_MADWIFI=y
+#CFLAGS += -I../../madwifi # change to the madwifi source directory
+
+# 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
+
+# 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., madwifi or 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
+
+# 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 state into a file on SIGUSR1 signal
+# 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
diff --git a/hostapd/dump_state.c b/hostapd/dump_state.c
new file mode 100644
index 000000000000..bba3068ccd81
--- /dev/null
+++ b/hostapd/dump_state.c
@@ -0,0 +1,184 @@
+/*
+ * hostapd / State dump
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+#include "radius/radius_client.h"
+#include "radius/radius_server.h"
+#include "eapol_auth/eapol_auth_sm.h"
+#include "eapol_auth/eapol_auth_sm_i.h"
+#include "eap_server/eap.h"
+#include "ap/hostapd.h"
+#include "ap/ap_config.h"
+#include "ap/sta_info.h"
+#include "dump_state.h"
+
+
+static void fprint_char(FILE *f, char c)
+{
+ if (c >= 32 && c < 127)
+ fprintf(f, "%c", c);
+ else
+ fprintf(f, "<%02x>", c);
+}
+
+
+static void ieee802_1x_dump_state(FILE *f, const char *prefix,
+ struct sta_info *sta)
+{
+ struct eapol_state_machine *sm = sta->eapol_sm;
+ if (sm == NULL)
+ return;
+
+ fprintf(f, "%sIEEE 802.1X:\n", prefix);
+
+ if (sm->identity) {
+ size_t i;
+ fprintf(f, "%sidentity=", prefix);
+ for (i = 0; i < sm->identity_len; i++)
+ fprint_char(f, sm->identity[i]);
+ fprintf(f, "\n");
+ }
+
+ fprintf(f, "%slast EAP type: Authentication Server: %d (%s) "
+ "Supplicant: %d (%s)\n", prefix,
+ sm->eap_type_authsrv,
+ eap_server_get_name(0, sm->eap_type_authsrv),
+ sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp));
+
+ fprintf(f, "%scached_packets=%s\n", prefix,
+ sm->last_recv_radius ? "[RX RADIUS]" : "");
+
+ eapol_auth_dump_state(f, prefix, sm);
+}
+
+
+/**
+ * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file
+ */
+static void hostapd_dump_state(struct hostapd_data *hapd)
+{
+ FILE *f;
+ time_t now;
+ struct sta_info *sta;
+ int i;
+#ifndef CONFIG_NO_RADIUS
+ char *buf;
+#endif /* CONFIG_NO_RADIUS */
+
+ if (!hapd->conf->dump_log_name) {
+ wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump "
+ "request");
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'",
+ hapd->conf->dump_log_name);
+ f = fopen(hapd->conf->dump_log_name, "w");
+ if (f == NULL) {
+ wpa_printf(MSG_WARNING, "Could not open dump file '%s' for "
+ "writing.", hapd->conf->dump_log_name);
+ return;
+ }
+
+ time(&now);
+ fprintf(f, "hostapd state dump - %s", ctime(&now));
+ fprintf(f, "num_sta=%d num_sta_non_erp=%d "
+ "num_sta_no_short_slot_time=%d\n"
+ "num_sta_no_short_preamble=%d\n",
+ hapd->num_sta, hapd->iface->num_sta_non_erp,
+ hapd->iface->num_sta_no_short_slot_time,
+ hapd->iface->num_sta_no_short_preamble);
+
+ for (sta = hapd->sta_list; sta != NULL; sta = sta->next) {
+ fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr));
+
+ fprintf(f,
+ " AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
+ " capability=0x%x listen_interval=%d\n",
+ sta->aid,
+ sta->flags,
+ (sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""),
+ (sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""),
+ (sta->flags & WLAN_STA_PS ? "[PS]" : ""),
+ (sta->flags & WLAN_STA_TIM ? "[TIM]" : ""),
+ (sta->flags & WLAN_STA_PERM ? "[PERM]" : ""),
+ (sta->flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" :
+ ""),
+ (sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" :
+ ""),
+ (sta->flags & WLAN_STA_SHORT_PREAMBLE ?
+ "[SHORT_PREAMBLE]" : ""),
+ (sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""),
+ (sta->flags & WLAN_STA_WMM ? "[WMM]" : ""),
+ (sta->flags & WLAN_STA_MFP ? "[MFP]" : ""),
+ (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""),
+ (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""),
+ (sta->flags & WLAN_STA_WDS ? "[WDS]" : ""),
+ (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""),
+ sta->capability,
+ sta->listen_interval);
+
+ fprintf(f, " supported_rates=");
+ for (i = 0; i < sta->supported_rates_len; i++)
+ fprintf(f, "%02x ", sta->supported_rates[i]);
+ fprintf(f, "\n");
+
+ fprintf(f,
+ " timeout_next=%s\n",
+ (sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" :
+ (sta->timeout_next == STA_DISASSOC ? "DISASSOC" :
+ "DEAUTH")));
+
+ ieee802_1x_dump_state(f, " ", sta);
+ }
+
+#ifndef CONFIG_NO_RADIUS
+ buf = os_malloc(4096);
+ if (buf) {
+ int count = radius_client_get_mib(hapd->radius, buf, 4096);
+ if (count < 0)
+ count = 0;
+ else if (count > 4095)
+ count = 4095;
+ buf[count] = '\0';
+ fprintf(f, "%s", buf);
+
+#ifdef RADIUS_SERVER
+ count = radius_server_get_mib(hapd->radius_srv, buf, 4096);
+ if (count < 0)
+ count = 0;
+ else if (count > 4095)
+ count = 4095;
+ buf[count] = '\0';
+ fprintf(f, "%s", buf);
+#endif /* RADIUS_SERVER */
+
+ os_free(buf);
+ }
+#endif /* CONFIG_NO_RADIUS */
+ fclose(f);
+}
+
+
+int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx)
+{
+ size_t i;
+
+ for (i = 0; i < iface->num_bss; i++)
+ hostapd_dump_state(iface->bss[i]);
+
+ return 0;
+}
diff --git a/hostapd/dump_state.h b/hostapd/dump_state.h
new file mode 100644
index 000000000000..e14f08a4f5e1
--- /dev/null
+++ b/hostapd/dump_state.h
@@ -0,0 +1,20 @@
+/*
+ * hostapd / State dump
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef DUMP_STATE_H
+#define DUMP_STATE_H
+
+int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx);
+
+#endif /* DUMP_STATE_H */
diff --git a/hostapd/eap_register.c b/hostapd/eap_register.c
new file mode 100644
index 000000000000..ae9bf9d38de9
--- /dev/null
+++ b/hostapd/eap_register.c
@@ -0,0 +1,134 @@
+/*
+ * EAP method registration
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING 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_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 */
+
+ return ret;
+}
diff --git a/hostapd/eap_register.h b/hostapd/eap_register.h
new file mode 100644
index 000000000000..82e7171d6fde
--- /dev/null
+++ b/hostapd/eap_register.h
@@ -0,0 +1,20 @@
+/*
+ * EAP method registration
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef EAP_REGISTER_H
+#define EAP_REGISTER_H
+
+int eap_server_register_methods(void);
+
+#endif /* EAP_REGISTER_H */
diff --git a/hostapd/eap_testing.txt b/hostapd/eap_testing.txt
new file mode 100644
index 000000000000..04468c39f01e
--- /dev/null
+++ b/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?)
diff --git a/hostapd/hlr_auc_gw.c b/hostapd/hlr_auc_gw.c
new file mode 100644
index 000000000000..36934aa9728a
--- /dev/null
+++ b/hostapd/hlr_auc_gw.c
@@ -0,0 +1,714 @@
+/*
+ * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator
+ * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING 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
+ *
+ * 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.
+ *
+ * The 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 testing.
+ */
+
+#include "includes.h"
+#include <sys/un.h>
+
+#include "common.h"
+#include "crypto/milenage.h"
+
+static const char *default_socket_path = "/tmp/hlr_auc_gw.sock";
+static const char *socket_path;
+static int serv_sock = -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];
+};
+
+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_MAX_LEN 16
+#define EAP_AKA_IK_LEN 16
+#define EAP_AKA_CK_LEN 16
+
+
+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("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 tripler 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 = strchr(pos, ':');
+ if (pos2 == NULL) {
+ printf("%s:%d - Invalid IMSI (%s)\n",
+ fname, line, pos);
+ ret = -1;
+ break;
+ }
+ *pos2 = '\0';
+ if (strlen(pos) >= sizeof(g->imsi)) {
+ printf("%s:%d - Too long IMSI (%s)\n",
+ fname, line, pos);
+ ret = -1;
+ break;
+ }
+ os_strlcpy(g->imsi, pos, sizeof(g->imsi));
+ pos = pos2 + 1;
+
+ /* Kc */
+ pos2 = strchr(pos, ':');
+ if (pos2 == NULL) {
+ printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
+ ret = -1;
+ break;
+ }
+ *pos2 = '\0';
+ if (strlen(pos) != 16 || hexstr2bin(pos, g->kc, 8)) {
+ printf("%s:%d - Invalid Kc (%s)\n", fname, line, pos);
+ ret = -1;
+ break;
+ }
+ pos = pos2 + 1;
+
+ /* SRES */
+ pos2 = strchr(pos, ':');
+ if (pos2 == NULL) {
+ printf("%s:%d - Invalid SRES (%s)\n", fname, line,
+ pos);
+ ret = -1;
+ break;
+ }
+ *pos2 = '\0';
+ if (strlen(pos) != 8 || hexstr2bin(pos, g->sres, 4)) {
+ printf("%s:%d - Invalid SRES (%s)\n", fname, line,
+ pos);
+ ret = -1;
+ break;
+ }
+ pos = pos2 + 1;
+
+ /* RAND */
+ pos2 = strchr(pos, ':');
+ if (pos2)
+ *pos2 = '\0';
+ if (strlen(pos) != 32 || hexstr2bin(pos, g->_rand, 16)) {
+ printf("%s:%d - Invalid RAND (%s)\n", fname, line,
+ pos);
+ ret = -1;
+ break;
+ }
+ pos = pos2 + 1;
+
+ g->next = gsm_db;
+ gsm_db = g;
+ g = NULL;
+ }
+ 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 */
+ 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 = strchr(pos, ' ');
+ if (pos2 == NULL) {
+ printf("%s:%d - Invalid IMSI (%s)\n",
+ fname, line, pos);
+ ret = -1;
+ break;
+ }
+ *pos2 = '\0';
+ if (strlen(pos) >= sizeof(m->imsi)) {
+ printf("%s:%d - Too long IMSI (%s)\n",
+ fname, line, pos);
+ ret = -1;
+ break;
+ }
+ os_strlcpy(m->imsi, pos, sizeof(m->imsi));
+ pos = pos2 + 1;
+
+ /* Ki */
+ pos2 = strchr(pos, ' ');
+ if (pos2 == NULL) {
+ printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
+ ret = -1;
+ break;
+ }
+ *pos2 = '\0';
+ if (strlen(pos) != 32 || hexstr2bin(pos, m->ki, 16)) {
+ printf("%s:%d - Invalid Ki (%s)\n", fname, line, pos);
+ ret = -1;
+ break;
+ }
+ pos = pos2 + 1;
+
+ /* OPc */
+ pos2 = strchr(pos, ' ');
+ if (pos2 == NULL) {
+ printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
+ ret = -1;
+ break;
+ }
+ *pos2 = '\0';
+ if (strlen(pos) != 32 || hexstr2bin(pos, m->opc, 16)) {
+ printf("%s:%d - Invalid OPc (%s)\n", fname, line, pos);
+ ret = -1;
+ break;
+ }
+ pos = pos2 + 1;
+
+ /* AMF */
+ pos2 = strchr(pos, ' ');
+ if (pos2 == NULL) {
+ printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
+ ret = -1;
+ break;
+ }
+ *pos2 = '\0';
+ if (strlen(pos) != 4 || hexstr2bin(pos, m->amf, 2)) {
+ printf("%s:%d - Invalid AMF (%s)\n", fname, line, pos);
+ ret = -1;
+ break;
+ }
+ pos = pos2 + 1;
+
+ /* SQN */
+ pos2 = strchr(pos, ' ');
+ if (pos2)
+ *pos2 = '\0';
+ if (strlen(pos) != 12 || hexstr2bin(pos, m->sqn, 6)) {
+ printf("%s:%d - Invalid SEQ (%s)\n", fname, line, pos);
+ ret = -1;
+ break;
+ }
+ pos = pos2 + 1;
+
+ m->next = milenage_db;
+ milenage_db = m;
+ m = NULL;
+ }
+ free(m);
+
+ fclose(f);
+
+ return ret;
+}
+
+
+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;
+ }
+
+ return m;
+}
+
+
+static void sim_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
+ char *imsi)
+{
+ int count, max_chal, ret;
+ char *pos;
+ char reply[1000], *rpos, *rend;
+ struct milenage_parameters *m;
+ struct gsm_triplet *g;
+
+ reply[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 = &reply[sizeof(reply)];
+ rpos = reply;
+ ret = snprintf(rpos, rend - rpos, "SIM-RESP-AUTH %s", imsi);
+ if (ret < 0 || ret >= rend - rpos)
+ return;
+ rpos += ret;
+
+ m = get_milenage(imsi);
+ if (m) {
+ u8 _rand[16], sres[4], kc[8];
+ for (count = 0; count < max_chal; count++) {
+ if (os_get_random(_rand, 16) < 0)
+ return;
+ 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';
+ goto send;
+ }
+
+ 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;
+ rpos += ret;
+ }
+
+send:
+ printf("Send: %s\n", reply);
+ if (sendto(s, reply, rpos - reply, 0,
+ (struct sockaddr *) from, fromlen) < 0)
+ perror("send");
+}
+
+
+static void aka_req_auth(int s, struct sockaddr_un *from, socklen_t fromlen,
+ char *imsi)
+{
+ /* AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */
+ char reply[1000], *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;
+
+ m = get_milenage(imsi);
+ if (m) {
+ if (os_get_random(_rand, EAP_AKA_RAND_LEN) < 0)
+ return;
+ res_len = EAP_AKA_RES_MAX_LEN;
+ inc_byte_array(m->sqn, 6);
+ 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);
+ } 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 */
+ return;
+#endif /* AKA_USE_FIXED_TEST_VALUES */
+ }
+
+ pos = reply;
+ end = &reply[sizeof(reply)];
+ ret = snprintf(pos, end - pos, "AKA-RESP-AUTH %s ", imsi);
+ if (ret < 0 || ret >= end - pos)
+ return;
+ pos += ret;
+ 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);
+
+ printf("Send: %s\n", reply);
+
+ if (sendto(s, reply, pos - reply, 0, (struct sockaddr *) from,
+ fromlen) < 0)
+ perror("send");
+}
+
+
+static void aka_auts(int s, struct sockaddr_un *from, socklen_t fromlen,
+ char *imsi)
+{
+ char *auts, *__rand;
+ u8 _auts[EAP_AKA_AUTS_LEN], _rand[EAP_AKA_RAND_LEN], sqn[6];
+ struct milenage_parameters *m;
+
+ /* AKA-AUTS <IMSI> <AUTS> <RAND> */
+
+ auts = strchr(imsi, ' ');
+ if (auts == NULL)
+ return;
+ *auts++ = '\0';
+
+ __rand = strchr(auts, ' ');
+ if (__rand == NULL)
+ return;
+ *__rand++ = '\0';
+
+ 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;
+ }
+
+ m = get_milenage(imsi);
+ if (m == NULL) {
+ printf("Unknown IMSI: %s\n", imsi);
+ return;
+ }
+
+ if (milenage_auts(m->opc, m->ki, _rand, _auts, sqn)) {
+ printf("AKA-AUTS: Incorrect MAC-S\n");
+ } else {
+ memcpy(m->sqn, sqn, 6);
+ 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]);
+ }
+}
+
+
+static int process(int s)
+{
+ char buf[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 (strncmp(buf, "SIM-REQ-AUTH ", 13) == 0)
+ sim_req_auth(s, &from, fromlen, buf + 13);
+ else if (strncmp(buf, "AKA-REQ-AUTH ", 13) == 0)
+ aka_req_auth(s, &from, fromlen, buf + 13);
+ else if (strncmp(buf, "AKA-AUTS ", 9) == 0)
+ aka_auts(s, &from, fromlen, buf + 9);
+ else
+ printf("Unknown request: %s\n", buf);
+
+ return 0;
+}
+
+
+static void cleanup(void)
+{
+ struct gsm_triplet *g, *gprev;
+ struct milenage_parameters *m, *prev;
+
+ g = gsm_db;
+ while (g) {
+ gprev = g;
+ g = g->next;
+ free(gprev);
+ }
+
+ m = milenage_db;
+ while (m) {
+ prev = m;
+ m = m->next;
+ free(prev);
+ }
+
+ close(serv_sock);
+ unlink(socket_path);
+}
+
+
+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-2007, Jouni Malinen <j@w1.fi>\n"
+ "\n"
+ "usage:\n"
+ "hlr_auc_gw [-h] [-s<socket path>] [-g<triplet file>] "
+ "[-m<milenage file>]\n"
+ "\n"
+ "options:\n"
+ " -h = show this usage help\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",
+ default_socket_path);
+}
+
+
+int main(int argc, char *argv[])
+{
+ int c;
+ char *milenage_file = NULL;
+ char *gsm_triplet_file = NULL;
+
+ socket_path = default_socket_path;
+
+ for (;;) {
+ c = getopt(argc, argv, "g:hm:s:");
+ if (c < 0)
+ break;
+ switch (c) {
+ case 'g':
+ gsm_triplet_file = optarg;
+ break;
+ case 'h':
+ usage();
+ return 0;
+ case 'm':
+ milenage_file = optarg;
+ break;
+ case 's':
+ socket_path = optarg;
+ break;
+ default:
+ usage();
+ return -1;
+ }
+ }
+
+ if (gsm_triplet_file && read_gsm_triplets(gsm_triplet_file) < 0)
+ return -1;
+
+ if (milenage_file && read_milenage(milenage_file) < 0)
+ return -1;
+
+ 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);
+
+ return 0;
+}
diff --git a/hostapd/hlr_auc_gw.milenage_db b/hostapd/hlr_auc_gw.milenage_db
new file mode 100644
index 000000000000..ecd06d72096d
--- /dev/null
+++ b/hostapd/hlr_auc_gw.milenage_db
@@ -0,0 +1,13 @@
+# 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
+232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
+
+# 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
diff --git a/hostapd/hostapd.8 b/hostapd/hostapd.8
new file mode 100644
index 000000000000..b4456bbcf3e6
--- /dev/null
+++ b/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, madwifi, 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).
diff --git a/hostapd/hostapd.accept b/hostapd/hostapd.accept
new file mode 100644
index 000000000000..2d2a0a27efdc
--- /dev/null
+++ b/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
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
new file mode 100644
index 000000000000..b44a81868c83
--- /dev/null
+++ b/hostapd/hostapd.conf
@@ -0,0 +1,1016 @@
+##### 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); ath0 for madwifi
+interface=wlan0
+
+# In case of madwifi, 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/madwifi/test/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
+
+# 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
+
+# Dump file for state information (on SIGUSR1)
+dump_file=/tmp/hostapd.dump
+
+# 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
+
+# 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
+
+# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
+# Default: IEEE 802.11b
+hw_mode=a
+
+# Channel number (IEEE 802.11)
+# (default: 0, i.e., not set)
+# Please note that some drivers (e.g., madwifi) do not use this value from
+# hostapd and the channel will need to be configuration separately with
+# iwconfig.
+channel=60
+
+# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
+beacon_int=100
+
+# DTIM (delivery trafic 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; 2347 = disabled (default); range 0..2347
+# 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=2347
+
+# Fragmentation threshold; 2346 = disabled (default); range 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=2346
+
+# 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=madwifi.
+# 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
+
+# TX queue parameters (EDCF / bursting)
+# default for all these fields: not set, use hardware defaults
+# 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)
+# cwmax: cwMax (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023); 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
+#
+# Special queues; normally not user configurable
+#
+#tx_queue_after_beacon_aifs=2
+#tx_queue_after_beacon_cwmin=15
+#tx_queue_after_beacon_cwmax=1023
+#tx_queue_after_beacon_burst=0
+#
+#tx_queue_beacon_aifs=2
+#tx_queue_beacon_cwmin=3
+#tx_queue_beacon_cwmax=7
+#tx_queue_beacon_burst=1.5
+
+# 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
+#
+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
+
+# 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
+
+##### 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.
+#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 below 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)
+# PSMP support: [PSMP] (disabled if not set)
+# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)
+#ht_capab=[HT40-][SHORT-GI-20][SHORT-GI-40]
+
+##### 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
+
+##### 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
+#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
+
+# 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
+
+# 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 1024"
+#dh_file=/etc/hostapd.dh.pem
+
+# 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.
+#eap_sim_db=unix:/tmp/hlr_auc_gw.sock
+
+# 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
+
+
+##### 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
+
+# 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.
+# When using IEEE 802.11r, nas_identifier must be set and must be between 1 and
+# 48 octets long.
+#nas_identifier=ap.example.com
+
+# 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
+
+# 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). vlan_file option below must be configured if dynamic
+# VLANs are used. 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
+
+# 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).
+#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
+
+
+##### 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
+
+# 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.
+# 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
+
+# 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
+
+# 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
+
+
+# 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
+
+
+##### 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.
+#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
+
+##### 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
+
+
+##### Wi-Fi Protected Setup (WPS) #############################################
+
+# WPS state
+# 0 = WPS disabled (default)
+# 1 = WPS enabled, not configured
+# 2 = WPS enabled, configured
+#wps_state=2
+
+# 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
+#config_methods=label display push_button keypad
+
+# 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
+
+##### 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
+#
+# 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
+# ...
diff --git a/hostapd/hostapd.deny b/hostapd/hostapd.deny
new file mode 100644
index 000000000000..1616678f579e
--- /dev/null
+++ b/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
diff --git a/hostapd/hostapd.eap_user b/hostapd/hostapd.eap_user
new file mode 100644
index 000000000000..ac9a5d896a04
--- /dev/null
+++ b/hostapd/hostapd.eap_user
@@ -0,0 +1,91 @@
+# 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.
+
+# 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
+
+# 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]
diff --git a/hostapd/hostapd.radius_clients b/hostapd/hostapd.radius_clients
new file mode 100644
index 000000000000..3980427253b4
--- /dev/null
+++ b/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
diff --git a/hostapd/hostapd.sim_db b/hostapd/hostapd.sim_db
new file mode 100644
index 000000000000..01c593de8d2d
--- /dev/null
+++ b/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
diff --git a/hostapd/hostapd.vlan b/hostapd/hostapd.vlan
new file mode 100644
index 000000000000..98254fa84f01
--- /dev/null
+++ b/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#
diff --git a/hostapd/hostapd.wpa_psk b/hostapd/hostapd.wpa_psk
new file mode 100644
index 000000000000..0a9499acd736
--- /dev/null
+++ b/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
diff --git a/hostapd/hostapd_cli.1 b/hostapd/hostapd_cli.1
new file mode 100644
index 000000000000..218ea1588a4a
--- /dev/null
+++ b/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).
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
new file mode 100644
index 000000000000..589530e419fc
--- /dev/null
+++ b/hostapd/hostapd_cli.c
@@ -0,0 +1,904 @@
+/*
+ * hostapd - command line interface for hostapd daemon
+ * Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+#include <dirent.h>
+
+#include "common/wpa_ctrl.h"
+#include "common.h"
+#include "common/version.h"
+
+
+static const char *hostapd_cli_version =
+"hostapd_cli v" VERSION_STR "\n"
+"Copyright (c) 2004-2010, Jouni Malinen <j@w1.fi> and contributors";
+
+
+static const char *hostapd_cli_license =
+"This program is free software. You can distribute it and/or modify it\n"
+"under the terms of the GNU General Public License version 2.\n"
+"\n"
+"Alternatively, this software may be distributed under the terms of the\n"
+"BSD license. See README and COPYING for more details.\n";
+
+static const char *hostapd_cli_full_license =
+"This program is free software; you can redistribute it and/or modify\n"
+"it under the terms of the GNU General Public License version 2 as\n"
+"published by the Free Software Foundation.\n"
+"\n"
+"This program is distributed in the hope that it will be useful,\n"
+"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+"GNU General Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License\n"
+"along with this program; if not, write to the Free Software\n"
+"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
+"\n"
+"Alternatively, this software may be distributed under the terms of the\n"
+"BSD license.\n"
+"\n"
+"Redistribution and use in source and binary forms, with or without\n"
+"modification, are permitted provided that the following conditions are\n"
+"met:\n"
+"\n"
+"1. Redistributions of source code must retain the above copyright\n"
+" notice, this list of conditions and the following disclaimer.\n"
+"\n"
+"2. Redistributions in binary form must reproduce the above copyright\n"
+" notice, this list of conditions and the following disclaimer in the\n"
+" documentation and/or other materials provided with the distribution.\n"
+"\n"
+"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
+" names of its contributors may be used to endorse or promote products\n"
+" derived from this software without specific prior written permission.\n"
+"\n"
+"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
+"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
+"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
+"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
+"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
+"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
+"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
+"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
+"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
+"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
+"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
+"\n";
+
+static const char *commands_help =
+"Commands:\n"
+" mib get MIB variables (dot1x, dot11, radius)\n"
+" sta <addr> get MIB variables for one station\n"
+" all_sta get MIB variables for all stations\n"
+" new_sta <addr> add a new station\n"
+" deauthenticate <addr> deauthenticate a station\n"
+" disassociate <addr> disassociate a station\n"
+#ifdef CONFIG_IEEE80211W
+" sa_query <addr> send SA Query to a station\n"
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_WPS
+" wps_pin <uuid> <pin> [timeout] add WPS Enrollee PIN (Device Password)\n"
+" wps_pbc indicate button pushed to initiate PBC\n"
+#ifdef CONFIG_WPS_OOB
+" wps_oob <type> <path> <method> use WPS with out-of-band (UFD)\n"
+#endif /* CONFIG_WPS_OOB */
+" wps_ap_pin <cmd> [params..] enable/disable AP PIN\n"
+#endif /* CONFIG_WPS */
+" help show this usage help\n"
+" interface [ifname] show interfaces/select interface\n"
+" level <debug level> change debug level\n"
+" license show full hostapd_cli license\n"
+" quit exit hostapd_cli\n";
+
+static struct wpa_ctrl *ctrl_conn;
+static int hostapd_cli_quit = 0;
+static int hostapd_cli_attached = 0;
+static const char *ctrl_iface_dir = "/var/run/hostapd";
+static char *ctrl_ifname = NULL;
+static const char *pid_file = NULL;
+static const char *action_file = NULL;
+static int ping_interval = 5;
+
+
+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"
+ " [-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"
+ " -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"
+ "%s",
+ commands_help);
+}
+
+
+static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
+{
+ char *cfile;
+ int flen;
+
+ if (ifname == NULL)
+ return NULL;
+
+ 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);
+
+ ctrl_conn = wpa_ctrl_open(cfile);
+ free(cfile);
+ return ctrl_conn;
+}
+
+
+static void hostapd_cli_close_connection(void)
+{
+ if (ctrl_conn == NULL)
+ return;
+
+ 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_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "PING");
+}
+
+
+static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "MIB");
+}
+
+
+static int hostapd_cli_exec(const char *program, const char *arg1,
+ const char *arg2)
+{
+ char *cmd;
+ size_t len;
+ int res;
+ int ret = 0;
+
+ len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
+ cmd = os_malloc(len);
+ if (cmd == NULL)
+ return -1;
+ res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
+ if (res < 0 || (size_t) res >= len) {
+ os_free(cmd);
+ return -1;
+ }
+ cmd[len - 1] = '\0';
+#ifndef _WIN32_WCE
+ if (system(cmd) < 0)
+ ret = -1;
+#endif /* _WIN32_WCE */
+ os_free(cmd);
+
+ return ret;
+}
+
+
+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 - exactly one argument, STA "
+ "address, is required.\n");
+ return -1;
+ }
+ 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 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);
+}
+
+
+#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[64];
+ if (argc < 2) {
+ printf("Invalid 'wps_pin' command - at least two arguments, "
+ "UUID and PIN, are required.\n");
+ return -1;
+ }
+ 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_pbc(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "WPS_PBC");
+}
+
+
+#ifdef CONFIG_WPS_OOB
+static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char cmd[256];
+ int res;
+
+ if (argc != 3 && argc != 4) {
+ printf("Invalid WPS_OOB command: need three or four "
+ "arguments:\n"
+ "- DEV_TYPE: use 'ufd' or 'nfc'\n"
+ "- PATH: path of OOB device like '/mnt'\n"
+ "- METHOD: OOB method 'pin-e' or 'pin-r', "
+ "'cred'\n"
+ "- DEV_NAME: (only for NFC) device name like "
+ "'pn531'\n");
+ return -1;
+ }
+
+ if (argc == 3)
+ res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
+ argv[0], argv[1], argv[2]);
+ else
+ res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
+ argv[0], argv[1], argv[2], argv[3]);
+ if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ printf("Too long WPS_OOB command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+#endif /* CONFIG_WPS_OOB */
+
+
+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);
+}
+#endif /* CONFIG_WPS */
+
+
+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[])
+{
+ printf("%s", commands_help);
+ return 0;
+}
+
+
+static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
+ return 0;
+}
+
+
+static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ hostapd_cli_quit = 1;
+ 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_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();
+ free(ctrl_ifname);
+ ctrl_ifname = strdup(argv[0]);
+
+ 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;
+ } else {
+ printf("Warning: Failed to attach to "
+ "hostapd.\n");
+ }
+ } else {
+ printf("Could not connect to interface '%s' - re-trying\n",
+ ctrl_ifname);
+ }
+ return 0;
+}
+
+
+struct hostapd_cli_cmd {
+ const char *cmd;
+ int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
+};
+
+static struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ { "ping", hostapd_cli_cmd_ping },
+ { "mib", hostapd_cli_cmd_mib },
+ { "sta", hostapd_cli_cmd_sta },
+ { "all_sta", hostapd_cli_cmd_all_sta },
+ { "new_sta", hostapd_cli_cmd_new_sta },
+ { "deauthenticate", hostapd_cli_cmd_deauthenticate },
+ { "disassociate", hostapd_cli_cmd_disassociate },
+#ifdef CONFIG_IEEE80211W
+ { "sa_query", hostapd_cli_cmd_sa_query },
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_WPS
+ { "wps_pin", hostapd_cli_cmd_wps_pin },
+ { "wps_pbc", hostapd_cli_cmd_wps_pbc },
+#ifdef CONFIG_WPS_OOB
+ { "wps_oob", hostapd_cli_cmd_wps_oob },
+#endif /* CONFIG_WPS_OOB */
+ { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
+#endif /* CONFIG_WPS */
+ { "help", hostapd_cli_cmd_help },
+ { "interface", hostapd_cli_cmd_interface },
+ { "level", hostapd_cli_cmd_level },
+ { "license", hostapd_cli_cmd_license },
+ { "quit", hostapd_cli_cmd_quit },
+ { NULL, NULL }
+};
+
+
+static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ 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;
+ 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 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 {
+ 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_interactive(void)
+{
+ const int max_args = 10;
+ char cmd[256], *res, *argv[max_args], *pos;
+ int argc;
+
+ printf("\nInteractive mode\n\n");
+
+ do {
+ hostapd_cli_recv_pending(ctrl_conn, 0, 0);
+ printf("> ");
+ alarm(ping_interval);
+ res = fgets(cmd, sizeof(cmd), stdin);
+ alarm(0);
+ if (res == NULL)
+ break;
+ pos = cmd;
+ while (*pos != '\0') {
+ if (*pos == '\n') {
+ *pos = '\0';
+ break;
+ }
+ pos++;
+ }
+ argc = 0;
+ pos = cmd;
+ for (;;) {
+ while (*pos == ' ')
+ pos++;
+ if (*pos == '\0')
+ break;
+ argv[argc] = pos;
+ argc++;
+ if (argc == max_args)
+ break;
+ while (*pos != '\0' && *pos != ' ')
+ pos++;
+ if (*pos == ' ')
+ *pos++ = '\0';
+ }
+ if (argc)
+ wpa_request(ctrl_conn, argc, argv);
+ } while (!hostapd_cli_quit);
+}
+
+
+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_terminate(int sig)
+{
+ hostapd_cli_cleanup();
+ exit(0);
+}
+
+
+static void hostapd_cli_alarm(int sig)
+{
+ 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;
+ } else {
+ printf("Warning: Failed to attach to "
+ "hostapd.\n");
+ }
+ }
+ }
+ if (ctrl_conn)
+ hostapd_cli_recv_pending(ctrl_conn, 1, 0);
+ alarm(ping_interval);
+}
+
+
+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 interactive;
+ int warning_displayed = 0;
+ int c;
+ int daemonize = 0;
+
+ if (os_program_init())
+ return -1;
+
+ for (;;) {
+ c = getopt(argc, argv, "a:BhG:i:p: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;
+ default:
+ usage();
+ return -1;
+ }
+ }
+
+ interactive = (argc == optind) && (action_file == NULL);
+
+ if (interactive) {
+ printf("%s\n\n%s\n\n", hostapd_cli_version,
+ hostapd_cli_license);
+ }
+
+ 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;
+ }
+
+ signal(SIGINT, hostapd_cli_terminate);
+ signal(SIGTERM, hostapd_cli_terminate);
+ signal(SIGALRM, hostapd_cli_alarm);
+
+ if (interactive || action_file) {
+ if (wpa_ctrl_attach(ctrl_conn) == 0) {
+ hostapd_cli_attached = 1;
+ } else {
+ printf("Warning: Failed to attach to hostapd.\n");
+ if (action_file)
+ return -1;
+ }
+ }
+
+ if (daemonize && os_daemonize(pid_file))
+ 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]);
+
+ os_free(ctrl_ifname);
+ hostapd_cli_cleanup();
+ return 0;
+}
diff --git a/hostapd/logwatch/README b/hostapd/logwatch/README
new file mode 100644
index 000000000000..3cba51190963
--- /dev/null
+++ b/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/
diff --git a/hostapd/logwatch/hostapd b/hostapd/logwatch/hostapd
new file mode 100755
index 000000000000..97b24ef6e1b8
--- /dev/null
+++ b/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);
diff --git a/hostapd/logwatch/hostapd.conf b/hostapd/logwatch/hostapd.conf
new file mode 100644
index 000000000000..5bebe6ad2c1b
--- /dev/null
+++ b/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
diff --git a/hostapd/main.c b/hostapd/main.c
new file mode 100644
index 000000000000..9c532d4cce6e
--- /dev/null
+++ b/hostapd/main.c
@@ -0,0 +1,565 @@
+/*
+ * hostapd / main()
+ * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "utils/includes.h"
+#ifndef CONFIG_NATIVE_WINDOWS
+#include <syslog.h>
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+#include "utils/common.h"
+#include "utils/eloop.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 "config_file.h"
+#include "eap_register.h"
+#include "dump_state.h"
+#include "ctrl_iface.h"
+
+
+extern int wpa_debug_level;
+extern int wpa_debug_show_keys;
+extern int wpa_debug_timestamp;
+
+
+struct hapd_interfaces {
+ size_t count;
+ struct hostapd_iface **iface;
+};
+
+
+static 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;
+}
+
+
+#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, txt);
+ else if (hapd && hapd->conf)
+ os_snprintf(format, maxlen, "%s:%s%s %s",
+ hapd->conf->iface, module_str ? " " : "",
+ module_str, txt);
+ else if (addr)
+ os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s",
+ MAC2STR(addr), module_str ? " " : "",
+ module_str, txt);
+ else
+ os_snprintf(format, maxlen, "%s%s%s",
+ module_str, module_str ? ": " : "", txt);
+
+ if ((conf_stdout & module) && level >= conf_stdout_level) {
+ wpa_debug_print_timestamp();
+ printf("%s\n", 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_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().
+ */
+static struct hostapd_iface * hostapd_init(const char *config_file)
+{
+ struct hostapd_iface *hapd_iface = NULL;
+ struct hostapd_config *conf = NULL;
+ struct hostapd_data *hapd;
+ size_t i;
+
+ hapd_iface = os_zalloc(sizeof(*hapd_iface));
+ if (hapd_iface == NULL)
+ goto fail;
+
+ hapd_iface->reload_config = hostapd_reload_config;
+ hapd_iface->config_read_cb = hostapd_config_read;
+ hapd_iface->config_fname = os_strdup(config_file);
+ if (hapd_iface->config_fname == NULL)
+ goto fail;
+ hapd_iface->ctrl_iface_init = hostapd_ctrl_iface_init;
+ hapd_iface->ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
+ hapd_iface->for_each_interface = hostapd_for_each_interface;
+
+ conf = hostapd_config_read(hapd_iface->config_fname);
+ if (conf == NULL)
+ goto fail;
+ hapd_iface->conf = conf;
+
+ hapd_iface->num_bss = conf->num_bss;
+ hapd_iface->bss = os_zalloc(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:
+ if (conf)
+ hostapd_config_free(conf);
+ if (hapd_iface) {
+ os_free(hapd_iface->config_fname);
+ os_free(hapd_iface->bss);
+ os_free(hapd_iface);
+ }
+ return NULL;
+}
+
+
+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;
+
+ 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));
+ params.bssid = b;
+ params.ifname = hapd->conf->iface;
+ params.ssid = (const u8 *) hapd->conf->ssid.ssid;
+ params.ssid_len = hapd->conf->ssid.ssid_len;
+ params.test_socket = hapd->conf->test_socket;
+ params.use_pae_group_addr = hapd->conf->use_pae_group_addr;
+
+ params.num_bridge = hapd->iface->num_bss;
+ params.bridge = os_zalloc(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;
+ }
+
+ return 0;
+}
+
+
+static void hostapd_interface_deinit_free(struct hostapd_iface *iface)
+{
+ const struct wpa_driver_ops *driver;
+ void *drv_priv;
+ if (iface == NULL)
+ return;
+ driver = iface->bss[0]->driver;
+ drv_priv = iface->bss[0]->drv_priv;
+ hostapd_interface_deinit(iface);
+ if (driver && driver->hapd_deinit)
+ driver->hapd_deinit(drv_priv);
+ hostapd_interface_free(iface);
+}
+
+
+static struct hostapd_iface *
+hostapd_interface_init(struct hapd_interfaces *interfaces,
+ const char *config_fname, int debug)
+{
+ struct hostapd_iface *iface;
+ int k;
+
+ wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
+ iface = hostapd_init(config_fname);
+ if (!iface)
+ return NULL;
+ 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 (hostapd_driver_init(iface) ||
+ hostapd_setup_interface(iface)) {
+ 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)
+{
+#ifdef HOSTAPD_DUMP_STATE
+ struct hapd_interfaces *interfaces = signal_ctx;
+ hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL);
+#endif /* HOSTAPD_DUMP_STATE */
+}
+#endif /* CONFIG_NATIVE_WINDOWS */
+
+
+static int hostapd_global_init(struct hapd_interfaces *interfaces)
+{
+ 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;
+ }
+
+#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 */
+
+ return 0;
+}
+
+
+static void hostapd_global_deinit(const char *pid_file)
+{
+#ifdef EAP_SERVER_TNC
+ tncs_global_deinit();
+#endif /* EAP_SERVER_TNC */
+
+ 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 && os_daemonize(pid_file)) {
+ perror("daemon");
+ 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-2010, Jouni Malinen <j@w1.fi> "
+ "and contributors\n");
+}
+
+
+static void usage(void)
+{
+ show_version();
+ fprintf(stderr,
+ "\n"
+ "usage: hostapd [-hdBKtv] [-P <PID file>] "
+ "<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"
+ " -P PID file\n"
+ " -K include key data in debug messages\n"
+ " -t include timestamps in some debug messages\n"
+ " -v show hostapd version\n");
+
+ exit(1);
+}
+
+
+int main(int argc, char *argv[])
+{
+ struct hapd_interfaces interfaces;
+ int ret = 1;
+ size_t i;
+ int c, debug = 0, daemonize = 0;
+ char *pid_file = NULL;
+
+ if (os_program_init())
+ return -1;
+
+ for (;;) {
+ c = getopt(argc, argv, "BdhKP:tv");
+ 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 '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;
+ case 'v':
+ show_version();
+ exit(1);
+ break;
+
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (optind == argc)
+ usage();
+
+ interfaces.count = argc - optind;
+ interfaces.iface = os_malloc(interfaces.count *
+ sizeof(struct hostapd_iface *));
+ if (interfaces.iface == NULL) {
+ wpa_printf(MSG_ERROR, "malloc failed\n");
+ return -1;
+ }
+
+ if (hostapd_global_init(&interfaces))
+ return -1;
+
+ /* Initialize interfaces */
+ for (i = 0; i < interfaces.count; i++) {
+ interfaces.iface[i] = hostapd_interface_init(&interfaces,
+ argv[optind + i],
+ debug);
+ if (!interfaces.iface[i])
+ goto out;
+ }
+
+ if (hostapd_global_run(&interfaces, daemonize, pid_file))
+ goto out;
+
+ ret = 0;
+
+ out:
+ /* Deinitialize all interfaces */
+ for (i = 0; i < interfaces.count; i++)
+ hostapd_interface_deinit_free(interfaces.iface[i]);
+ os_free(interfaces.iface);
+
+ hostapd_global_deinit(pid_file);
+ os_free(pid_file);
+
+ os_program_deinit();
+
+ return ret;
+}
diff --git a/hostapd/nt_password_hash.c b/hostapd/nt_password_hash.c
new file mode 100644
index 000000000000..839802a744c5
--- /dev/null
+++ b/hostapd/nt_password_hash.c
@@ -0,0 +1,53 @@
+/*
+ * hostapd - Plaintext password to NtPasswordHash
+ * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING 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;
+}
diff --git a/hostapd/wired.conf b/hostapd/wired.conf
new file mode 100644
index 000000000000..956f8c53c540
--- /dev/null
+++ b/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